Revision: 22316
Author:   [email protected]
Date:     Thu Jul 10 10:54:47 2014 UTC
Log:      Support ES6 Map and Set in heap profiler

Added special handling for Map and Set in the heap snapshot generator.

Extracted common base type from JSMap/JSSet similar to JSWeakMap/JSWeakSet.

After handling collection specific properties all collections are processed as regular JSObject to make sure all regular properties set on them are present in the heap snapshot.

BUG=v8:3368
LOG=Y
[email protected], [email protected]

Committed: https://code.google.com/p/v8/source/detail?r=22311

Review URL: https://codereview.chromium.org/373183002
http://code.google.com/p/v8/source/detail?r=22316

Modified:
 /branches/bleeding_edge/src/heap-snapshot-generator.cc
 /branches/bleeding_edge/src/heap-snapshot-generator.h
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/test/cctest/test-heap-profiler.cc

=======================================
--- /branches/bleeding_edge/src/heap-snapshot-generator.cc Thu Jul 10 08:45:45 2014 UTC +++ /branches/bleeding_edge/src/heap-snapshot-generator.cc Thu Jul 10 10:54:47 2014 UTC
@@ -1097,11 +1097,16 @@
     ExtractJSGlobalProxyReferences(entry, JSGlobalProxy::cast(obj));
   } else if (obj->IsJSArrayBuffer()) {
     ExtractJSArrayBufferReferences(entry, JSArrayBuffer::cast(obj));
-  } else if (obj->IsJSWeakSet()) {
-    ExtractJSWeakCollectionReferences(entry, JSWeakSet::cast(obj));
-  } else if (obj->IsJSWeakMap()) {
-    ExtractJSWeakCollectionReferences(entry, JSWeakMap::cast(obj));
   } else if (obj->IsJSObject()) {
+    if (obj->IsJSWeakSet()) {
+      ExtractJSWeakCollectionReferences(entry, JSWeakSet::cast(obj));
+    } else if (obj->IsJSWeakMap()) {
+      ExtractJSWeakCollectionReferences(entry, JSWeakMap::cast(obj));
+    } else if (obj->IsJSSet()) {
+      ExtractJSCollectionReferences(entry, JSSet::cast(obj));
+    } else if (obj->IsJSMap()) {
+      ExtractJSCollectionReferences(entry, JSMap::cast(obj));
+    }
     ExtractJSObjectReferences(entry, JSObject::cast(obj));
   } else if (obj->IsString()) {
     ExtractStringReferences(entry, String::cast(obj));
@@ -1258,6 +1263,13 @@
                        "name", symbol->name(),
                        Symbol::kNameOffset);
 }
+
+
+void V8HeapExplorer::ExtractJSCollectionReferences(int entry,
+ JSCollection* collection) {
+  SetInternalReference(collection, entry, "table", collection->table(),
+                       JSCollection::kTableOffset);
+}


 void V8HeapExplorer::ExtractJSWeakCollectionReferences(
=======================================
--- /branches/bleeding_edge/src/heap-snapshot-generator.h Thu Jul 10 08:45:45 2014 UTC +++ /branches/bleeding_edge/src/heap-snapshot-generator.h Thu Jul 10 10:54:47 2014 UTC
@@ -370,6 +370,7 @@
   void ExtractJSObjectReferences(int entry, JSObject* js_obj);
   void ExtractStringReferences(int entry, String* obj);
   void ExtractSymbolReferences(int entry, Symbol* symbol);
+  void ExtractJSCollectionReferences(int entry, JSCollection* collection);
   void ExtractJSWeakCollectionReferences(int entry,
                                          JSWeakCollection* collection);
   void ExtractContextReferences(int entry, Context* context);
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Thu Jul 10 08:45:45 2014 UTC
+++ /branches/bleeding_edge/src/objects-inl.h   Thu Jul 10 10:54:47 2014 UTC
@@ -6032,8 +6032,7 @@
 }


-ACCESSORS(JSSet, table, Object, kTableOffset)
-ACCESSORS(JSMap, table, Object, kTableOffset)
+ACCESSORS(JSCollection, table, Object, kTableOffset)


 #define ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(name, type, offset)    \
=======================================
--- /branches/bleeding_edge/src/objects.h       Thu Jul 10 08:45:45 2014 UTC
+++ /branches/bleeding_edge/src/objects.h       Thu Jul 10 10:54:47 2014 UTC
@@ -44,8 +44,9 @@
 //         - JSArrayBufferView
 //           - JSTypedArray
 //           - JSDataView
-//         - JSSet
-//         - JSMap
+//         - JSCollection
+//           - JSSet
+//           - JSMap
 //         - JSSetIterator
 //         - JSMapIterator
 //         - JSWeakCollection
@@ -10078,41 +10079,42 @@
 };


-// The JSSet describes EcmaScript Harmony sets
-class JSSet: public JSObject {
+class JSCollection : public JSObject {
  public:
-  // [set]: the backing hash set containing keys.
+  // [table]: the backing hash table
   DECL_ACCESSORS(table, Object)

+  static const int kTableOffset = JSObject::kHeaderSize;
+  static const int kSize = kTableOffset + kPointerSize;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(JSCollection);
+};
+
+
+// The JSSet describes EcmaScript Harmony sets
+class JSSet : public JSCollection {
+ public:
   DECLARE_CAST(JSSet)

   // Dispatched behavior.
   DECLARE_PRINTER(JSSet)
   DECLARE_VERIFIER(JSSet)

-  static const int kTableOffset = JSObject::kHeaderSize;
-  static const int kSize = kTableOffset + kPointerSize;
-
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSSet);
 };


 // The JSMap describes EcmaScript Harmony maps
-class JSMap: public JSObject {
+class JSMap : public JSCollection {
  public:
-  // [table]: the backing hash table mapping keys to values.
-  DECL_ACCESSORS(table, Object)
-
   DECLARE_CAST(JSMap)

   // Dispatched behavior.
   DECLARE_PRINTER(JSMap)
   DECLARE_VERIFIER(JSMap)

-  static const int kTableOffset = JSObject::kHeaderSize;
-  static const int kSize = kTableOffset + kPointerSize;
-
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSMap);
 };
=======================================
--- /branches/bleeding_edge/test/cctest/test-heap-profiler.cc Thu Jul 10 08:45:45 2014 UTC +++ /branches/bleeding_edge/test/cctest/test-heap-profiler.cc Thu Jul 10 10:54:47 2014 UTC
@@ -502,9 +502,10 @@
   v8::HandleScope scope(env->GetIsolate());
   v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();

-  CompileRun("k = {}; v = {};\n"
-             "ws = new WeakSet(); ws.add(k); ws.add(v);\n"
-             "wm = new WeakMap(); wm.set(k, v);\n");
+  CompileRun(
+      "k = {}; v = {}; s = 'str';\n"
+      "ws = new WeakSet(); ws.add(k); ws.add(v); ws[s] = s;\n"
+      "wm = new WeakMap(); wm.set(k, v); wm[s] = s;\n");
   const v8::HeapSnapshot* snapshot =
       heap_profiler->TakeHeapSnapshot(v8_str("WeakCollections"));
   CHECK(ValidateSnapshot(snapshot));
@@ -515,6 +516,9 @@
   const v8::HeapGraphNode* v =
       GetProperty(global, v8::HeapGraphEdge::kProperty, "v");
   CHECK_NE(NULL, v);
+  const v8::HeapGraphNode* s =
+      GetProperty(global, v8::HeapGraphEdge::kProperty, "s");
+  CHECK_NE(NULL, s);

   const v8::HeapGraphNode* ws =
       GetProperty(global, v8::HeapGraphEdge::kProperty, "ws");
@@ -535,6 +539,10 @@
     }
   }
   CHECK_EQ(1, weak_entries);
+  const v8::HeapGraphNode* ws_s =
+      GetProperty(ws, v8::HeapGraphEdge::kProperty, "str");
+  CHECK_NE(NULL, ws_s);
+  CHECK_EQ(static_cast<int>(s->GetId()), static_cast<int>(ws_s->GetId()));

   const v8::HeapGraphNode* wm =
       GetProperty(global, v8::HeapGraphEdge::kProperty, "wm");
@@ -556,6 +564,85 @@
     }
   }
   CHECK_EQ(2, weak_entries);
+  const v8::HeapGraphNode* wm_s =
+      GetProperty(wm, v8::HeapGraphEdge::kProperty, "str");
+  CHECK_NE(NULL, wm_s);
+  CHECK_EQ(static_cast<int>(s->GetId()), static_cast<int>(wm_s->GetId()));
+}
+
+
+TEST(HeapSnapshotCollection) {
+  i::FLAG_harmony_collections = true;
+
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
+
+  CompileRun(
+      "k = {}; v = {}; s = 'str';\n"
+      "set = new Set(); set.add(k); set.add(v); set[s] = s;\n"
+      "map = new Map(); map.set(k, v); map[s] = s;\n");
+  const v8::HeapSnapshot* snapshot =
+      heap_profiler->TakeHeapSnapshot(v8_str("Collections"));
+  CHECK(ValidateSnapshot(snapshot));
+  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
+  const v8::HeapGraphNode* k =
+      GetProperty(global, v8::HeapGraphEdge::kProperty, "k");
+  CHECK_NE(NULL, k);
+  const v8::HeapGraphNode* v =
+      GetProperty(global, v8::HeapGraphEdge::kProperty, "v");
+  CHECK_NE(NULL, v);
+  const v8::HeapGraphNode* s =
+      GetProperty(global, v8::HeapGraphEdge::kProperty, "s");
+  CHECK_NE(NULL, s);
+
+  const v8::HeapGraphNode* set =
+      GetProperty(global, v8::HeapGraphEdge::kProperty, "set");
+  CHECK_NE(NULL, set);
+  CHECK_EQ(v8::HeapGraphNode::kObject, set->GetType());
+  CHECK_EQ(v8_str("Set"), set->GetName());
+
+  const v8::HeapGraphNode* set_table =
+      GetProperty(set, v8::HeapGraphEdge::kInternal, "table");
+  CHECK_EQ(v8::HeapGraphNode::kArray, set_table->GetType());
+  CHECK_GT(set_table->GetChildrenCount(), 0);
+  int entries = 0;
+  for (int i = 0, count = set_table->GetChildrenCount(); i < count; ++i) {
+    const v8::HeapGraphEdge* prop = set_table->GetChild(i);
+    const v8::SnapshotObjectId to_node_id = prop->GetToNode()->GetId();
+    if (to_node_id == k->GetId() || to_node_id == v->GetId()) {
+      ++entries;
+    }
+  }
+  CHECK_EQ(2, entries);
+  const v8::HeapGraphNode* set_s =
+      GetProperty(set, v8::HeapGraphEdge::kProperty, "str");
+  CHECK_NE(NULL, set_s);
+  CHECK_EQ(static_cast<int>(s->GetId()), static_cast<int>(set_s->GetId()));
+
+  const v8::HeapGraphNode* map =
+      GetProperty(global, v8::HeapGraphEdge::kProperty, "map");
+  CHECK_NE(NULL, map);
+  CHECK_EQ(v8::HeapGraphNode::kObject, map->GetType());
+  CHECK_EQ(v8_str("Map"), map->GetName());
+
+  const v8::HeapGraphNode* map_table =
+      GetProperty(map, v8::HeapGraphEdge::kInternal, "table");
+  CHECK_EQ(v8::HeapGraphNode::kArray, map_table->GetType());
+  CHECK_GT(map_table->GetChildrenCount(), 0);
+  entries = 0;
+  for (int i = 0, count = map_table->GetChildrenCount(); i < count; ++i) {
+    const v8::HeapGraphEdge* prop = map_table->GetChild(i);
+    const v8::SnapshotObjectId to_node_id = prop->GetToNode()->GetId();
+    if (to_node_id == k->GetId() || to_node_id == v->GetId()) {
+      ++entries;
+    }
+  }
+  CHECK_EQ(2, entries);
+  const v8::HeapGraphNode* map_s =
+      GetProperty(map, v8::HeapGraphEdge::kProperty, "str");
+  CHECK_NE(NULL, map_s);
+  CHECK_EQ(static_cast<int>(s->GetId()), static_cast<int>(map_s->GetId()));
 }


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to