diff options
Diffstat (limited to 'deps/v8/src/profiler/heap-snapshot-generator.cc')
-rw-r--r-- | deps/v8/src/profiler/heap-snapshot-generator.cc | 133 |
1 files changed, 109 insertions, 24 deletions
diff --git a/deps/v8/src/profiler/heap-snapshot-generator.cc b/deps/v8/src/profiler/heap-snapshot-generator.cc index b51ea0de7e4..96ac785273c 100644 --- a/deps/v8/src/profiler/heap-snapshot-generator.cc +++ b/deps/v8/src/profiler/heap-snapshot-generator.cc @@ -6,7 +6,7 @@ #include <utility> -#include "src/api.h" +#include "src/api-inl.h" #include "src/code-stubs.h" #include "src/conversions.h" #include "src/debug/debug.h" @@ -16,7 +16,10 @@ #include "src/objects-inl.h" #include "src/objects/api-callbacks.h" #include "src/objects/hash-table-inl.h" +#include "src/objects/js-array-buffer-inl.h" +#include "src/objects/js-array-inl.h" #include "src/objects/js-collection-inl.h" +#include "src/objects/js-generator-inl.h" #include "src/objects/js-promise-inl.h" #include "src/objects/js-regexp-inl.h" #include "src/objects/literal-objects-inl.h" @@ -246,6 +249,9 @@ HeapEntry* HeapSnapshot::AddGcSubrootEntry(Root root, SnapshotObjectId id) { return entry; } +void HeapSnapshot::AddLocation(int entry, int scriptId, int line, int col) { + locations_.emplace_back(entry, scriptId, line, col); +} HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, const char* name, @@ -608,6 +614,33 @@ HeapEntry* V8HeapExplorer::AllocateEntry(HeapThing ptr) { return AddEntry(reinterpret_cast<HeapObject*>(ptr)); } +void V8HeapExplorer::ExtractLocation(int entry, HeapObject* object) { + if (object->IsJSFunction()) { + JSFunction* func = JSFunction::cast(object); + ExtractLocationForJSFunction(entry, func); + + } else if (object->IsJSGeneratorObject()) { + JSGeneratorObject* gen = JSGeneratorObject::cast(object); + ExtractLocationForJSFunction(entry, gen->function()); + + } else if (object->IsJSObject()) { + JSObject* obj = JSObject::cast(object); + JSFunction* maybe_constructor = GetConstructor(obj); + + if (maybe_constructor) + ExtractLocationForJSFunction(entry, maybe_constructor); + } +} + +void V8HeapExplorer::ExtractLocationForJSFunction(int entry, JSFunction* func) { + if (!func->shared()->script()->IsScript()) return; + Script* script = Script::cast(func->shared()->script()); + int scriptId = script->id(); + int start = func->shared()->StartPosition(); + int line = script->GetLineNumber(start); + int col = script->GetColumnNumber(start); + snapshot_->AddLocation(entry, scriptId, line, col); +} HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) { if (object->IsJSFunction()) { @@ -854,6 +887,8 @@ void V8HeapExplorer::ExtractReferences(int entry, HeapObject* obj) { ExtractJSCollectionReferences(entry, JSMap::cast(obj)); } else if (obj->IsJSPromise()) { ExtractJSPromiseReferences(entry, JSPromise::cast(obj)); + } else if (obj->IsJSGeneratorObject()) { + ExtractJSGeneratorObjectReferences(entry, JSGeneratorObject::cast(obj)); } ExtractJSObjectReferences(entry, JSObject::cast(obj)); } else if (obj->IsString()) { @@ -876,8 +911,6 @@ void V8HeapExplorer::ExtractReferences(int entry, HeapObject* obj) { ExtractCellReferences(entry, Cell::cast(obj)); } else if (obj->IsFeedbackCell()) { ExtractFeedbackCellReferences(entry, FeedbackCell::cast(obj)); - } else if (obj->IsWeakCell()) { - ExtractWeakCellReferences(entry, WeakCell::cast(obj)); } else if (obj->IsPropertyCell()) { ExtractPropertyCellReferences(entry, PropertyCell::cast(obj)); } else if (obj->IsAllocationSite()) { @@ -1119,8 +1152,6 @@ void V8HeapExplorer::ExtractMapReferences(int entry, Map* map) { Map::kTransitionsOrPrototypeInfoOffset); } else if (maybe_raw_transitions_or_prototype_info->ToStrongHeapObject( &raw_transitions_or_prototype_info)) { - DCHECK(!raw_transitions_or_prototype_info->IsWeakCell()); - if (raw_transitions_or_prototype_info->IsTransitionArray()) { TransitionArray* transitions = TransitionArray::cast(raw_transitions_or_prototype_info); @@ -1172,9 +1203,6 @@ void V8HeapExplorer::ExtractMapReferences(int entry, Map* map) { TagObject(map->dependent_code(), "(dependent code)"); SetInternalReference(map, entry, "dependent_code", map->dependent_code(), Map::kDependentCodeOffset); - TagObject(map->weak_cell_cache(), "(weak cell)"); - SetInternalReference(map, entry, "weak_cell_cache", map->weak_cell_cache(), - Map::kWeakCellCacheOffset); } @@ -1198,17 +1226,13 @@ void V8HeapExplorer::ExtractSharedFunctionInfoReferences( SetInternalReference(obj, entry, "name_or_scope_info", shared->name_or_scope_info(), SharedFunctionInfo::kNameOrScopeInfoOffset); - SetInternalReference(obj, entry, - "script", shared->script(), - SharedFunctionInfo::kScriptOffset); + SetInternalReference(obj, entry, "script_or_debug_info", + shared->script_or_debug_info(), + SharedFunctionInfo::kScriptOrDebugInfoOffset); SetInternalReference(obj, entry, "function_data", shared->function_data(), SharedFunctionInfo::kFunctionDataOffset); SetInternalReference( - obj, entry, "function_identifier_or_debug_info", - shared->function_identifier_or_debug_info(), - SharedFunctionInfo::kFunctionIdentifierOrDebugInfoOffset); - SetInternalReference( obj, entry, "raw_outer_scope_info_or_feedback_metadata", shared->raw_outer_scope_info_or_feedback_metadata(), SharedFunctionInfo::kOuterScopeInfoOrFeedbackMetadataOffset); @@ -1294,12 +1318,6 @@ void V8HeapExplorer::ExtractFeedbackCellReferences( FeedbackCell::kValueOffset); } -void V8HeapExplorer::ExtractWeakCellReferences(int entry, WeakCell* weak_cell) { - TagObject(weak_cell, "(weak cell)"); - SetWeakReference(weak_cell, entry, "value", weak_cell->value(), - WeakCell::kValueOffset); -} - void V8HeapExplorer::ExtractPropertyCellReferences(int entry, PropertyCell* cell) { SetInternalReference(cell, entry, "value", cell->value(), @@ -1363,6 +1381,19 @@ void V8HeapExplorer::ExtractJSPromiseReferences(int entry, JSPromise* promise) { JSPromise::kReactionsOrResultOffset); } +void V8HeapExplorer::ExtractJSGeneratorObjectReferences( + int entry, JSGeneratorObject* generator) { + SetInternalReference(generator, entry, "function", generator->function(), + JSGeneratorObject::kFunctionOffset); + SetInternalReference(generator, entry, "context", generator->context(), + JSGeneratorObject::kContextOffset); + SetInternalReference(generator, entry, "receiver", generator->receiver(), + JSGeneratorObject::kReceiverOffset); + SetInternalReference(generator, entry, "parameters_and_registers", + generator->parameters_and_registers(), + JSGeneratorObject::kParametersAndRegistersOffset); +} + void V8HeapExplorer::ExtractFixedArrayReferences(int entry, FixedArray* array) { for (int i = 0, l = array->length(); i < l; ++i) { DCHECK(!HasWeakHeapObjectTag(array->get(i))); @@ -1513,6 +1544,17 @@ void V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj, int entry) { } } +JSFunction* V8HeapExplorer::GetConstructor(JSReceiver* receiver) { + Isolate* isolate = receiver->GetIsolate(); + DisallowHeapAllocation no_gc; + HandleScope scope(isolate); + MaybeHandle<JSFunction> maybe_constructor = + JSReceiver::GetConstructor(handle(receiver, isolate)); + + if (maybe_constructor.is_null()) return nullptr; + + return *maybe_constructor.ToHandleChecked(); +} String* V8HeapExplorer::GetConstructorName(JSObject* object) { Isolate* isolate = object->GetIsolate(); @@ -1602,6 +1644,9 @@ bool V8HeapExplorer::IterateAndExtractReferences(SnapshotFiller* filler) { DCHECK(!visited_fields_[i]); } + // Extract location for specific object types + ExtractLocation(entry, obj); + if (!progress_->ProgressReport(false)) interrupted = true; } @@ -2630,6 +2675,11 @@ void HeapSnapshotJSONSerializer::SerializeImpl() { if (writer_->aborted()) return; writer_->AddString("],\n"); + writer_->AddString("\"locations\":["); + SerializeLocations(); + if (writer_->aborted()) return; + writer_->AddString("],\n"); + writer_->AddString("\"strings\":["); SerializeStrings(); if (writer_->aborted()) return; @@ -2709,7 +2759,7 @@ void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge, buffer[buffer_pos++] = ','; buffer_pos = utoa(edge_name_or_index, buffer, buffer_pos); buffer[buffer_pos++] = ','; - buffer_pos = utoa(entry_index(edge->to()), buffer, buffer_pos); + buffer_pos = utoa(to_node_index(edge->to()), buffer, buffer_pos); buffer[buffer_pos++] = '\n'; buffer[buffer_pos++] = '\0'; writer_->AddString(buffer.start()); @@ -2734,7 +2784,7 @@ void HeapSnapshotJSONSerializer::SerializeNode(const HeapEntry* entry) { + 6 + 1 + 1; EmbeddedVector<char, kBufferSize> buffer; int buffer_pos = 0; - if (entry_index(entry) != 0) { + if (to_node_index(entry) != 0) { buffer[buffer_pos++] = ','; } buffer_pos = utoa(entry->type(), buffer, buffer_pos); @@ -2767,6 +2817,8 @@ void HeapSnapshotJSONSerializer::SerializeSnapshot() { writer_->AddString("\"meta\":"); // The object describing node serialization layout. // We use a set of macros to improve readability. + +// clang-format off #define JSON_A(s) "[" s "]" #define JSON_O(s) "{" s "}" #define JSON_S(s) "\"" s "\"" @@ -2830,7 +2882,13 @@ void HeapSnapshotJSONSerializer::SerializeSnapshot() { JSON_S("children")) "," JSON_S("sample_fields") ":" JSON_A( JSON_S("timestamp_us") "," - JSON_S("last_assigned_id")))); + JSON_S("last_assigned_id")) "," + JSON_S("location_fields") ":" JSON_A( + JSON_S("object_index") "," + JSON_S("script_id") "," + JSON_S("line") "," + JSON_S("column")))); +// clang-format on #undef JSON_S #undef JSON_O #undef JSON_A @@ -3037,6 +3095,33 @@ void HeapSnapshotJSONSerializer::SerializeStrings() { } } +void HeapSnapshotJSONSerializer::SerializeLocation( + const SourceLocation& location) { + // The buffer needs space for 4 unsigned ints, 3 commas, \n and \0 + static const int kBufferSize = + MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned * 4 + 3 + 2; + EmbeddedVector<char, kBufferSize> buffer; + int buffer_pos = 0; + buffer_pos = utoa(to_node_index(location.entry_index), buffer, buffer_pos); + buffer[buffer_pos++] = ','; + buffer_pos = utoa(location.scriptId, buffer, buffer_pos); + buffer[buffer_pos++] = ','; + buffer_pos = utoa(location.line, buffer, buffer_pos); + buffer[buffer_pos++] = ','; + buffer_pos = utoa(location.col, buffer, buffer_pos); + buffer[buffer_pos++] = '\n'; + buffer[buffer_pos++] = '\0'; + writer_->AddString(buffer.start()); +} + +void HeapSnapshotJSONSerializer::SerializeLocations() { + const std::vector<SourceLocation>& locations = snapshot_->locations(); + for (size_t i = 0; i < locations.size(); i++) { + if (i > 0) writer_->AddCharacter(','); + SerializeLocation(locations[i]); + if (writer_->aborted()) return; + } +} } // namespace internal } // namespace v8 |