New GC related APIs: Implicit references.
authormstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 16 Apr 2013 12:57:01 +0000 (12:57 +0000)
committermstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 16 Apr 2013 12:57:01 +0000 (12:57 +0000)
When using these APIs, the embedder doesn't need to copy Persistent handles around.

BUG=NONE

Review URL: https://codereview.chromium.org/14175005

Patch from Marja Hölttä <marja@chromium.org>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14283 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

include/v8.h
src/api.cc
src/global-handles.cc
src/global-handles.h
src/heap-snapshot-generator.cc
src/mark-compact.cc
test/cctest/test-api.cc
test/cctest/test-heap-profiler.cc
test/cctest/test-mark-compact.cc

index 38312e9..b40a4bf 100644 (file)
@@ -3555,17 +3555,39 @@ class V8EXPORT V8 {
                                     RetainedObjectInfo* info);
 
   /**
+   * Sets a representative object to a group. Used in conjunction with implicit
+   * references: If you're going to use AddImplicitReference with the group, you
+   * need to set a representative object too.
+   */
+  static void SetObjectGroupRepresentative(Isolate* isolate,
+                                           UniqueId id,
+                                           const Persistent<Object>& object);
+
+  /**
    * Allows the host application to declare implicit references between
    * the objects: if |parent| is alive, all |children| are alive too.
    * After each garbage collection, all implicit references
    * are removed.  It is intended to be used in the before-garbage-collection
    * callback function.
    */
+  // TODO(marja): Deprecate AddImplicitReferences. Use
+  // SetObjectGroupRepresentativeObject and AddImplicitReference instead.
   static void AddImplicitReferences(Persistent<Object> parent,
                                     Persistent<Value>* children,
                                     size_t length);
 
   /**
+   * Allows the host application to declare implicit references. If the
+   * representative object of the object group (identified by id) is alive, the
+   * children are alive too. After each garbage collection, all implicit
+   * references are removed. It is intended to be used in the
+   * before-garbage-collection callback function.
+   */
+  static void AddImplicitReference(Isolate* isolate,
+                                   UniqueId id,
+                                   const Persistent<Value>& object);
+
+  /**
    * Initializes from snapshot if possible. Otherwise, attempts to
    * initialize from scratch.  This function is called implicitly if
    * you use the API without calling it first.
index 077fff5..a9e01e0 100644 (file)
@@ -5942,6 +5942,17 @@ void V8::SetRetainedObjectInfo(Isolate* exported_isolate,
 }
 
 
+void V8::SetObjectGroupRepresentative(
+      Isolate* exported_isolate,
+      UniqueId id,
+      const Persistent<Object>& object) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(exported_isolate);
+  isolate->global_handles()->SetObjectGroupRepresentative(
+      id,
+      i::Handle<i::HeapObject>::cast(Utils::OpenHandle(*object)).location());
+}
+
+
 void V8::AddImplicitReferences(Persistent<Object> parent,
                                Persistent<Value>* children,
                                size_t length) {
@@ -5954,6 +5965,15 @@ void V8::AddImplicitReferences(Persistent<Object> parent,
 }
 
 
+void V8::AddImplicitReference(Isolate* exported_isolate,
+                              UniqueId id,
+                              const Persistent<Value>& object) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(exported_isolate);
+  isolate->global_handles()
+      ->AddImplicitReference(id, reinterpret_cast<i::Object**>(*object));
+}
+
+
 intptr_t Isolate::AdjustAmountOfExternalAllocatedMemory(
     intptr_t change_in_bytes) {
   i::Heap* heap = reinterpret_cast<i::Isolate*>(this)->heap();
index 8058f35..a3e7f1e 100644 (file)
@@ -855,8 +855,18 @@ void GlobalHandles::AddObjectGroup(Object*** handles,
     object_groups_.Add(ObjectGroupConnection(
         UniqueId(reinterpret_cast<intptr_t>(handles[0])), handles[i]));
   }
-  retainer_infos_.Add(ObjectGroupRetainerInfo(
-      UniqueId(reinterpret_cast<intptr_t>(handles[0])), info));
+  for (size_t i = 0; i < length; ++i) {
+    if ((*handles[i])->IsHeapObject()) {
+      representative_objects_.Add(ObjectGroupRepresentative(
+          UniqueId(reinterpret_cast<intptr_t>(handles[0])),
+          reinterpret_cast<HeapObject**>(handles[i])));
+      break;
+    }
+  }
+  if (info != NULL) {
+    retainer_infos_.Add(ObjectGroupRetainerInfo(
+        UniqueId(reinterpret_cast<intptr_t>(handles[0])), info));
+  }
 }
 
 void GlobalHandles::SetObjectGroupId(Object** handle,
@@ -871,6 +881,13 @@ void GlobalHandles::SetRetainedObjectInfo(UniqueId id,
 }
 
 
+void GlobalHandles::SetObjectGroupRepresentative(
+    UniqueId id,
+    HeapObject** representative_object) {
+  representative_objects_.Add(
+      ObjectGroupRepresentative(id, representative_object));
+}
+
 void GlobalHandles::AddImplicitReferences(HeapObject** parent,
                                           Object*** children,
                                           size_t length) {
@@ -880,8 +897,16 @@ void GlobalHandles::AddImplicitReferences(HeapObject** parent,
     ASSERT(!Node::FromLocation(children[i])->is_independent());
   }
 #endif
-  if (length == 0) return;
-  implicit_ref_groups_.Add(ImplicitRefGroup::New(parent, children, length));
+  for (size_t i = 0; i < length; ++i) {
+    implicit_ref_groups_.Add(ObjectGroupConnection(
+        UniqueId(reinterpret_cast<intptr_t>(parent)), children[i]));
+  }
+}
+
+
+void GlobalHandles::AddImplicitReference(UniqueId id, Object** child) {
+  ASSERT(!Node::FromLocation(child)->is_independent());
+  implicit_ref_groups_.Add(ObjectGroupConnection(id, child));
 }
 
 
@@ -896,9 +921,7 @@ void GlobalHandles::RemoveObjectGroups() {
 
 
 void GlobalHandles::RemoveImplicitRefGroups() {
-  for (int i = 0; i < implicit_ref_groups_.length(); i++) {
-    implicit_ref_groups_.at(i)->Dispose();
-  }
+  representative_objects_.Clear();
   implicit_ref_groups_.Clear();
 }
 
index de93410..7697364 100644 (file)
@@ -47,10 +47,16 @@ class ObjectVisitor;
 // At GC the destroyed global handles are removed from the free list
 // and deallocated.
 
+// Data structures for tracking object groups and implicit references.
+
 // An object group is treated like a single JS object: if one of object in
 // the group is alive, all objects in the same group are considered alive.
 // An object group is used to simulate object relationship in a DOM tree.
 
+// An implicit references group consists of two parts: a parent object and a
+// list of children objects.  If the parent is alive, all the children are alive
+// too.
+
 struct ObjectGroupConnection {
   ObjectGroupConnection(UniqueId id, Object** object)
       : id(id), object(object) {}
@@ -85,36 +91,20 @@ struct ObjectGroupRetainerInfo {
 };
 
 
-// An implicit references group consists of two parts: a parent object and
-// a list of children objects.  If the parent is alive, all the children
-// are alive too.
-class ImplicitRefGroup {
- public:
-  static ImplicitRefGroup* New(HeapObject** parent,
-                               Object*** children,
-                               size_t length) {
-    ASSERT(length > 0);
-    ImplicitRefGroup* group = reinterpret_cast<ImplicitRefGroup*>(
-        malloc(OFFSET_OF(ImplicitRefGroup, children_[length])));
-    group->parent_ = parent;
-    group->length_ = length;
-    CopyWords(group->children_, children, length);
-    return group;
-  }
+struct ObjectGroupRepresentative {
+  ObjectGroupRepresentative(UniqueId id, HeapObject** object)
+      : id(id), object(object) {}
 
-  void Dispose() {
-    free(this);
+  bool operator==(const ObjectGroupRepresentative& other) const {
+    return id == other.id;
   }
 
-  HeapObject** parent_;
-  size_t length_;
-  Object** children_[1];  // Variable sized array.
+  bool operator<(const ObjectGroupRepresentative& other) const {
+    return id < other.id;
+  }
 
- private:
-  void* operator new(size_t size);
-  void operator delete(void* p);
-  ~ImplicitRefGroup();
-  DISALLOW_IMPLICIT_CONSTRUCTORS(ImplicitRefGroup);
+  UniqueId id;
+  HeapObject** object;
 };
 
 
@@ -228,7 +218,16 @@ class GlobalHandles {
   // All groups are destroyed after a garbage collection.
   void SetObjectGroupId(Object** handle, UniqueId id);
 
-  void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info = NULL);
+  // Set RetainedObjectInfo for an object group. Should not be called more than
+  // once for a group. Should not be called for a group which contains no
+  // handles.
+  void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
+
+  // Sets a representative object for an object group. Should not be called more
+  // than once for a group. Should not be called for a group which contains no
+  // handles.
+  void SetObjectGroupRepresentative(UniqueId id,
+                                    HeapObject** representative_object);
 
   // Add an implicit references' group.
   // Should be only used in GC callback function before a collection.
@@ -237,6 +236,12 @@ class GlobalHandles {
                              Object*** children,
                              size_t length);
 
+  // Adds an implicit reference from a group (representative object of that
+  // group) to an object. Should be only used in GC callback function before a
+  // collection. All implicit references are destroyed after a mark-compact
+  // collection.
+  void AddImplicitReference(UniqueId id, Object** child);
+
   List<ObjectGroupConnection>* object_groups() {
     return &object_groups_;
   }
@@ -245,11 +250,14 @@ class GlobalHandles {
     return &retainer_infos_;
   }
 
-  // Returns the implicit references' groups.
-  List<ImplicitRefGroup*>* implicit_ref_groups() {
+  List<ObjectGroupConnection>* implicit_ref_groups() {
     return &implicit_ref_groups_;
   }
 
+  List<ObjectGroupRepresentative>* representative_objects() {
+    return &representative_objects_;
+  }
+
   // Remove bags, this should only happen after GC.
   void RemoveObjectGroups();
   void RemoveImplicitRefGroups();
@@ -292,9 +300,13 @@ class GlobalHandles {
 
   int post_gc_processing_count_;
 
+  // Object groups.
   List<ObjectGroupConnection> object_groups_;
   List<ObjectGroupRetainerInfo> retainer_infos_;
-  List<ImplicitRefGroup*> implicit_ref_groups_;
+  List<ObjectGroupRepresentative> representative_objects_;
+
+  // Implicit references.
+  List<ObjectGroupConnection> implicit_ref_groups_;
 
   friend class Isolate;
 
index 4588094..f167886 100644 (file)
@@ -1988,24 +1988,61 @@ void NativeObjectsExplorer::FillRetainedObjects() {
 
 void NativeObjectsExplorer::FillImplicitReferences() {
   Isolate* isolate = Isolate::Current();
-  List<ImplicitRefGroup*>* groups =
+  List<ObjectGroupConnection>* ref_groups =
       isolate->global_handles()->implicit_ref_groups();
-  for (int i = 0; i < groups->length(); ++i) {
-    ImplicitRefGroup* group = groups->at(i);
-    HeapObject* parent = *group->parent_;
-    int parent_entry =
-        filler_->FindOrAddEntry(parent, native_entries_allocator_)->index();
-    ASSERT(parent_entry != HeapEntry::kNoEntry);
-    Object*** children = group->children_;
-    for (size_t j = 0; j < group->length_; ++j) {
-      Object* child = *children[j];
-      HeapEntry* child_entry =
-          filler_->FindOrAddEntry(child, native_entries_allocator_);
-      filler_->SetNamedReference(
-          HeapGraphEdge::kInternal,
-          parent_entry,
-          "native",
-          child_entry);
+  List<ObjectGroupRepresentative>* representative_objects =
+      isolate->global_handles()->representative_objects();
+
+  if (ref_groups->length() == 0)
+    return;
+
+  ref_groups->Sort();
+  representative_objects->Sort();
+
+  int representative_objects_index = 0;
+  UniqueId current_group_id(0);
+  size_t current_group_start = 0;
+  for (int i = 0; i <= ref_groups->length(); ++i) {
+    if (i == 0)
+      current_group_id = ref_groups->at(i).id;
+    if (i == ref_groups->length() || current_group_id != ref_groups->at(i).id) {
+      // Group detected: objects in indices [current_group_start, i[.
+
+      // Find the representative object for this group.
+      while (representative_objects_index < representative_objects->length() &&
+             representative_objects->at(representative_objects_index).id <
+             current_group_id)
+        ++representative_objects_index;
+
+      if (representative_objects_index < representative_objects->length() &&
+          representative_objects->at(representative_objects_index).id ==
+              current_group_id) {
+        HeapObject* parent =
+            *(representative_objects->at(representative_objects_index).object);
+
+        int parent_entry =
+            filler_->FindOrAddEntry(parent, native_entries_allocator_)->index();
+        ASSERT(parent_entry != HeapEntry::kNoEntry);
+
+        for (int j = current_group_start; j < i; ++j) {
+          Object* child = *(ref_groups->at(j).object);
+          HeapEntry* child_entry =
+              filler_->FindOrAddEntry(child, native_entries_allocator_);
+          filler_->SetNamedReference(
+              HeapGraphEdge::kInternal,
+              parent_entry,
+              "native",
+              child_entry);
+        }
+      } else {
+        // This should not happen: representative object for a group was not
+        // set!
+        UNREACHABLE();
+      }
+      if (i < ref_groups->length()) {
+        current_group_id = ref_groups->at(i).id;
+        current_group_start = i;
+      }
     }
   }
   isolate->global_handles()->RemoveImplicitRefGroups();
index f49179f..721ce92 100644 (file)
@@ -1931,34 +1931,72 @@ void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) {
 
 
 void MarkCompactCollector::MarkImplicitRefGroups() {
-  List<ImplicitRefGroup*>* ref_groups =
-      isolate()->global_handles()->implicit_ref_groups();
-
-  int last = 0;
-  for (int i = 0; i < ref_groups->length(); i++) {
-    ImplicitRefGroup* entry = ref_groups->at(i);
-    ASSERT(entry != NULL);
-
-    if (!IsMarked(*entry->parent_)) {
-      (*ref_groups)[last++] = entry;
-      continue;
-    }
-
-    Object*** children = entry->children_;
-    // A parent object is marked, so mark all child heap objects.
-    for (size_t j = 0; j < entry->length_; ++j) {
-      if ((*children[j])->IsHeapObject()) {
-        HeapObject* child = HeapObject::cast(*children[j]);
-        MarkBit mark = Marking::MarkBitFrom(child);
-        MarkObject(child, mark);
+  Isolate* isolate = Isolate::Current();
+  List<ObjectGroupConnection>* ref_groups =
+      isolate->global_handles()->implicit_ref_groups();
+  List<ObjectGroupRepresentative>* representative_objects =
+      isolate->global_handles()->representative_objects();
+
+  if (ref_groups->length() == 0)
+    return;
+
+  ref_groups->Sort();
+  representative_objects->Sort();
+
+  int surviving_ref_group_index = 0;
+  int surviving_representative_object_index = 0;
+
+  int representative_objects_index = 0;
+  UniqueId current_group_id(0);
+  size_t current_group_start = 0;
+  for (int i = 0; i <= ref_groups->length(); ++i) {
+    if (i == 0)
+      current_group_id = ref_groups->at(i).id;
+    if (i == ref_groups->length() || current_group_id != ref_groups->at(i).id) {
+      // Group detected: objects in indices [current_group_start, i[.
+
+      // Find the representative object for this group.
+      while (representative_objects_index < representative_objects->length() &&
+             representative_objects->at(representative_objects_index).id <
+             current_group_id)
+        ++representative_objects_index;
+
+      if (representative_objects_index < representative_objects->length() &&
+          representative_objects->at(representative_objects_index).id ==
+              current_group_id) {
+        HeapObject* parent =
+            *(representative_objects->at(representative_objects_index).object);
+
+        if (!IsMarked(parent)) {
+          // Nothing tbd, copy the reference group so that it can be iterated
+          // during the next call.
+          for (int j = current_group_start; j < i; ++j)
+            ref_groups->at(surviving_ref_group_index++) = ref_groups->at(j);
+          representative_objects->at(surviving_representative_object_index++) =
+              representative_objects->at(representative_objects_index);
+        } else {
+          // A parent object is marked, so mark all child heap objects.
+          for (int j = current_group_start; j < i; ++j) {
+            if ((*ref_groups->at(j).object)->IsHeapObject()) {
+              HeapObject* child = HeapObject::cast(*ref_groups->at(j).object);
+              MarkBit mark = Marking::MarkBitFrom(child);
+              MarkObject(child, mark);
+            }
+          }
+        }
+      } else {
+        // This should not happen: representative object for a group was not
+        // set!
+        UNREACHABLE();
+      }
+      if (i < ref_groups->length()) {
+        current_group_id = ref_groups->at(i).id;
+        current_group_start = i;
       }
     }
-
-    // Once the entire group has been marked, dispose it because it's
-    // not needed anymore.
-    entry->Dispose();
   }
-  ref_groups->Rewind(last);
+  ref_groups->Rewind(surviving_ref_group_index);
+  representative_objects->Rewind(surviving_representative_object_index);
 }
 
 
index d75d5c2..e4f523e 100644 (file)
@@ -2491,7 +2491,7 @@ THREADED_TEST(OldApiObjectGroups) {
     V8::AddObjectGroup(g1_objects, 2);
     V8::AddImplicitReferences(g1s1, g1_children, 1);
     V8::AddObjectGroup(g2_objects, 2);
-    V8::AddImplicitReferences(g2s2, g2_children, 1);
+    V8::AddImplicitReferences(g2s1, g2_children, 1);
   }
   // Do a single full GC, ensure incremental marking is stopped.
   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
@@ -2515,7 +2515,7 @@ THREADED_TEST(OldApiObjectGroups) {
     V8::AddObjectGroup(g1_objects, 2);
     V8::AddImplicitReferences(g1s1, g1_children, 1);
     V8::AddObjectGroup(g2_objects, 2);
-    V8::AddImplicitReferences(g2s2, g2_children, 1);
+    V8::AddImplicitReferences(g2s1, g2_children, 1);
   }
 
   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
@@ -2570,14 +2570,16 @@ THREADED_TEST(ApiObjectGroups) {
   CHECK(g2s1->Set(0, g1s1));
 
   {
-    Persistent<Value> g1_children[] = { g1c1 };
-    Persistent<Value> g2_children[] = { g2c1 };
-    V8::SetObjectGroupId(iso, g1s1, UniqueId(1));
-    V8::SetObjectGroupId(iso, g1s2, UniqueId(1));
-    V8::AddImplicitReferences(g1s1, g1_children, 1);
-    V8::SetObjectGroupId(iso, g2s1, UniqueId(2));
-    V8::SetObjectGroupId(iso, g2s2, UniqueId(2));
-    V8::AddImplicitReferences(g2s2, g2_children, 1);
+    UniqueId id1(reinterpret_cast<intptr_t>(*g1s1));
+    UniqueId id2(reinterpret_cast<intptr_t>(*g2s2));
+    V8::SetObjectGroupId(iso, g1s1, id1);
+    V8::SetObjectGroupId(iso, g1s2, id1);
+    V8::SetObjectGroupRepresentative(iso, id1, g1s1);
+    V8::AddImplicitReference(iso, id1, g1c1);
+    V8::SetObjectGroupId(iso, g2s1, id2);
+    V8::SetObjectGroupId(iso, g2s2, id2);
+    V8::SetObjectGroupRepresentative(iso, id2, g2s1);
+    V8::AddImplicitReference(iso, id2, g2c1);
   }
   // Do a single full GC, ensure incremental marking is stopped.
   v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
@@ -2596,14 +2598,16 @@ THREADED_TEST(ApiObjectGroups) {
 
   // Groups are deleted, rebuild groups.
   {
-    Persistent<Value> g1_children[] = { g1c1 };
-    Persistent<Value> g2_children[] = { g2c1 };
-    V8::SetObjectGroupId(iso, g1s1, UniqueId(1));
-    V8::SetObjectGroupId(iso, g1s2, UniqueId(1));
-    V8::AddImplicitReferences(g1s1, g1_children, 1);
-    V8::SetObjectGroupId(iso, g2s1, UniqueId(2));
-    V8::SetObjectGroupId(iso, g2s2, UniqueId(2));
-    V8::AddImplicitReferences(g2s2, g2_children, 1);
+    UniqueId id1(reinterpret_cast<intptr_t>(*g1s1));
+    UniqueId id2(reinterpret_cast<intptr_t>(*g2s2));
+    V8::SetObjectGroupId(iso, g1s1, id1);
+    V8::SetObjectGroupId(iso, g1s2, id1);
+    V8::SetObjectGroupRepresentative(iso, id1, g1s1);
+    V8::AddImplicitReference(iso, id1, g1c1);
+    V8::SetObjectGroupId(iso, g2s1, id2);
+    V8::SetObjectGroupId(iso, g2s2, id2);
+    V8::SetObjectGroupRepresentative(iso, id2, g2s1);
+    V8::AddImplicitReference(iso, id2, g2c1);
   }
 
   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
@@ -2779,22 +2783,26 @@ THREADED_TEST(ApiObjectGroupsCycle) {
   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
   // groups.
   {
-    Persistent<Value> g1_children[] = { g2s1 };
-    Persistent<Value> g2_children[] = { g3s1 };
-    Persistent<Value> g3_children[] = { g4s1 };
-    Persistent<Value> g4_children[] = { g1s1 };
-    V8::SetObjectGroupId(iso, g1s1, UniqueId(1));
-    V8::SetObjectGroupId(iso, g1s2, UniqueId(1));
-    V8::AddImplicitReferences(g1s1, g1_children, 1);
-    V8::SetObjectGroupId(iso, g2s1, UniqueId(2));
-    V8::SetObjectGroupId(iso, g2s2, UniqueId(2));
-    V8::AddImplicitReferences(g2s1, g2_children, 1);
-    V8::SetObjectGroupId(iso, g3s1, UniqueId(3));
-    V8::SetObjectGroupId(iso, g3s2, UniqueId(3));
-    V8::AddImplicitReferences(g3s1, g3_children, 1);
-    V8::SetObjectGroupId(iso, g4s1, UniqueId(4));
-    V8::SetObjectGroupId(iso, g4s2, UniqueId(4));
-    V8::AddImplicitReferences(g4s1, g4_children, 1);
+    UniqueId id1(reinterpret_cast<intptr_t>(*g1s1));
+    UniqueId id2(reinterpret_cast<intptr_t>(*g2s1));
+    UniqueId id3(reinterpret_cast<intptr_t>(*g3s1));
+    UniqueId id4(reinterpret_cast<intptr_t>(*g4s1));
+    V8::SetObjectGroupId(iso, g1s1, id1);
+    V8::SetObjectGroupId(iso, g1s2, id1);
+    V8::SetObjectGroupRepresentative(iso, id1, g1s1);
+    V8::AddImplicitReference(iso, id1, g2s1);
+    V8::SetObjectGroupId(iso, g2s1, id2);
+    V8::SetObjectGroupId(iso, g2s2, id2);
+    V8::SetObjectGroupRepresentative(iso, id2, g2s1);
+    V8::AddImplicitReference(iso, id2, g3s1);
+    V8::SetObjectGroupId(iso, g3s1, id3);
+    V8::SetObjectGroupId(iso, g3s2, id3);
+    V8::SetObjectGroupRepresentative(iso, id3, g3s1);
+    V8::AddImplicitReference(iso, id3, g4s1);
+    V8::SetObjectGroupId(iso, g4s1, id4);
+    V8::SetObjectGroupId(iso, g4s2, id4);
+    V8::SetObjectGroupRepresentative(iso, id4, g4s1);
+    V8::AddImplicitReference(iso, id4, g1s1);
   }
   // Do a single full GC
   v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
@@ -2809,22 +2817,26 @@ THREADED_TEST(ApiObjectGroupsCycle) {
 
   // Groups are deleted, rebuild groups.
   {
-    Persistent<Value> g1_children[] = { g2s1 };
-    Persistent<Value> g2_children[] = { g3s1 };
-    Persistent<Value> g3_children[] = { g4s1 };
-    Persistent<Value> g4_children[] = { g1s1 };
-    V8::SetObjectGroupId(iso, g1s1, UniqueId(1));
-    V8::SetObjectGroupId(iso, g1s2, UniqueId(1));
-    V8::AddImplicitReferences(g1s1, g1_children, 1);
-    V8::SetObjectGroupId(iso, g2s1, UniqueId(2));
-    V8::SetObjectGroupId(iso, g2s2, UniqueId(2));
-    V8::AddImplicitReferences(g2s1, g2_children, 1);
-    V8::SetObjectGroupId(iso, g3s1, UniqueId(3));
-    V8::SetObjectGroupId(iso, g3s2, UniqueId(3));
-    V8::AddImplicitReferences(g3s1, g3_children, 1);
-    V8::SetObjectGroupId(iso, g4s1, UniqueId(4));
-    V8::SetObjectGroupId(iso, g4s2, UniqueId(4));
-    V8::AddImplicitReferences(g4s1, g4_children, 1);
+    UniqueId id1(reinterpret_cast<intptr_t>(*g1s1));
+    UniqueId id2(reinterpret_cast<intptr_t>(*g2s1));
+    UniqueId id3(reinterpret_cast<intptr_t>(*g3s1));
+    UniqueId id4(reinterpret_cast<intptr_t>(*g4s1));
+    V8::SetObjectGroupId(iso, g1s1, id1);
+    V8::SetObjectGroupId(iso, g1s2, id1);
+    V8::SetObjectGroupRepresentative(iso, id1, g1s1);
+    V8::AddImplicitReference(iso, id1, g2s1);
+    V8::SetObjectGroupId(iso, g2s1, id2);
+    V8::SetObjectGroupId(iso, g2s2, id2);
+    V8::SetObjectGroupRepresentative(iso, id2, g2s1);
+    V8::AddImplicitReference(iso, id2, g3s1);
+    V8::SetObjectGroupId(iso, g3s1, id3);
+    V8::SetObjectGroupId(iso, g3s2, id3);
+    V8::SetObjectGroupRepresentative(iso, id3, g3s1);
+    V8::AddImplicitReference(iso, id3, g4s1);
+    V8::SetObjectGroupId(iso, g4s1, id4);
+    V8::SetObjectGroupId(iso, g4s2, id4);
+    V8::SetObjectGroupRepresentative(iso, id4, g4s1);
+    V8::AddImplicitReference(iso, id4, g1s1);
   }
 
   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
index 59e7b8f..ff2838c 100644 (file)
@@ -1191,9 +1191,10 @@ class GraphWithImplicitRefs {
   explicit GraphWithImplicitRefs(LocalContext* env) {
     CHECK_EQ(NULL, instance_);
     instance_ = this;
-    v8::Isolate* isolate = (*env)->GetIsolate();
+    isolate_ = (*env)->GetIsolate();
     for (int i = 0; i < kObjectsCount; i++) {
-      objects_[i] = v8::Persistent<v8::Object>::New(isolate, v8::Object::New());
+      objects_[i] =
+          v8::Persistent<v8::Object>::New(isolate_, v8::Object::New());
     }
     (*env)->Global()->Set(v8_str("root_object"), objects_[0]);
   }
@@ -1208,15 +1209,35 @@ class GraphWithImplicitRefs {
  private:
   void AddImplicitReferences() {
     // 0 -> 1
-    v8::V8::AddImplicitReferences(
-        v8::Persistent<v8::Object>::Cast(objects_[0]), &objects_[1], 1);
+    v8::V8::SetObjectGroupId(isolate_,
+                             v8::Persistent<v8::Object>::Cast(objects_[0]),
+                             v8::UniqueId(1));
+    v8::V8::SetObjectGroupRepresentative(
+        isolate_,
+        v8::UniqueId(1),
+        v8::Persistent<v8::Object>::Cast(objects_[0]));
+    v8::V8::AddImplicitReference(isolate_,
+                                 v8::UniqueId(1),
+                                 v8::Persistent<v8::Object>::Cast(objects_[1]));
     // Adding two more references(note length=2 in params): 1 -> 2, 1 -> 3
-    v8::V8::AddImplicitReferences(
-        v8::Persistent<v8::Object>::Cast(objects_[1]), &objects_[2], 2);
+    v8::V8::SetObjectGroupId(isolate_,
+                             v8::Persistent<v8::Object>::Cast(objects_[1]),
+                             v8::UniqueId(2));
+    v8::V8::SetObjectGroupRepresentative(
+        isolate_,
+        v8::UniqueId(2),
+        v8::Persistent<v8::Object>::Cast(objects_[1]));
+    v8::V8::AddImplicitReference(isolate_,
+                                 v8::UniqueId(2),
+                                 v8::Persistent<v8::Object>::Cast(objects_[2]));
+    v8::V8::AddImplicitReference(isolate_,
+                                 v8::UniqueId(2),
+                                 v8::Persistent<v8::Object>::Cast(objects_[3]));
   }
 
   v8::Persistent<v8::Value> objects_[kObjectsCount];
   static GraphWithImplicitRefs* instance_;
+  v8::Isolate* isolate_;
 };
 
 GraphWithImplicitRefs* GraphWithImplicitRefs::instance_ = NULL;
index 5f01731..ee1481f 100644 (file)
@@ -370,7 +370,7 @@ TEST(ObjectGroupsOldApi) {
         Handle<HeapObject>::cast(g1s1).location(), g1_children, 1);
     global_handles->AddObjectGroup(g2_objects, 2, NULL);
     global_handles->AddImplicitReferences(
-        Handle<HeapObject>::cast(g2s2).location(), g2_children, 1);
+        Handle<HeapObject>::cast(g2s1).location(), g2_children, 1);
   }
   // Do a full GC
   HEAP->CollectGarbage(OLD_POINTER_SPACE);
@@ -399,7 +399,7 @@ TEST(ObjectGroupsOldApi) {
         Handle<HeapObject>::cast(g1s1).location(), g1_children, 1);
     global_handles->AddObjectGroup(g2_objects, 2, NULL);
     global_handles->AddImplicitReferences(
-        Handle<HeapObject>::cast(g2s2).location(), g2_children, 1);
+        Handle<HeapObject>::cast(g2s1).location(), g2_children, 1);
   }
 
   HEAP->CollectGarbage(OLD_POINTER_SPACE);
@@ -477,16 +477,16 @@ TEST(ObjectGroups) {
   Handle<FixedArray>::cast(g2s1)->set(0, *g1s1);
 
   {
-    Object** g1_children[] = { g1c1.location() };
-    Object** g2_children[] = { g2c1.location() };
     global_handles->SetObjectGroupId(g1s1.location(), v8::UniqueId(1));
     global_handles->SetObjectGroupId(g1s2.location(), v8::UniqueId(1));
-    global_handles->AddImplicitReferences(
-        Handle<HeapObject>::cast(g1s1).location(), g1_children, 1);
+    global_handles->SetObjectGroupRepresentative(
+        v8::UniqueId(1), reinterpret_cast<HeapObject**>(g1s1.location()));
+    global_handles->AddImplicitReference(v8::UniqueId(1), g1c1.location());
     global_handles->SetObjectGroupId(g2s1.location(), v8::UniqueId(2));
     global_handles->SetObjectGroupId(g2s2.location(), v8::UniqueId(2));
-    global_handles->AddImplicitReferences(
-        Handle<HeapObject>::cast(g2s2).location(), g2_children, 1);
+    global_handles->SetObjectGroupRepresentative(
+        v8::UniqueId(2), reinterpret_cast<HeapObject**>(g2s1.location()));
+    global_handles->AddImplicitReference(v8::UniqueId(2), g2c1.location());
   }
   // Do a full GC
   heap->CollectGarbage(OLD_POINTER_SPACE);
@@ -506,16 +506,16 @@ TEST(ObjectGroups) {
 
   // Groups are deleted, rebuild groups.
   {
-    Object** g1_children[] = { g1c1.location() };
-    Object** g2_children[] = { g2c1.location() };
     global_handles->SetObjectGroupId(g1s1.location(), v8::UniqueId(1));
     global_handles->SetObjectGroupId(g1s2.location(), v8::UniqueId(1));
-    global_handles->AddImplicitReferences(
-        Handle<HeapObject>::cast(g1s1).location(), g1_children, 1);
+    global_handles->SetObjectGroupRepresentative(
+        v8::UniqueId(1), reinterpret_cast<HeapObject**>(g1s1.location()));
+    global_handles->AddImplicitReference(v8::UniqueId(1), g1c1.location());
     global_handles->SetObjectGroupId(g2s1.location(), v8::UniqueId(2));
     global_handles->SetObjectGroupId(g2s2.location(), v8::UniqueId(2));
-    global_handles->AddImplicitReferences(
-        Handle<HeapObject>::cast(g2s2).location(), g2_children, 1);
+    global_handles->SetObjectGroupRepresentative(
+        v8::UniqueId(2), reinterpret_cast<HeapObject**>(g2s1.location()));
+    global_handles->AddImplicitReference(v8::UniqueId(2), g2c1.location());
   }
 
   heap->CollectGarbage(OLD_POINTER_SPACE);