Chromium Code Reviews| Index: src/global-handles.cc |
| diff --git a/src/global-handles.cc b/src/global-handles.cc |
| index 404f3ad16789c0fae684b6a496dc91b24b83a831..f25fdce8522318f6d8a1367f23670673e78a862c 100644 |
| --- a/src/global-handles.cc |
| +++ b/src/global-handles.cc |
| @@ -769,6 +769,10 @@ void GlobalHandles::IterateNewSpaceWeakUnmodifiedRoots(ObjectVisitor* v) { |
| bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, |
| WeakSlotCallbackWithHeap can_skip) { |
| ComputeObjectGroupsAndImplicitReferences(); |
| + if (FLAG_trace_object_groups) { |
| + ObjectGroupsTracer(isolate_).CollectTraces(); |
|
ulan
2016/03/08 20:23:32
Not needed anymore.
Marcel Hlopko
2016/03/09 09:30:30
Done.
|
| + } |
| + |
| int last = 0; |
| bool any_group_was_visited = false; |
| for (int i = 0; i < object_groups_.length(); i++) { |
| @@ -811,6 +815,143 @@ bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, |
| 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: |
| + class HasDumpObject { |
| + public: |
| + void DumpObject(Object* object); |
| + |
| + private: |
| + void DumpConstructor(JSObject* js_object); |
| + void DumpInternalFields(JSObject* js_object); |
| + }; |
| + |
| + class ObjectGroupVisitor : public HasDumpObject { |
| + public: |
| + explicit ObjectGroupVisitor(Isolate* isolate); |
| + void Apply(ObjectGroup** group); |
| + |
| + private: |
| + Isolate* isolate_; |
| + }; |
| + |
| + class ImplicitRefGroupVisitor : public HasDumpObject { |
| + public: |
| + explicit ImplicitRefGroupVisitor(Isolate* isolate); |
| + void Apply(ImplicitRefGroup** group); |
| + |
| + private: |
| + Isolate* isolate_; |
| + }; |
| + |
| + explicit ObjectGroupsTracer(Isolate* isolate); |
| + void CollectTraces(); |
| + |
| + private: |
| + Isolate* isolate_; |
| + DISALLOW_COPY_AND_ASSIGN(ObjectGroupsTracer); |
| +}; |
| + |
| +ObjectGroupsTracer::ObjectGroupsTracer(Isolate* isolate) : isolate_(isolate) {} |
| + |
| +void ObjectGroupsTracer::CollectTraces() { |
| + GlobalHandles* global_handles = isolate_->global_handles(); |
| + ObjectGroupVisitor object_groups_visitor(isolate_); |
| + ImplicitRefGroupVisitor implicit_ref_groups_visitor(isolate_); |
| + |
| + PrintIsolate(isolate_, "### Tracing object groups:\n"); |
| + |
| + global_handles->object_groups()->Iterate(&object_groups_visitor); |
| + global_handles->implicit_ref_groups()->Iterate(&implicit_ref_groups_visitor); |
| + |
| + PrintIsolate(isolate_, "### Tracing object groups finished.\n"); |
| +} |
| + |
| +void ObjectGroupsTracer::HasDumpObject::DumpObject(Object* o) { |
| + JSObject* js_object = reinterpret_cast<JSObject*>(o); |
| + |
| + PrintF("{ constructor_name: "); |
| + DumpConstructor(js_object); |
| + PrintF(", hidden_fields: [ "); |
| + DumpInternalFields(js_object); |
| + PrintF(" ] }\n"); |
| +} |
| + |
| +void ObjectGroupsTracer::HasDumpObject::DumpConstructor(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()) { |
| + if (js_object->IsOddball()) { |
| + PrintF("<oddball>"); |
| + } else { |
| + PrintF("<null>"); |
| + } |
| + } else { |
| + PrintF("boo will crash\n"); |
| + maybe_constructor->Print(); |
| + UNREACHABLE(); |
| + } |
| +} |
| + |
| +void ObjectGroupsTracer::HasDumpObject::DumpInternalFields( |
| + JSObject* js_object) { |
| + if (js_object->IsOddball()) { |
| + return; |
| + } |
| + |
| + for (int i = 0; i < js_object->GetInternalFieldCount(); ++i) { |
| + if (i != 0) { |
| + PrintF(", "); |
| + } |
| + PrintF("%p", js_object->GetInternalField(i)); |
| + } |
| +} |
| + |
| +ObjectGroupsTracer::ObjectGroupVisitor::ObjectGroupVisitor(Isolate* isolate) |
| + : isolate_(isolate) {} |
| + |
| +ObjectGroupsTracer::ImplicitRefGroupVisitor::ImplicitRefGroupVisitor( |
| + Isolate* isolate) |
| + : isolate_(isolate) {} |
| + |
| +void ObjectGroupsTracer::ObjectGroupVisitor::Apply(ObjectGroup** p) { |
| + ObjectGroup* group = *p; |
| + PrintIsolate(isolate_, "ObjectGroup (size: %lu)\n", group->length); |
| + Object*** objects = group->objects; |
| + |
| + for (size_t i = 0; i < group->length; ++i) { |
| + PrintIsolate(isolate_, " - Member: "); |
| + DumpObject(*objects[i]); |
| + } |
| +} |
| + |
| +void ObjectGroupsTracer::ImplicitRefGroupVisitor::Apply(ImplicitRefGroup** p) { |
| + ImplicitRefGroup* group = *p; |
| + PrintIsolate(isolate_, "ImplicitRefGroup (children count: %lu)\n", |
| + group->length); |
| + PrintIsolate(isolate_, " - Parent: "); |
| + DumpObject(*(group->parent)); |
| + |
| + Object*** children = group->children; |
| + for (size_t i = 0; i < group->length; ++i) { |
| + PrintIsolate(isolate_, " - Child: "); |
| + DumpObject(*children[i]); |
| + } |
| +} |
| + |
| +} // namespace |
| + |
| +void GlobalHandles::PrintObjectGroups() { |
| + ObjectGroupsTracer(isolate_).CollectTraces(); |
| +} |
| void GlobalHandles::InvokeSecondPassPhantomCallbacks( |
| List<PendingPhantomCallback>* callbacks, Isolate* isolate) { |