From e8bc8d76ae8870306349793094c498ffc605d392 Mon Sep 17 00:00:00 2001 From: "mstarzinger@chromium.org" Date: Tue, 16 Apr 2013 12:57:01 +0000 Subject: [PATCH] New GC related APIs: Implicit references. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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ä . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14283 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- include/v8.h | 22 ++++++++ src/api.cc | 20 +++++++ src/global-handles.cc | 37 ++++++++++--- src/global-handles.h | 72 ++++++++++++++---------- src/heap-snapshot-generator.cc | 71 ++++++++++++++++++------ src/mark-compact.cc | 88 +++++++++++++++++++++--------- test/cctest/test-api.cc | 112 +++++++++++++++++++++----------------- test/cctest/test-heap-profiler.cc | 33 +++++++++-- test/cctest/test-mark-compact.cc | 28 +++++----- 9 files changed, 334 insertions(+), 149 deletions(-) diff --git a/include/v8.h b/include/v8.h index 38312e9..b40a4bf 100644 --- a/include/v8.h +++ b/include/v8.h @@ -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); + + /** * 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 parent, Persistent* 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& 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. diff --git a/src/api.cc b/src/api.cc index 077fff5..a9e01e0 100644 --- a/src/api.cc +++ b/src/api.cc @@ -5942,6 +5942,17 @@ void V8::SetRetainedObjectInfo(Isolate* exported_isolate, } +void V8::SetObjectGroupRepresentative( + Isolate* exported_isolate, + UniqueId id, + const Persistent& object) { + i::Isolate* isolate = reinterpret_cast(exported_isolate); + isolate->global_handles()->SetObjectGroupRepresentative( + id, + i::Handle::cast(Utils::OpenHandle(*object)).location()); +} + + void V8::AddImplicitReferences(Persistent parent, Persistent* children, size_t length) { @@ -5954,6 +5965,15 @@ void V8::AddImplicitReferences(Persistent parent, } +void V8::AddImplicitReference(Isolate* exported_isolate, + UniqueId id, + const Persistent& object) { + i::Isolate* isolate = reinterpret_cast(exported_isolate); + isolate->global_handles() + ->AddImplicitReference(id, reinterpret_cast(*object)); +} + + intptr_t Isolate::AdjustAmountOfExternalAllocatedMemory( intptr_t change_in_bytes) { i::Heap* heap = reinterpret_cast(this)->heap(); diff --git a/src/global-handles.cc b/src/global-handles.cc index 8058f35..a3e7f1e 100644 --- a/src/global-handles.cc +++ b/src/global-handles.cc @@ -855,8 +855,18 @@ void GlobalHandles::AddObjectGroup(Object*** handles, object_groups_.Add(ObjectGroupConnection( UniqueId(reinterpret_cast(handles[0])), handles[i])); } - retainer_infos_.Add(ObjectGroupRetainerInfo( - UniqueId(reinterpret_cast(handles[0])), info)); + for (size_t i = 0; i < length; ++i) { + if ((*handles[i])->IsHeapObject()) { + representative_objects_.Add(ObjectGroupRepresentative( + UniqueId(reinterpret_cast(handles[0])), + reinterpret_cast(handles[i]))); + break; + } + } + if (info != NULL) { + retainer_infos_.Add(ObjectGroupRetainerInfo( + UniqueId(reinterpret_cast(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(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(); } diff --git a/src/global-handles.h b/src/global-handles.h index de93410..7697364 100644 --- a/src/global-handles.h +++ b/src/global-handles.h @@ -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( - 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* object_groups() { return &object_groups_; } @@ -245,11 +250,14 @@ class GlobalHandles { return &retainer_infos_; } - // Returns the implicit references' groups. - List* implicit_ref_groups() { + List* implicit_ref_groups() { return &implicit_ref_groups_; } + List* 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 object_groups_; List retainer_infos_; - List implicit_ref_groups_; + List representative_objects_; + + // Implicit references. + List implicit_ref_groups_; friend class Isolate; diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc index 4588094..f167886 100644 --- a/src/heap-snapshot-generator.cc +++ b/src/heap-snapshot-generator.cc @@ -1988,24 +1988,61 @@ void NativeObjectsExplorer::FillRetainedObjects() { void NativeObjectsExplorer::FillImplicitReferences() { Isolate* isolate = Isolate::Current(); - List* groups = + List* 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* 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(); diff --git a/src/mark-compact.cc b/src/mark-compact.cc index f49179f..721ce92 100644 --- a/src/mark-compact.cc +++ b/src/mark-compact.cc @@ -1931,34 +1931,72 @@ void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) { void MarkCompactCollector::MarkImplicitRefGroups() { - List* 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* ref_groups = + isolate->global_handles()->implicit_ref_groups(); + List* 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); } diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index d75d5c2..e4f523e 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -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 g1_children[] = { g1c1 }; - Persistent 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(*g1s1)); + UniqueId id2(reinterpret_cast(*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( @@ -2596,14 +2598,16 @@ THREADED_TEST(ApiObjectGroups) { // Groups are deleted, rebuild groups. { - Persistent g1_children[] = { g1c1 }; - Persistent 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(*g1s1)); + UniqueId id2(reinterpret_cast(*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 g1_children[] = { g2s1 }; - Persistent g2_children[] = { g3s1 }; - Persistent g3_children[] = { g4s1 }; - Persistent 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(*g1s1)); + UniqueId id2(reinterpret_cast(*g2s1)); + UniqueId id3(reinterpret_cast(*g3s1)); + UniqueId id4(reinterpret_cast(*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( @@ -2809,22 +2817,26 @@ THREADED_TEST(ApiObjectGroupsCycle) { // Groups are deleted, rebuild groups. { - Persistent g1_children[] = { g2s1 }; - Persistent g2_children[] = { g3s1 }; - Persistent g3_children[] = { g4s1 }; - Persistent 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(*g1s1)); + UniqueId id2(reinterpret_cast(*g2s1)); + UniqueId id3(reinterpret_cast(*g3s1)); + UniqueId id4(reinterpret_cast(*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); diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc index 59e7b8f..ff2838c 100644 --- a/test/cctest/test-heap-profiler.cc +++ b/test/cctest/test-heap-profiler.cc @@ -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::New(isolate, v8::Object::New()); + objects_[i] = + v8::Persistent::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::Cast(objects_[0]), &objects_[1], 1); + v8::V8::SetObjectGroupId(isolate_, + v8::Persistent::Cast(objects_[0]), + v8::UniqueId(1)); + v8::V8::SetObjectGroupRepresentative( + isolate_, + v8::UniqueId(1), + v8::Persistent::Cast(objects_[0])); + v8::V8::AddImplicitReference(isolate_, + v8::UniqueId(1), + v8::Persistent::Cast(objects_[1])); // Adding two more references(note length=2 in params): 1 -> 2, 1 -> 3 - v8::V8::AddImplicitReferences( - v8::Persistent::Cast(objects_[1]), &objects_[2], 2); + v8::V8::SetObjectGroupId(isolate_, + v8::Persistent::Cast(objects_[1]), + v8::UniqueId(2)); + v8::V8::SetObjectGroupRepresentative( + isolate_, + v8::UniqueId(2), + v8::Persistent::Cast(objects_[1])); + v8::V8::AddImplicitReference(isolate_, + v8::UniqueId(2), + v8::Persistent::Cast(objects_[2])); + v8::V8::AddImplicitReference(isolate_, + v8::UniqueId(2), + v8::Persistent::Cast(objects_[3])); } v8::Persistent objects_[kObjectsCount]; static GraphWithImplicitRefs* instance_; + v8::Isolate* isolate_; }; GraphWithImplicitRefs* GraphWithImplicitRefs::instance_ = NULL; diff --git a/test/cctest/test-mark-compact.cc b/test/cctest/test-mark-compact.cc index 5f01731..ee1481f 100644 --- a/test/cctest/test-mark-compact.cc +++ b/test/cctest/test-mark-compact.cc @@ -370,7 +370,7 @@ TEST(ObjectGroupsOldApi) { Handle::cast(g1s1).location(), g1_children, 1); global_handles->AddObjectGroup(g2_objects, 2, NULL); global_handles->AddImplicitReferences( - Handle::cast(g2s2).location(), g2_children, 1); + Handle::cast(g2s1).location(), g2_children, 1); } // Do a full GC HEAP->CollectGarbage(OLD_POINTER_SPACE); @@ -399,7 +399,7 @@ TEST(ObjectGroupsOldApi) { Handle::cast(g1s1).location(), g1_children, 1); global_handles->AddObjectGroup(g2_objects, 2, NULL); global_handles->AddImplicitReferences( - Handle::cast(g2s2).location(), g2_children, 1); + Handle::cast(g2s1).location(), g2_children, 1); } HEAP->CollectGarbage(OLD_POINTER_SPACE); @@ -477,16 +477,16 @@ TEST(ObjectGroups) { Handle::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::cast(g1s1).location(), g1_children, 1); + global_handles->SetObjectGroupRepresentative( + v8::UniqueId(1), reinterpret_cast(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::cast(g2s2).location(), g2_children, 1); + global_handles->SetObjectGroupRepresentative( + v8::UniqueId(2), reinterpret_cast(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::cast(g1s1).location(), g1_children, 1); + global_handles->SetObjectGroupRepresentative( + v8::UniqueId(1), reinterpret_cast(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::cast(g2s2).location(), g2_children, 1); + global_handles->SetObjectGroupRepresentative( + v8::UniqueId(2), reinterpret_cast(g2s1.location())); + global_handles->AddImplicitReference(v8::UniqueId(2), g2c1.location()); } heap->CollectGarbage(OLD_POINTER_SPACE); -- 2.7.4