From 95c4b0d8f6ba224c3b7fdc1fd5cb6584ad095658 Mon Sep 17 00:00:00 2001 From: Michael Lippautz Date: Thu, 2 Mar 2017 18:03:31 +0100 Subject: [PATCH] deps: backport 78867ad8707a016 from v8 upstream Original commit message: Remove object grouping Enbedders should switch to EmbedderHeapTracer API. BUG=v8:5828 Change-Id: I82f2bc583d246617865a17f5904e02cd35f92fec Reviewed-on: https://chromium-review.googlesource.com/448539 Reviewed-by: Hannes Payer Reviewed-by: Ulan Degenbaev Commit-Queue: Michael Lippautz Cr-Commit-Position: refs/heads/master@{#43551} Ref: https://chromium-review.googlesource.com/448539 Ref: https://github.com/v8/v8/commit/78867ad8707a016 PR-URL: https://github.com/nodejs/node/pull/12875 Reviewed-By: James M Snell --- deps/v8/include/v8-profiler.h | 5 - deps/v8/include/v8.h | 69 ---- deps/v8/src/api.cc | 32 -- deps/v8/src/global-handles.cc | 341 +----------------- deps/v8/src/global-handles.h | 143 +------- deps/v8/src/heap/gc-tracer.cc | 6 - deps/v8/src/heap/gc-tracer.h | 3 - deps/v8/src/heap/heap.cc | 4 - deps/v8/src/heap/incremental-marking.cc | 27 +- deps/v8/src/heap/incremental-marking.h | 1 - deps/v8/src/heap/mark-compact.cc | 52 --- deps/v8/src/heap/mark-compact.h | 6 - deps/v8/src/profiler/heap-profiler.cc | 8 - deps/v8/src/profiler/heap-profiler.h | 1 - deps/v8/test/cctest/heap/test-mark-compact.cc | 157 -------- deps/v8/test/cctest/test-global-handles.cc | 289 --------------- 16 files changed, 5 insertions(+), 1139 deletions(-) diff --git a/deps/v8/include/v8-profiler.h b/deps/v8/include/v8-profiler.h index f7d182f8021e1f..b60d137f4479e6 100644 --- a/deps/v8/include/v8-profiler.h +++ b/deps/v8/include/v8-profiler.h @@ -812,11 +812,6 @@ class V8_EXPORT HeapProfiler { /** Returns memory used for profiler internal data and snapshots. */ size_t GetProfilerMemorySize(); - /** - * Sets a RetainedObjectInfo for an object group (see V8::SetObjectGroupId). - */ - void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info); - private: HeapProfiler(); ~HeapProfiler(); diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index e38f657b48fae8..f62fdb2c9ae50d 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -6824,45 +6824,6 @@ class V8_EXPORT Isolate { */ Local ThrowException(Local exception); - /** - * Allows the host application to group objects together. If one - * object in the group is alive, all objects in the group are alive. - * After each garbage collection, object groups are removed. It is - * intended to be used in the before-garbage-collection callback - * function, for instance to simulate DOM tree connections among JS - * wrapper objects. Object groups for all dependent handles need to - * be provided for kGCTypeMarkSweepCompact collections, for all other - * garbage collection types it is sufficient to provide object groups - * for partially dependent handles only. - */ - template - V8_DEPRECATED("Use EmbedderHeapTracer", - void SetObjectGroupId(const Persistent& object, - UniqueId id)); - - /** - * Allows the host application to declare implicit references from an object - * group to an object. If the objects of the object group are alive, the child - * object is alive too. After each garbage collection, all implicit references - * are removed. It is intended to be used in the before-garbage-collection - * callback function. - */ - template - V8_DEPRECATED("Use EmbedderHeapTracer", - void SetReferenceFromGroup(UniqueId id, - const Persistent& child)); - - /** - * Allows the host application to declare implicit references from an object - * to another object. If the parent object is alive, the child object is alive - * too. After each garbage collection, all implicit references are removed. It - * is intended to be used in the before-garbage-collection callback function. - */ - template - V8_DEPRECATED("Use EmbedderHeapTracer", - void SetReference(const Persistent& parent, - const Persistent& child)); - typedef void (*GCCallback)(Isolate* isolate, GCType type, GCCallbackFlags flags); @@ -7328,9 +7289,6 @@ class V8_EXPORT Isolate { template friend class PersistentValueMapBase; - void SetObjectGroupId(internal::Object** object, UniqueId id); - void SetReferenceFromGroup(UniqueId id, internal::Object** object); - void SetReference(internal::Object** parent, internal::Object** child); void ReportExternalAllocationLimitReached(); }; @@ -9745,33 +9703,6 @@ int64_t Isolate::AdjustAmountOfExternalAllocatedMemory( return *external_memory; } - -template -void Isolate::SetObjectGroupId(const Persistent& object, - UniqueId id) { - TYPE_CHECK(Value, T); - SetObjectGroupId(reinterpret_cast(object.val_), id); -} - - -template -void Isolate::SetReferenceFromGroup(UniqueId id, - const Persistent& object) { - TYPE_CHECK(Value, T); - SetReferenceFromGroup(id, reinterpret_cast(object.val_)); -} - - -template -void Isolate::SetReference(const Persistent& parent, - const Persistent& child) { - TYPE_CHECK(Object, T); - TYPE_CHECK(Value, S); - SetReference(reinterpret_cast(parent.val_), - reinterpret_cast(child.val_)); -} - - Local Context::GetEmbedderData(int index) { #ifndef V8_ENABLE_CHECKS typedef internal::Object O; diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 8ce75201c2f695..a8fba7454415b0 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -8059,31 +8059,6 @@ v8::Local Isolate::ThrowException(v8::Local value) { return v8::Undefined(reinterpret_cast(isolate)); } - -void Isolate::SetObjectGroupId(internal::Object** object, UniqueId id) { - i::Isolate* internal_isolate = reinterpret_cast(this); - internal_isolate->global_handles()->SetObjectGroupId( - i::Handle(object).location(), id); -} - - -void Isolate::SetReferenceFromGroup(UniqueId id, internal::Object** object) { - i::Isolate* internal_isolate = reinterpret_cast(this); - internal_isolate->global_handles()->SetReferenceFromGroup( - id, i::Handle(object).location()); -} - - -void Isolate::SetReference(internal::Object** parent, - internal::Object** child) { - i::Isolate* internal_isolate = reinterpret_cast(this); - i::Object** parent_location = i::Handle(parent).location(); - internal_isolate->global_handles()->SetReference( - reinterpret_cast(parent_location), - i::Handle(child).location()); -} - - void Isolate::AddGCPrologueCallback(GCCallback callback, GCType gc_type) { i::Isolate* isolate = reinterpret_cast(this); isolate->heap()->AddGCPrologueCallback(callback, gc_type); @@ -10028,13 +10003,6 @@ size_t HeapProfiler::GetProfilerMemorySize() { GetMemorySizeUsedByProfiler(); } - -void HeapProfiler::SetRetainedObjectInfo(UniqueId id, - RetainedObjectInfo* info) { - reinterpret_cast(this)->SetRetainedObjectInfo(id, info); -} - - v8::Testing::StressType internal::Testing::stress_type_ = v8::Testing::kStressTypeOpt; diff --git a/deps/v8/src/global-handles.cc b/deps/v8/src/global-handles.cc index ff7f132305cd73..95c5c82bc2d341 100644 --- a/deps/v8/src/global-handles.cc +++ b/deps/v8/src/global-handles.cc @@ -13,18 +13,6 @@ namespace v8 { namespace internal { - -ObjectGroup::~ObjectGroup() { - if (info != NULL) info->Dispose(); - delete[] objects; -} - - -ImplicitRefGroup::~ImplicitRefGroup() { - delete[] children; -} - - class GlobalHandles::Node { public: // State transition diagram: @@ -544,8 +532,7 @@ GlobalHandles::GlobalHandles(Isolate* isolate) first_used_block_(NULL), first_free_(NULL), post_gc_processing_count_(0), - number_of_phantom_handle_resets_(0), - object_group_connections_(kObjectGroupConnectionsCapacity) {} + number_of_phantom_handle_resets_(0) {} GlobalHandles::~GlobalHandles() { NodeBlock* block = first_block_; @@ -760,158 +747,6 @@ template void GlobalHandles::IterateNewSpaceWeakUnmodifiedRoots< template void GlobalHandles::IterateNewSpaceWeakUnmodifiedRoots< GlobalHandles::HANDLE_PHANTOM_NODES_VISIT_OTHERS>(ObjectVisitor* v); -DISABLE_CFI_PERF -bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, - WeakSlotCallbackWithHeap can_skip) { - ComputeObjectGroupsAndImplicitReferences(); - int last = 0; - bool any_group_was_visited = false; - for (int i = 0; i < object_groups_.length(); i++) { - ObjectGroup* entry = object_groups_.at(i); - DCHECK(entry != NULL); - - Object*** objects = entry->objects; - bool group_should_be_visited = false; - for (size_t j = 0; j < entry->length; j++) { - Object* object = *objects[j]; - if (object->IsHeapObject()) { - if (!can_skip(isolate_->heap(), &object)) { - group_should_be_visited = true; - break; - } - } - } - - if (!group_should_be_visited) { - object_groups_[last++] = entry; - continue; - } - - // An object in the group requires visiting, so iterate over all - // objects in the group. - for (size_t j = 0; j < entry->length; ++j) { - Object* object = *objects[j]; - if (object->IsHeapObject()) { - v->VisitPointer(&object); - any_group_was_visited = true; - } - } - - // Once the entire group has been iterated over, set the object - // group to NULL so it won't be processed again. - delete entry; - object_groups_.at(i) = NULL; - } - object_groups_.Rewind(last); - return any_group_was_visited; -} - -namespace { -// Traces the information about object groups and implicit ref groups given by -// the embedder to the V8 during each gc prologue. -class ObjectGroupsTracer { - public: - explicit ObjectGroupsTracer(Isolate* isolate); - void Print(); - - private: - void PrintObjectGroup(ObjectGroup* group); - void PrintImplicitRefGroup(ImplicitRefGroup* group); - void PrintObject(Object* object); - void PrintConstructor(JSObject* js_object); - void PrintInternalFields(JSObject* js_object); - Isolate* isolate_; - DISALLOW_COPY_AND_ASSIGN(ObjectGroupsTracer); -}; - -ObjectGroupsTracer::ObjectGroupsTracer(Isolate* isolate) : isolate_(isolate) {} - -void ObjectGroupsTracer::Print() { - GlobalHandles* global_handles = isolate_->global_handles(); - - PrintIsolate(isolate_, "### Tracing object groups:\n"); - - for (auto group : *(global_handles->object_groups())) { - PrintObjectGroup(group); - } - for (auto group : *(global_handles->implicit_ref_groups())) { - PrintImplicitRefGroup(group); - } - - PrintIsolate(isolate_, "### Tracing object groups finished.\n"); -} - -void ObjectGroupsTracer::PrintObject(Object* object) { - if (object->IsJSObject()) { - JSObject* js_object = JSObject::cast(object); - - PrintF("{ constructor_name: "); - PrintConstructor(js_object); - PrintF(", hidden_fields: [ "); - PrintInternalFields(js_object); - PrintF(" ] }\n"); - } else { - PrintF("object of unexpected type: %p\n", static_cast(object)); - } -} - -void ObjectGroupsTracer::PrintConstructor(JSObject* js_object) { - Object* maybe_constructor = js_object->map()->GetConstructor(); - if (maybe_constructor->IsJSFunction()) { - JSFunction* constructor = JSFunction::cast(maybe_constructor); - String* name = String::cast(constructor->shared()->name()); - if (name->length() == 0) name = constructor->shared()->inferred_name(); - - PrintF("%s", name->ToCString().get()); - } else if (maybe_constructor->IsNull(isolate_)) { - if (js_object->IsOddball()) { - PrintF(""); - } else { - PrintF(""); - } - } else { - UNREACHABLE(); - } -} - -void ObjectGroupsTracer::PrintInternalFields(JSObject* js_object) { - for (int i = 0; i < js_object->GetInternalFieldCount(); ++i) { - if (i != 0) { - PrintF(", "); - } - PrintF("%p", static_cast(js_object->GetInternalField(i))); - } -} - -void ObjectGroupsTracer::PrintObjectGroup(ObjectGroup* group) { - PrintIsolate(isolate_, "ObjectGroup (size: %" PRIuS ")\n", group->length); - Object*** objects = group->objects; - - for (size_t i = 0; i < group->length; ++i) { - PrintIsolate(isolate_, " - Member: "); - PrintObject(*objects[i]); - } -} - -void ObjectGroupsTracer::PrintImplicitRefGroup(ImplicitRefGroup* group) { - PrintIsolate(isolate_, "ImplicitRefGroup (children count: %" PRIuS ")\n", - group->length); - PrintIsolate(isolate_, " - Parent: "); - PrintObject(*(group->parent)); - - Object*** children = group->children; - for (size_t i = 0; i < group->length; ++i) { - PrintIsolate(isolate_, " - Child: "); - PrintObject(*children[i]); - } -} - -} // namespace - -void GlobalHandles::PrintObjectGroups() { - ObjectGroupsTracer(isolate_).Print(); -} - void GlobalHandles::InvokeSecondPassPhantomCallbacks( List* callbacks, Isolate* isolate) { while (callbacks->length() != 0) { @@ -1233,184 +1068,10 @@ void GlobalHandles::Print() { #endif - - -void GlobalHandles::AddObjectGroup(Object*** handles, - size_t length, - v8::RetainedObjectInfo* info) { -#ifdef DEBUG - for (size_t i = 0; i < length; ++i) { - DCHECK(!Node::FromLocation(handles[i])->is_independent()); - } -#endif - if (length == 0) { - if (info != NULL) info->Dispose(); - return; - } - ObjectGroup* group = new ObjectGroup(length); - for (size_t i = 0; i < length; ++i) - group->objects[i] = handles[i]; - group->info = info; - object_groups_.Add(group); -} - - -void GlobalHandles::SetObjectGroupId(Object** handle, - UniqueId id) { - object_group_connections_.Add(ObjectGroupConnection(id, handle)); -} - - -void GlobalHandles::SetRetainedObjectInfo(UniqueId id, - RetainedObjectInfo* info) { - retainer_infos_.Add(ObjectGroupRetainerInfo(id, info)); -} - - -void GlobalHandles::SetReferenceFromGroup(UniqueId id, Object** child) { - DCHECK(!Node::FromLocation(child)->is_independent()); - implicit_ref_connections_.Add(ObjectGroupConnection(id, child)); -} - - -void GlobalHandles::SetReference(HeapObject** parent, Object** child) { - DCHECK(!Node::FromLocation(child)->is_independent()); - ImplicitRefGroup* group = new ImplicitRefGroup(parent, 1); - group->children[0] = child; - implicit_ref_groups_.Add(group); -} - - -void GlobalHandles::RemoveObjectGroups() { - for (int i = 0; i < object_groups_.length(); i++) - delete object_groups_.at(i); - object_groups_.Clear(); - for (int i = 0; i < retainer_infos_.length(); ++i) - retainer_infos_[i].info->Dispose(); - retainer_infos_.Clear(); - object_group_connections_.Clear(); - object_group_connections_.Initialize(kObjectGroupConnectionsCapacity); -} - - -void GlobalHandles::RemoveImplicitRefGroups() { - for (int i = 0; i < implicit_ref_groups_.length(); i++) { - delete implicit_ref_groups_.at(i); - } - implicit_ref_groups_.Clear(); - implicit_ref_connections_.Clear(); -} - - void GlobalHandles::TearDown() { // TODO(1428): invoke weak callbacks. } - -void GlobalHandles::ComputeObjectGroupsAndImplicitReferences() { - if (object_group_connections_.length() == 0) { - for (int i = 0; i < retainer_infos_.length(); ++i) - retainer_infos_[i].info->Dispose(); - retainer_infos_.Clear(); - implicit_ref_connections_.Clear(); - return; - } - - object_group_connections_.Sort(); - retainer_infos_.Sort(); - implicit_ref_connections_.Sort(); - - int info_index = 0; // For iterating retainer_infos_. - UniqueId current_group_id(0); - int current_group_start = 0; - - int current_implicit_refs_start = 0; - int current_implicit_refs_end = 0; - for (int i = 0; i <= object_group_connections_.length(); ++i) { - if (i == 0) - current_group_id = object_group_connections_[i].id; - if (i == object_group_connections_.length() || - current_group_id != object_group_connections_[i].id) { - // Group detected: objects in indices [current_group_start, i[. - - // Find out which implicit references are related to this group. (We want - // to ignore object groups which only have 1 object, but that object is - // needed as a representative object for the implicit refrerence group.) - while (current_implicit_refs_start < implicit_ref_connections_.length() && - implicit_ref_connections_[current_implicit_refs_start].id < - current_group_id) - ++current_implicit_refs_start; - current_implicit_refs_end = current_implicit_refs_start; - while (current_implicit_refs_end < implicit_ref_connections_.length() && - implicit_ref_connections_[current_implicit_refs_end].id == - current_group_id) - ++current_implicit_refs_end; - - if (current_implicit_refs_end > current_implicit_refs_start) { - // Find a representative object for the implicit references. - HeapObject** representative = NULL; - for (int j = current_group_start; j < i; ++j) { - Object** object = object_group_connections_[j].object; - if ((*object)->IsHeapObject()) { - representative = reinterpret_cast(object); - break; - } - } - if (representative) { - ImplicitRefGroup* group = new ImplicitRefGroup( - representative, - current_implicit_refs_end - current_implicit_refs_start); - for (int j = current_implicit_refs_start; - j < current_implicit_refs_end; - ++j) { - group->children[j - current_implicit_refs_start] = - implicit_ref_connections_[j].object; - } - implicit_ref_groups_.Add(group); - } - current_implicit_refs_start = current_implicit_refs_end; - } - - // Find a RetainedObjectInfo for the group. - RetainedObjectInfo* info = NULL; - while (info_index < retainer_infos_.length() && - retainer_infos_[info_index].id < current_group_id) { - retainer_infos_[info_index].info->Dispose(); - ++info_index; - } - if (info_index < retainer_infos_.length() && - retainer_infos_[info_index].id == current_group_id) { - // This object group has an associated ObjectGroupRetainerInfo. - info = retainer_infos_[info_index].info; - ++info_index; - } - - // Ignore groups which only contain one object. - if (i > current_group_start + 1) { - ObjectGroup* group = new ObjectGroup(i - current_group_start); - for (int j = current_group_start; j < i; ++j) { - group->objects[j - current_group_start] = - object_group_connections_[j].object; - } - group->info = info; - object_groups_.Add(group); - } else if (info) { - info->Dispose(); - } - - if (i < object_group_connections_.length()) { - current_group_id = object_group_connections_[i].id; - current_group_start = i; - } - } - } - object_group_connections_.Clear(); - object_group_connections_.Initialize(kObjectGroupConnectionsCapacity); - retainer_infos_.Clear(); - implicit_ref_connections_.Clear(); -} - - EternalHandles::EternalHandles() : size_(0) { for (unsigned i = 0; i < arraysize(singleton_handles_); i++) { singleton_handles_[i] = kInvalidIndex; diff --git a/deps/v8/src/global-handles.h b/deps/v8/src/global-handles.h index 9c4ffb4f1a4351..d80f4a274c8884 100644 --- a/deps/v8/src/global-handles.h +++ b/deps/v8/src/global-handles.h @@ -24,78 +24,6 @@ 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 ObjectGroup { - explicit ObjectGroup(size_t length) - : info(NULL), length(length) { - DCHECK(length > 0); - objects = new Object**[length]; - } - ~ObjectGroup(); - - v8::RetainedObjectInfo* info; - Object*** objects; - size_t length; -}; - - -struct ImplicitRefGroup { - ImplicitRefGroup(HeapObject** parent, size_t length) - : parent(parent), length(length) { - DCHECK(length > 0); - children = new Object**[length]; - } - ~ImplicitRefGroup(); - - HeapObject** parent; - Object*** children; - size_t length; -}; - - -// For internal bookkeeping. -struct ObjectGroupConnection { - ObjectGroupConnection(UniqueId id, Object** object) - : id(id), object(object) {} - - bool operator==(const ObjectGroupConnection& other) const { - return id == other.id; - } - - bool operator<(const ObjectGroupConnection& other) const { - return id < other.id; - } - - UniqueId id; - Object** object; -}; - - -struct ObjectGroupRetainerInfo { - ObjectGroupRetainerInfo(UniqueId id, RetainedObjectInfo* info) - : id(id), info(info) {} - - bool operator==(const ObjectGroupRetainerInfo& other) const { - return id == other.id; - } - - bool operator<(const ObjectGroupRetainerInfo& other) const { - return id < other.id; - } - - UniqueId id; - RetainedObjectInfo* info; -}; - enum WeaknessType { // Embedder gets a handle to the dying object. FINALIZER_WEAK, @@ -170,7 +98,7 @@ class GlobalHandles { // Clear the weakness of a global handle. static void* ClearWeakness(Object** location); - // Mark the reference to this object independent of any object group. + // Mark the reference to this object independent. static void MarkIndependent(Object** location); static bool IsIndependent(Object** location); @@ -240,55 +168,6 @@ class GlobalHandles { // unmodified void IdentifyWeakUnmodifiedObjects(WeakSlotCallback is_unmodified); - // Iterate over objects in object groups that have at least one object - // which requires visiting. The callback has to return true if objects - // can be skipped and false otherwise. - bool IterateObjectGroups(ObjectVisitor* v, WeakSlotCallbackWithHeap can_skip); - - // Print all objects in object groups - void PrintObjectGroups(); - - // Add an object group. - // Should be only used in GC callback function before a collection. - // All groups are destroyed after a garbage collection. - void AddObjectGroup(Object*** handles, - size_t length, - v8::RetainedObjectInfo* info); - - // Associates handle with the object group represented by id. - // Should be only used in GC callback function before a collection. - // All groups are destroyed after a garbage collection. - void SetObjectGroupId(Object** handle, UniqueId id); - - // 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); - - // Adds an implicit reference from a 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 SetReferenceFromGroup(UniqueId id, Object** child); - - // Adds an implicit reference from a parent object to a child object. Should - // be only used in GC callback function before a collection. All implicit - // references are destroyed after a mark-compact collection. - void SetReference(HeapObject** parent, Object** child); - - List* object_groups() { - ComputeObjectGroupsAndImplicitReferences(); - return &object_groups_; - } - - List* implicit_ref_groups() { - ComputeObjectGroupsAndImplicitReferences(); - return &implicit_ref_groups_; - } - - // Remove bags, this should only happen after GC. - void RemoveObjectGroups(); - void RemoveImplicitRefGroups(); - // Tear down the global handle structure. void TearDown(); @@ -302,15 +181,6 @@ class GlobalHandles { private: explicit GlobalHandles(Isolate* isolate); - // Migrates data from the internal representation (object_group_connections_, - // retainer_infos_ and implicit_ref_connections_) to the public and more - // efficient representation (object_groups_ and implicit_ref_groups_). - void ComputeObjectGroupsAndImplicitReferences(); - - // v8::internal::List is inefficient even for small number of elements, if we - // don't assign any initial capacity. - static const int kObjectGroupConnectionsCapacity = 20; - class PendingPhantomCallback; // Helpers for PostGarbageCollectionProcessing. @@ -349,17 +219,6 @@ class GlobalHandles { size_t number_of_phantom_handle_resets_; - // Object groups and implicit references, public and more efficient - // representation. - List object_groups_; - List implicit_ref_groups_; - - // Object groups and implicit references, temporary representation while - // constructing the groups. - List object_group_connections_; - List retainer_infos_; - List implicit_ref_connections_; - List pending_phantom_callbacks_; friend class Isolate; diff --git a/deps/v8/src/heap/gc-tracer.cc b/deps/v8/src/heap/gc-tracer.cc index 2c1024f09ae01a..2a4b481805f802 100644 --- a/deps/v8/src/heap/gc-tracer.cc +++ b/deps/v8/src/heap/gc-tracer.cc @@ -537,7 +537,6 @@ void GCTracer::PrintNVP() const { "clear=%1.f " "clear.code_flush=%.1f " "clear.dependent_code=%.1f " - "clear.global_handles=%.1f " "clear.maps=%.1f " "clear.slots_buffer=%.1f " "clear.store_buffer=%.1f " @@ -563,7 +562,6 @@ void GCTracer::PrintNVP() const { "finish=%.1f " "mark=%.1f " "mark.finish_incremental=%.1f " - "mark.object_grouping=%.1f " "mark.prepare_code_flush=%.1f " "mark.roots=%.1f " "mark.weak_closure=%.1f " @@ -584,7 +582,6 @@ void GCTracer::PrintNVP() const { "incremental.finalize.body=%.1f " "incremental.finalize.external.prologue=%.1f " "incremental.finalize.external.epilogue=%.1f " - "incremental.finalize.object_grouping=%.1f " "incremental.sweeping=%.1f " "incremental.wrapper_prologue=%.1f " "incremental.wrapper_tracing=%.1f " @@ -623,7 +620,6 @@ void GCTracer::PrintNVP() const { current_.reduce_memory, current_.scopes[Scope::MC_CLEAR], current_.scopes[Scope::MC_CLEAR_CODE_FLUSH], current_.scopes[Scope::MC_CLEAR_DEPENDENT_CODE], - current_.scopes[Scope::MC_CLEAR_GLOBAL_HANDLES], current_.scopes[Scope::MC_CLEAR_MAPS], current_.scopes[Scope::MC_CLEAR_SLOTS_BUFFER], current_.scopes[Scope::MC_CLEAR_STORE_BUFFER], @@ -648,7 +644,6 @@ void GCTracer::PrintNVP() const { current_.scopes[Scope::EXTERNAL_WEAK_GLOBAL_HANDLES], current_.scopes[Scope::MC_FINISH], current_.scopes[Scope::MC_MARK], current_.scopes[Scope::MC_MARK_FINISH_INCREMENTAL], - current_.scopes[Scope::MC_MARK_OBJECT_GROUPING], current_.scopes[Scope::MC_MARK_PREPARE_CODE_FLUSH], current_.scopes[Scope::MC_MARK_ROOTS], current_.scopes[Scope::MC_MARK_WEAK_CLOSURE], @@ -668,7 +663,6 @@ void GCTracer::PrintNVP() const { current_.scopes[Scope::MC_INCREMENTAL_FINALIZE_BODY], current_.scopes[Scope::MC_INCREMENTAL_EXTERNAL_PROLOGUE], current_.scopes[Scope::MC_INCREMENTAL_EXTERNAL_EPILOGUE], - current_.scopes[Scope::MC_INCREMENTAL_FINALIZE_OBJECT_GROUPING], current_.scopes[Scope::MC_INCREMENTAL_SWEEPING], current_.scopes[Scope::MC_INCREMENTAL_WRAPPER_PROLOGUE], current_.scopes[Scope::MC_INCREMENTAL_WRAPPER_TRACING], diff --git a/deps/v8/src/heap/gc-tracer.h b/deps/v8/src/heap/gc-tracer.h index b2062861680581..55bd3e8d83ec86 100644 --- a/deps/v8/src/heap/gc-tracer.h +++ b/deps/v8/src/heap/gc-tracer.h @@ -31,7 +31,6 @@ enum ScavengeSpeedMode { kForAllObjects, kForSurvivedObjects }; F(MC_INCREMENTAL_WRAPPER_TRACING) \ F(MC_INCREMENTAL_FINALIZE) \ F(MC_INCREMENTAL_FINALIZE_BODY) \ - F(MC_INCREMENTAL_FINALIZE_OBJECT_GROUPING) \ F(MC_INCREMENTAL_EXTERNAL_EPILOGUE) \ F(MC_INCREMENTAL_EXTERNAL_PROLOGUE) @@ -43,7 +42,6 @@ enum ScavengeSpeedMode { kForAllObjects, kForSurvivedObjects }; F(MC_CLEAR) \ F(MC_CLEAR_CODE_FLUSH) \ F(MC_CLEAR_DEPENDENT_CODE) \ - F(MC_CLEAR_GLOBAL_HANDLES) \ F(MC_CLEAR_MAPS) \ F(MC_CLEAR_SLOTS_BUFFER) \ F(MC_CLEAR_STORE_BUFFER) \ @@ -76,7 +74,6 @@ enum ScavengeSpeedMode { kForAllObjects, kForSurvivedObjects }; F(MC_MARK_WRAPPER_EPILOGUE) \ F(MC_MARK_WRAPPER_PROLOGUE) \ F(MC_MARK_WRAPPER_TRACING) \ - F(MC_MARK_OBJECT_GROUPING) \ F(MC_PROLOGUE) \ F(MC_SWEEP) \ F(MC_SWEEP_CODE) \ diff --git a/deps/v8/src/heap/heap.cc b/deps/v8/src/heap/heap.cc index 25cb56d20c0f5b..e1f0994a2501a6 100644 --- a/deps/v8/src/heap/heap.cc +++ b/deps/v8/src/heap/heap.cc @@ -1432,10 +1432,6 @@ void Heap::CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags) { } } } - if (FLAG_trace_object_groups && (gc_type == kGCTypeIncrementalMarking || - gc_type == kGCTypeMarkSweepCompact)) { - isolate_->global_handles()->PrintObjectGroups(); - } } diff --git a/deps/v8/src/heap/incremental-marking.cc b/deps/v8/src/heap/incremental-marking.cc index 9e8fdc726e8ff4..64d8c056c8eba2 100644 --- a/deps/v8/src/heap/incremental-marking.cc +++ b/deps/v8/src/heap/incremental-marking.cc @@ -591,24 +591,6 @@ void IncrementalMarking::MarkRoots() { heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); } - -void IncrementalMarking::MarkObjectGroups() { - TRACE_GC(heap_->tracer(), - GCTracer::Scope::MC_INCREMENTAL_FINALIZE_OBJECT_GROUPING); - - DCHECK(!heap_->local_embedder_heap_tracer()->InUse()); - DCHECK(!finalize_marking_completed_); - DCHECK(IsMarking()); - - IncrementalMarkingRootMarkingVisitor visitor(this); - heap_->mark_compact_collector()->MarkImplicitRefGroups(&MarkGrey); - heap_->isolate()->global_handles()->IterateObjectGroups( - &visitor, &MarkCompactCollector::IsUnmarkedHeapObjectWithHeap); - heap_->isolate()->global_handles()->RemoveImplicitRefGroups(); - heap_->isolate()->global_handles()->RemoveObjectGroups(); -} - - void IncrementalMarking::ProcessWeakCells() { DCHECK(!finalize_marking_completed_); DCHECK(IsMarking()); @@ -721,14 +703,11 @@ void IncrementalMarking::FinalizeIncrementally() { // After finishing incremental marking, we try to discover all unmarked // objects to reduce the marking load in the final pause. // 1) We scan and mark the roots again to find all changes to the root set. - // 2) We mark the object groups. - // 3) Age and retain maps embedded in optimized code. - // 4) Remove weak cell with live values from the list of weak cells, they + // 2) Age and retain maps embedded in optimized code. + // 3) Remove weak cell with live values from the list of weak cells, they // do not need processing during GC. MarkRoots(); - if (!heap_->local_embedder_heap_tracer()->InUse()) { - MarkObjectGroups(); - } + if (incremental_marking_finalization_rounds_ == 0) { // Map retaining is needed for perfromance, not correctness, // so we can do it only once at the beginning of the finalization. diff --git a/deps/v8/src/heap/incremental-marking.h b/deps/v8/src/heap/incremental-marking.h index 37f1e5cec114df..21a4b592ba1e06 100644 --- a/deps/v8/src/heap/incremental-marking.h +++ b/deps/v8/src/heap/incremental-marking.h @@ -244,7 +244,6 @@ class V8_EXPORT_PRIVATE IncrementalMarking { void FinishBlackAllocation(); void MarkRoots(); - void MarkObjectGroups(); void ProcessWeakCells(); // Retain dying maps for garbage collections to // increase chances of reusing of map transition tree in future. diff --git a/deps/v8/src/heap/mark-compact.cc b/deps/v8/src/heap/mark-compact.cc index cf6bdff35df729..d6dc943fc58db5 100644 --- a/deps/v8/src/heap/mark-compact.cc +++ b/deps/v8/src/heap/mark-compact.cc @@ -1949,13 +1949,6 @@ bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { } -bool MarkCompactCollector::IsUnmarkedHeapObjectWithHeap(Heap* heap, - Object** p) { - Object* o = *p; - DCHECK(o->IsHeapObject()); - return ObjectMarking::IsWhite(HeapObject::cast(o)); -} - void MarkCompactCollector::MarkStringTable( RootMarkingVisitor* visitor) { StringTable* string_table = heap()->string_table(); @@ -1985,38 +1978,6 @@ void MarkCompactCollector::MarkRoots( } } - -void MarkCompactCollector::MarkImplicitRefGroups( - MarkObjectFunction mark_object) { - 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); - DCHECK(entry != NULL); - - if (ObjectMarking::IsWhite(*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()) { - mark_object(heap(), HeapObject::cast(*children[j])); - } - } - - // Once the entire group has been marked, dispose it because it's - // not needed anymore. - delete entry; - } - ref_groups->Rewind(last); -} - - // Mark all objects reachable from the objects on the marking stack. // Before: the marking stack contains zero or more heap object pointers. // After: the marking stack is empty, and all objects reachable from the @@ -2104,11 +2065,6 @@ void MarkCompactCollector::ProcessEphemeralMarking( 0, EmbedderHeapTracer::AdvanceTracingActions( EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION)); - } else { - TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_OBJECT_GROUPING); - isolate()->global_handles()->IterateObjectGroups( - visitor, &IsUnmarkedHeapObjectWithHeap); - MarkImplicitRefGroups(&MarkCompactMarkingVisitor::MarkObject); } } else { // TODO(mlippautz): We currently do not trace through blink when @@ -2495,14 +2451,6 @@ void MarkCompactCollector::ClearNonLiveReferences() { heap()->ProcessAllWeakReferences(&mark_compact_object_retainer); } - { - TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_GLOBAL_HANDLES); - - // Remove object groups after marking phase. - heap()->isolate()->global_handles()->RemoveObjectGroups(); - heap()->isolate()->global_handles()->RemoveImplicitRefGroups(); - } - // Flush code from collected candidates. if (is_code_flushing_enabled()) { TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_CODE_FLUSH); diff --git a/deps/v8/src/heap/mark-compact.h b/deps/v8/src/heap/mark-compact.h index 86d0b9616b5048..da2ba4ee38dcfa 100644 --- a/deps/v8/src/heap/mark-compact.h +++ b/deps/v8/src/heap/mark-compact.h @@ -516,8 +516,6 @@ class MarkCompactCollector { static const uint32_t kSingleFreeEncoding = 0; static const uint32_t kMultiFreeEncoding = 1; - static bool IsUnmarkedHeapObjectWithHeap(Heap* heap, Object** p); - inline Heap* heap() const { return heap_; } inline Isolate* isolate() const; @@ -569,10 +567,6 @@ class MarkCompactCollector { bool evacuation() const { return evacuation_; } - // Mark objects in implicit references groups if their parent object - // is marked. - void MarkImplicitRefGroups(MarkObjectFunction mark_object); - MarkingDeque* marking_deque() { return &marking_deque_; } Sweeper& sweeper() { return sweeper_; } diff --git a/deps/v8/src/profiler/heap-profiler.cc b/deps/v8/src/profiler/heap-profiler.cc index 938bb1242438fc..d1980d7fa9405b 100644 --- a/deps/v8/src/profiler/heap-profiler.cc +++ b/deps/v8/src/profiler/heap-profiler.cc @@ -201,14 +201,6 @@ void HeapProfiler::UpdateObjectSizeEvent(Address addr, int size) { ids_->UpdateObjectSize(addr, size); } - -void HeapProfiler::SetRetainedObjectInfo(UniqueId id, - RetainedObjectInfo* info) { - // TODO(yurus, marja): Don't route this information through GlobalHandles. - heap()->isolate()->global_handles()->SetRetainedObjectInfo(id, info); -} - - Handle HeapProfiler::FindHeapObjectById(SnapshotObjectId id) { HeapObject* object = NULL; HeapIterator iterator(heap(), HeapIterator::kFilterUnreachable); diff --git a/deps/v8/src/profiler/heap-profiler.h b/deps/v8/src/profiler/heap-profiler.h index a10cb9228fa065..1a43fc8edf2ab0 100644 --- a/deps/v8/src/profiler/heap-profiler.h +++ b/deps/v8/src/profiler/heap-profiler.h @@ -64,7 +64,6 @@ class HeapProfiler { v8::RetainedObjectInfo* ExecuteWrapperClassCallback(uint16_t class_id, Object** wrapper); - void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info); void SetGetRetainerInfosCallback( v8::HeapProfiler::GetRetainerInfosCallback callback); diff --git a/deps/v8/test/cctest/heap/test-mark-compact.cc b/deps/v8/test/cctest/heap/test-mark-compact.cc index 9f749c5f42f085..342222304b6d62 100644 --- a/deps/v8/test/cctest/heap/test-mark-compact.cc +++ b/deps/v8/test/cctest/heap/test-mark-compact.cc @@ -227,169 +227,12 @@ TEST(MapCompact) { } #endif - -static int NumberOfWeakCalls = 0; -static void WeakPointerCallback(const v8::WeakCallbackInfo& data) { - std::pair*, int>* p = - reinterpret_cast*, int>*>( - data.GetParameter()); - CHECK_EQ(1234, p->second); - NumberOfWeakCalls++; - p->first->Reset(); -} - - -HEAP_TEST(ObjectGroups) { - FLAG_incremental_marking = false; - CcTest::InitializeVM(); - GlobalHandles* global_handles = CcTest::i_isolate()->global_handles(); - Heap* heap = CcTest::heap(); - NumberOfWeakCalls = 0; - v8::HandleScope handle_scope(CcTest::isolate()); - - Handle g1s1 = - global_handles->Create(heap->AllocateFixedArray(1).ToObjectChecked()); - Handle g1s2 = - global_handles->Create(heap->AllocateFixedArray(1).ToObjectChecked()); - Handle g1c1 = - global_handles->Create(heap->AllocateFixedArray(1).ToObjectChecked()); - std::pair*, int> g1s1_and_id(&g1s1, 1234); - GlobalHandles::MakeWeak( - g1s1.location(), reinterpret_cast(&g1s1_and_id), - &WeakPointerCallback, v8::WeakCallbackType::kParameter); - std::pair*, int> g1s2_and_id(&g1s2, 1234); - GlobalHandles::MakeWeak( - g1s2.location(), reinterpret_cast(&g1s2_and_id), - &WeakPointerCallback, v8::WeakCallbackType::kParameter); - std::pair*, int> g1c1_and_id(&g1c1, 1234); - GlobalHandles::MakeWeak( - g1c1.location(), reinterpret_cast(&g1c1_and_id), - &WeakPointerCallback, v8::WeakCallbackType::kParameter); - - Handle g2s1 = - global_handles->Create(heap->AllocateFixedArray(1).ToObjectChecked()); - Handle g2s2 = - global_handles->Create(heap->AllocateFixedArray(1).ToObjectChecked()); - Handle g2c1 = - global_handles->Create(heap->AllocateFixedArray(1).ToObjectChecked()); - std::pair*, int> g2s1_and_id(&g2s1, 1234); - GlobalHandles::MakeWeak( - g2s1.location(), reinterpret_cast(&g2s1_and_id), - &WeakPointerCallback, v8::WeakCallbackType::kParameter); - std::pair*, int> g2s2_and_id(&g2s2, 1234); - GlobalHandles::MakeWeak( - g2s2.location(), reinterpret_cast(&g2s2_and_id), - &WeakPointerCallback, v8::WeakCallbackType::kParameter); - std::pair*, int> g2c1_and_id(&g2c1, 1234); - GlobalHandles::MakeWeak( - g2c1.location(), reinterpret_cast(&g2c1_and_id), - &WeakPointerCallback, v8::WeakCallbackType::kParameter); - - Handle root = global_handles->Create(*g1s1); // make a root. - - // Connect group 1 and 2, make a cycle. - Handle::cast(g1s2)->set(0, *g2s2); - Handle::cast(g2s1)->set(0, *g1s1); - - { - Object** g1_objects[] = { g1s1.location(), g1s2.location() }; - Object** g2_objects[] = { g2s1.location(), g2s2.location() }; - global_handles->AddObjectGroup(g1_objects, 2, NULL); - global_handles->SetReference(Handle::cast(g1s1).location(), - g1c1.location()); - global_handles->AddObjectGroup(g2_objects, 2, NULL); - global_handles->SetReference(Handle::cast(g2s1).location(), - g2c1.location()); - } - // Do a full GC - CcTest::CollectGarbage(OLD_SPACE); - - // All object should be alive. - CHECK_EQ(0, NumberOfWeakCalls); - - // Weaken the root. - std::pair*, int> root_and_id(&root, 1234); - GlobalHandles::MakeWeak( - root.location(), reinterpret_cast(&root_and_id), - &WeakPointerCallback, v8::WeakCallbackType::kParameter); - // But make children strong roots---all the objects (except for children) - // should be collectable now. - global_handles->ClearWeakness(g1c1.location()); - global_handles->ClearWeakness(g2c1.location()); - - // Groups are deleted, rebuild groups. - { - Object** g1_objects[] = { g1s1.location(), g1s2.location() }; - Object** g2_objects[] = { g2s1.location(), g2s2.location() }; - global_handles->AddObjectGroup(g1_objects, 2, NULL); - global_handles->SetReference(Handle::cast(g1s1).location(), - g1c1.location()); - global_handles->AddObjectGroup(g2_objects, 2, NULL); - global_handles->SetReference(Handle::cast(g2s1).location(), - g2c1.location()); - } - - CcTest::CollectGarbage(OLD_SPACE); - - // All objects should be gone. 5 global handles in total. - CHECK_EQ(5, NumberOfWeakCalls); - - // And now make children weak again and collect them. - GlobalHandles::MakeWeak( - g1c1.location(), reinterpret_cast(&g1c1_and_id), - &WeakPointerCallback, v8::WeakCallbackType::kParameter); - GlobalHandles::MakeWeak( - g2c1.location(), reinterpret_cast(&g2c1_and_id), - &WeakPointerCallback, v8::WeakCallbackType::kParameter); - - CcTest::CollectGarbage(OLD_SPACE); - CHECK_EQ(7, NumberOfWeakCalls); -} - - -class TestRetainedObjectInfo : public v8::RetainedObjectInfo { - public: - TestRetainedObjectInfo() : has_been_disposed_(false) {} - - bool has_been_disposed() { return has_been_disposed_; } - - virtual void Dispose() { - CHECK(!has_been_disposed_); - has_been_disposed_ = true; - } - - virtual bool IsEquivalent(v8::RetainedObjectInfo* other) { - return other == this; - } - - virtual intptr_t GetHash() { return 0; } - - virtual const char* GetLabel() { return "whatever"; } - - private: - bool has_been_disposed_; -}; - - -TEST(EmptyObjectGroups) { - CcTest::InitializeVM(); - GlobalHandles* global_handles = CcTest::i_isolate()->global_handles(); - - v8::HandleScope handle_scope(CcTest::isolate()); - - TestRetainedObjectInfo info; - global_handles->AddObjectGroup(NULL, 0, &info); - CHECK(info.has_been_disposed()); -} - - #if defined(__has_feature) #if __has_feature(address_sanitizer) #define V8_WITH_ASAN 1 #endif #endif - // Here is a memory use test that uses /proc, and is therefore Linux-only. We // do not care how much memory the simulator uses, since it is only there for // debugging purposes. Testing with ASAN doesn't make sense, either. diff --git a/deps/v8/test/cctest/test-global-handles.cc b/deps/v8/test/cctest/test-global-handles.cc index 2ace0296c1e5bd..648cd869630e47 100644 --- a/deps/v8/test/cctest/test-global-handles.cc +++ b/deps/v8/test/cctest/test-global-handles.cc @@ -36,295 +36,6 @@ using namespace v8::internal; using v8::UniqueId; - -static List skippable_objects; -static List can_skip_called_objects; - - -static bool CanSkipCallback(Heap* heap, Object** pointer) { - can_skip_called_objects.Add(*pointer); - return skippable_objects.Contains(*pointer); -} - - -static void ResetCanSkipData() { - skippable_objects.Clear(); - can_skip_called_objects.Clear(); -} - - -class TestRetainedObjectInfo : public v8::RetainedObjectInfo { - public: - TestRetainedObjectInfo() : has_been_disposed_(false) {} - - bool has_been_disposed() { return has_been_disposed_; } - - virtual void Dispose() { - CHECK(!has_been_disposed_); - has_been_disposed_ = true; - } - - virtual bool IsEquivalent(v8::RetainedObjectInfo* other) { - return other == this; - } - - virtual intptr_t GetHash() { return 0; } - - virtual const char* GetLabel() { return "whatever"; } - - private: - bool has_been_disposed_; -}; - - -class TestObjectVisitor : public ObjectVisitor { - public: - void VisitPointers(Object** start, Object** end) override { - for (Object** o = start; o != end; ++o) - visited.Add(*o); - } - - List visited; -}; - - -TEST(IterateObjectGroupsOldApi) { - CcTest::InitializeVM(); - Isolate* isolate = CcTest::i_isolate(); - GlobalHandles* global_handles = isolate->global_handles(); - v8::HandleScope handle_scope(CcTest::isolate()); - - Handle g1s1 = - global_handles->Create(*isolate->factory()->NewFixedArray(1)); - Handle g1s2 = - global_handles->Create(*isolate->factory()->NewFixedArray(1)); - - Handle g2s1 = - global_handles->Create(*isolate->factory()->NewFixedArray(1)); - Handle g2s2 = - global_handles->Create(*isolate->factory()->NewFixedArray(1)); - - TestRetainedObjectInfo info1; - TestRetainedObjectInfo info2; - { - Object** g1_objects[] = { g1s1.location(), g1s2.location() }; - Object** g2_objects[] = { g2s1.location(), g2s2.location() }; - - global_handles->AddObjectGroup(g1_objects, 2, &info1); - global_handles->AddObjectGroup(g2_objects, 2, &info2); - } - - // Iterate the object groups. First skip all. - { - ResetCanSkipData(); - skippable_objects.Add(*g1s1.location()); - skippable_objects.Add(*g1s2.location()); - skippable_objects.Add(*g2s1.location()); - skippable_objects.Add(*g2s2.location()); - TestObjectVisitor visitor; - global_handles->IterateObjectGroups(&visitor, &CanSkipCallback); - - // CanSkipCallback was called for all objects. - CHECK(can_skip_called_objects.length() == 4); - CHECK(can_skip_called_objects.Contains(*g1s1.location())); - CHECK(can_skip_called_objects.Contains(*g1s2.location())); - CHECK(can_skip_called_objects.Contains(*g2s1.location())); - CHECK(can_skip_called_objects.Contains(*g2s2.location())); - - // Nothing was visited. - CHECK(visitor.visited.length() == 0); - CHECK(!info1.has_been_disposed()); - CHECK(!info2.has_been_disposed()); - } - - // Iterate again, now only skip the second object group. - { - ResetCanSkipData(); - // The first grough should still be visited, since only one object is - // skipped. - skippable_objects.Add(*g1s1.location()); - skippable_objects.Add(*g2s1.location()); - skippable_objects.Add(*g2s2.location()); - TestObjectVisitor visitor; - global_handles->IterateObjectGroups(&visitor, &CanSkipCallback); - - // CanSkipCallback was called for all objects. - CHECK(can_skip_called_objects.length() == 3 || - can_skip_called_objects.length() == 4); - CHECK(can_skip_called_objects.Contains(*g1s2.location())); - CHECK(can_skip_called_objects.Contains(*g2s1.location())); - CHECK(can_skip_called_objects.Contains(*g2s2.location())); - - // The first group was visited. - CHECK(visitor.visited.length() == 2); - CHECK(visitor.visited.Contains(*g1s1.location())); - CHECK(visitor.visited.Contains(*g1s2.location())); - CHECK(info1.has_been_disposed()); - CHECK(!info2.has_been_disposed()); - } - - // Iterate again, don't skip anything. - { - ResetCanSkipData(); - TestObjectVisitor visitor; - global_handles->IterateObjectGroups(&visitor, &CanSkipCallback); - - // CanSkipCallback was called for all objects. - CHECK(can_skip_called_objects.length() == 1); - CHECK(can_skip_called_objects.Contains(*g2s1.location()) || - can_skip_called_objects.Contains(*g2s2.location())); - - // The second group was visited. - CHECK(visitor.visited.length() == 2); - CHECK(visitor.visited.Contains(*g2s1.location())); - CHECK(visitor.visited.Contains(*g2s2.location())); - CHECK(info2.has_been_disposed()); - } -} - - -TEST(IterateObjectGroups) { - CcTest::InitializeVM(); - Isolate* isolate = CcTest::i_isolate(); - GlobalHandles* global_handles = isolate->global_handles(); - - v8::HandleScope handle_scope(CcTest::isolate()); - - Handle g1s1 = - global_handles->Create(*isolate->factory()->NewFixedArray(1)); - Handle g1s2 = - global_handles->Create(*isolate->factory()->NewFixedArray(1)); - - Handle g2s1 = - global_handles->Create(*isolate->factory()->NewFixedArray(1)); - Handle g2s2 = - global_handles->Create(*isolate->factory()->NewFixedArray(1)); - - TestRetainedObjectInfo info1; - TestRetainedObjectInfo info2; - global_handles->SetObjectGroupId(g2s1.location(), UniqueId(2)); - global_handles->SetObjectGroupId(g2s2.location(), UniqueId(2)); - global_handles->SetRetainedObjectInfo(UniqueId(2), &info2); - global_handles->SetObjectGroupId(g1s1.location(), UniqueId(1)); - global_handles->SetObjectGroupId(g1s2.location(), UniqueId(1)); - global_handles->SetRetainedObjectInfo(UniqueId(1), &info1); - - // Iterate the object groups. First skip all. - { - ResetCanSkipData(); - skippable_objects.Add(*g1s1.location()); - skippable_objects.Add(*g1s2.location()); - skippable_objects.Add(*g2s1.location()); - skippable_objects.Add(*g2s2.location()); - TestObjectVisitor visitor; - global_handles->IterateObjectGroups(&visitor, &CanSkipCallback); - - // CanSkipCallback was called for all objects. - CHECK(can_skip_called_objects.length() == 4); - CHECK(can_skip_called_objects.Contains(*g1s1.location())); - CHECK(can_skip_called_objects.Contains(*g1s2.location())); - CHECK(can_skip_called_objects.Contains(*g2s1.location())); - CHECK(can_skip_called_objects.Contains(*g2s2.location())); - - // Nothing was visited. - CHECK(visitor.visited.length() == 0); - CHECK(!info1.has_been_disposed()); - CHECK(!info2.has_been_disposed()); - } - - // Iterate again, now only skip the second object group. - { - ResetCanSkipData(); - // The first grough should still be visited, since only one object is - // skipped. - skippable_objects.Add(*g1s1.location()); - skippable_objects.Add(*g2s1.location()); - skippable_objects.Add(*g2s2.location()); - TestObjectVisitor visitor; - global_handles->IterateObjectGroups(&visitor, &CanSkipCallback); - - // CanSkipCallback was called for all objects. - CHECK(can_skip_called_objects.length() == 3 || - can_skip_called_objects.length() == 4); - CHECK(can_skip_called_objects.Contains(*g1s2.location())); - CHECK(can_skip_called_objects.Contains(*g2s1.location())); - CHECK(can_skip_called_objects.Contains(*g2s2.location())); - - // The first group was visited. - CHECK(visitor.visited.length() == 2); - CHECK(visitor.visited.Contains(*g1s1.location())); - CHECK(visitor.visited.Contains(*g1s2.location())); - CHECK(info1.has_been_disposed()); - CHECK(!info2.has_been_disposed()); - } - - // Iterate again, don't skip anything. - { - ResetCanSkipData(); - TestObjectVisitor visitor; - global_handles->IterateObjectGroups(&visitor, &CanSkipCallback); - - // CanSkipCallback was called for all objects. - CHECK(can_skip_called_objects.length() == 1); - CHECK(can_skip_called_objects.Contains(*g2s1.location()) || - can_skip_called_objects.Contains(*g2s2.location())); - - // The second group was visited. - CHECK(visitor.visited.length() == 2); - CHECK(visitor.visited.Contains(*g2s1.location())); - CHECK(visitor.visited.Contains(*g2s2.location())); - CHECK(info2.has_been_disposed()); - } -} - - -TEST(ImplicitReferences) { - CcTest::InitializeVM(); - Isolate* isolate = CcTest::i_isolate(); - GlobalHandles* global_handles = isolate->global_handles(); - - v8::HandleScope handle_scope(CcTest::isolate()); - - Handle g1s1 = - global_handles->Create(*isolate->factory()->NewFixedArray(1)); - Handle g1c1 = - global_handles->Create(*isolate->factory()->NewFixedArray(1)); - Handle g1c2 = - global_handles->Create(*isolate->factory()->NewFixedArray(1)); - - - Handle g2s1 = - global_handles->Create(*isolate->factory()->NewFixedArray(1)); - Handle g2s2 = - global_handles->Create(*isolate->factory()->NewFixedArray(1)); - Handle g2c1 = - global_handles->Create(*isolate->factory()->NewFixedArray(1)); - - global_handles->SetObjectGroupId(g1s1.location(), UniqueId(1)); - global_handles->SetObjectGroupId(g2s1.location(), UniqueId(2)); - global_handles->SetObjectGroupId(g2s2.location(), UniqueId(2)); - global_handles->SetReferenceFromGroup(UniqueId(1), g1c1.location()); - global_handles->SetReferenceFromGroup(UniqueId(1), g1c2.location()); - global_handles->SetReferenceFromGroup(UniqueId(2), g2c1.location()); - - List* implicit_refs = - global_handles->implicit_ref_groups(); - USE(implicit_refs); - CHECK(implicit_refs->length() == 2); - CHECK(implicit_refs->at(0)->parent == - reinterpret_cast(g1s1.location())); - CHECK(implicit_refs->at(0)->length == 2); - CHECK(implicit_refs->at(0)->children[0] == g1c1.location()); - CHECK(implicit_refs->at(0)->children[1] == g1c2.location()); - CHECK(implicit_refs->at(1)->parent == - reinterpret_cast(g2s1.location())); - CHECK(implicit_refs->at(1)->length == 1); - CHECK(implicit_refs->at(1)->children[0] == g2c1.location()); - global_handles->RemoveObjectGroups(); - global_handles->RemoveImplicitRefGroups(); -} - - TEST(EternalHandles) { CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate();