Commit fd43661c authored by hlopko's avatar hlopko Committed by Commit bot

Add flag to trace object groups

BUG=chromium:468240
LOG=no

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

Cr-Commit-Position: refs/heads/master@{#34634}
parent 32b3d3e9
......@@ -727,6 +727,9 @@ DEFINE_INT(heap_growing_percent, 0,
DEFINE_INT(histogram_interval, 600000,
"time interval in ms for aggregating memory histograms")
// global-handles.cc
DEFINE_BOOL(trace_object_groups, false,
"print object groups detected during each garbage collection")
// heap-snapshot-generator.cc
DEFINE_BOOL(heap_profiler_trace_objects, false,
......
......@@ -811,6 +811,111 @@ 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:
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", 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()) {
if (js_object->IsOddball()) {
PrintF("<oddball>");
} else {
PrintF("<null>");
}
} else {
UNREACHABLE();
}
}
void ObjectGroupsTracer::PrintInternalFields(JSObject* js_object) {
for (int i = 0; i < js_object->GetInternalFieldCount(); ++i) {
if (i != 0) {
PrintF(", ");
}
PrintF("%p", js_object->GetInternalField(i));
}
}
void ObjectGroupsTracer::PrintObjectGroup(ObjectGroup* group) {
PrintIsolate(isolate_, "ObjectGroup (size: %lu)\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: %lu)\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<PendingPhantomCallback>* callbacks, Isolate* isolate) {
......
......@@ -242,6 +242,9 @@ class GlobalHandles {
// 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.
......
......@@ -1398,6 +1398,10 @@ void Heap::CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags) {
}
}
}
if (FLAG_trace_object_groups && (gc_type == kGCTypeIncrementalMarking ||
gc_type == kGCTypeMarkSweepCompact)) {
isolate_->global_handles()->PrintObjectGroups();
}
}
......
......@@ -105,7 +105,7 @@ class IncrementalMarking {
void Epilogue();
// Performs incremental marking steps of step_size_in_bytes as long as
// deadline_ins_ms is not reached. step_size_in_bytes can be 0 to compute
// deadline_in_ms is not reached. step_size_in_bytes can be 0 to compute
// an estimate increment. Returns the remaining time that cannot be used
// for incremental marking anymore because a single step would exceed the
// deadline.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment