[profiler] Support WasmGC objects in heap snapshots
Since the heap snapshot generator is based on generic objects-visiting infrastructure, it already reported all objects, but it showed WasmGC objects as generic "system" objects. This patch adds proper categorization, including support for named types and fields. Bug: v8:7748 Change-Id: I1b0997059c9cf0290fe5d6c5402412ba09ecf143 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4181031 Auto-Submit: Jakob Kummerow <jkummerow@chromium.org> Commit-Queue: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Camillo Bruni <cbruni@chromium.org> Cr-Commit-Position: refs/heads/main@{#85435}
This commit is contained in:
parent
186068ad3f
commit
4724f988ae
@ -596,6 +596,7 @@ class V8_EXPORT HeapGraphNode {
|
|||||||
kBigInt = 13, // BigInt.
|
kBigInt = 13, // BigInt.
|
||||||
kObjectShape = 14, // Internal data used for tracking the shapes (or
|
kObjectShape = 14, // Internal data used for tracking the shapes (or
|
||||||
// "hidden classes") of JS objects.
|
// "hidden classes") of JS objects.
|
||||||
|
kWasmObject = 15, // A WasmGC struct or array.
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Returns node type (see HeapGraphNode::Type). */
|
/** Returns node type (see HeapGraphNode::Type). */
|
||||||
|
@ -41,6 +41,12 @@
|
|||||||
#include "src/profiler/heap-snapshot-generator-inl.h"
|
#include "src/profiler/heap-snapshot-generator-inl.h"
|
||||||
#include "src/profiler/output-stream-writer.h"
|
#include "src/profiler/output-stream-writer.h"
|
||||||
|
|
||||||
|
#if V8_ENABLE_WEBASSEMBLY
|
||||||
|
#include "src/wasm/names-provider.h"
|
||||||
|
#include "src/wasm/string-builder.h"
|
||||||
|
#include "src/wasm/wasm-objects.h"
|
||||||
|
#endif // V8_ENABLE_WEBASSEMBLY
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
@ -385,6 +391,8 @@ const char* HeapEntry::TypeAsString() const {
|
|||||||
return "/bigint/";
|
return "/bigint/";
|
||||||
case kObjectShape:
|
case kObjectShape:
|
||||||
return "/object shape/";
|
return "/object shape/";
|
||||||
|
case kWasmObject:
|
||||||
|
return "/wasm object/";
|
||||||
default: return "???";
|
default: return "???";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -873,6 +881,23 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject object) {
|
|||||||
} else if (InstanceTypeChecker::IsHeapNumber(instance_type)) {
|
} else if (InstanceTypeChecker::IsHeapNumber(instance_type)) {
|
||||||
return AddEntry(object, HeapEntry::kHeapNumber, "heap number");
|
return AddEntry(object, HeapEntry::kHeapNumber, "heap number");
|
||||||
}
|
}
|
||||||
|
#if V8_ENABLE_WEBASSEMBLY
|
||||||
|
if (InstanceTypeChecker::IsWasmObject(instance_type)) {
|
||||||
|
WasmTypeInfo info = object.map().wasm_type_info();
|
||||||
|
wasm::NamesProvider* names =
|
||||||
|
info.instance().module_object().native_module()->GetNamesProvider();
|
||||||
|
wasm::StringBuilder sb;
|
||||||
|
if (InstanceTypeChecker::IsWasmStruct(instance_type)) {
|
||||||
|
sb << "wasm struct / ";
|
||||||
|
} else {
|
||||||
|
sb << "wasm array / ";
|
||||||
|
}
|
||||||
|
names->PrintTypeName(sb, info.type_index());
|
||||||
|
sb << '\0';
|
||||||
|
const char* name = names_->GetCopy(sb.start());
|
||||||
|
return AddEntry(object, HeapEntry::kWasmObject, name);
|
||||||
|
}
|
||||||
|
#endif // V8_ENABLE_WEBASSEMBLY
|
||||||
return AddEntry(object, GetSystemEntryType(object),
|
return AddEntry(object, GetSystemEntryType(object),
|
||||||
GetSystemEntryName(object));
|
GetSystemEntryName(object));
|
||||||
}
|
}
|
||||||
@ -1192,6 +1217,12 @@ void V8HeapExplorer::ExtractReferences(HeapEntry* entry, HeapObject obj) {
|
|||||||
ExtractBytecodeArrayReferences(entry, BytecodeArray::cast(obj));
|
ExtractBytecodeArrayReferences(entry, BytecodeArray::cast(obj));
|
||||||
} else if (obj.IsScopeInfo()) {
|
} else if (obj.IsScopeInfo()) {
|
||||||
ExtractScopeInfoReferences(entry, ScopeInfo::cast(obj));
|
ExtractScopeInfoReferences(entry, ScopeInfo::cast(obj));
|
||||||
|
#if V8_ENABLE_WEBASSEMBLY
|
||||||
|
} else if (obj.IsWasmStruct()) {
|
||||||
|
ExtractWasmStructReferences(WasmStruct::cast(obj), entry);
|
||||||
|
} else if (obj.IsWasmArray()) {
|
||||||
|
ExtractWasmArrayReferences(WasmArray::cast(obj), entry);
|
||||||
|
#endif // V8_ENABLE_WEBASSEMBLY
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1936,6 +1967,39 @@ void V8HeapExplorer::ExtractInternalReferences(JSObject js_obj,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if V8_ENABLE_WEBASSEMBLY
|
||||||
|
|
||||||
|
void V8HeapExplorer::ExtractWasmStructReferences(WasmStruct obj,
|
||||||
|
HeapEntry* entry) {
|
||||||
|
wasm::StructType* type = obj.type();
|
||||||
|
WasmTypeInfo info = obj.map().wasm_type_info();
|
||||||
|
wasm::NamesProvider* names =
|
||||||
|
info.instance().module_object().native_module()->GetNamesProvider();
|
||||||
|
for (uint32_t i = 0; i < type->field_count(); i++) {
|
||||||
|
if (!type->field(i).is_reference()) continue;
|
||||||
|
wasm::StringBuilder sb;
|
||||||
|
names->PrintFieldName(sb, info.type_index(), i);
|
||||||
|
sb << '\0';
|
||||||
|
const char* field_name = names_->GetCopy(sb.start());
|
||||||
|
int field_offset = type->field_offset(i);
|
||||||
|
Object value = obj.RawField(field_offset).load(entry->isolate());
|
||||||
|
HeapEntry* value_entry = GetEntry(value);
|
||||||
|
entry->SetNamedReference(HeapGraphEdge::kProperty, field_name, value_entry,
|
||||||
|
generator_);
|
||||||
|
MarkVisitedField(WasmStruct::kHeaderSize + field_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void V8HeapExplorer::ExtractWasmArrayReferences(WasmArray obj,
|
||||||
|
HeapEntry* entry) {
|
||||||
|
if (!obj.type()->element_type().is_reference()) return;
|
||||||
|
for (uint32_t i = 0; i < obj.length(); i++) {
|
||||||
|
SetElementReference(entry, i, obj.ElementSlot(i).load(entry->isolate()));
|
||||||
|
MarkVisitedField(obj.element_offset(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // V8_ENABLE_WEBASSEMBLY
|
||||||
|
|
||||||
JSFunction V8HeapExplorer::GetConstructor(Isolate* isolate,
|
JSFunction V8HeapExplorer::GetConstructor(Isolate* isolate,
|
||||||
JSReceiver receiver) {
|
JSReceiver receiver) {
|
||||||
DisallowGarbageCollection no_gc;
|
DisallowGarbageCollection no_gc;
|
||||||
@ -3001,7 +3065,8 @@ void HeapSnapshotJSONSerializer::SerializeSnapshot() {
|
|||||||
JSON_S("sliced string") ","
|
JSON_S("sliced string") ","
|
||||||
JSON_S("symbol") ","
|
JSON_S("symbol") ","
|
||||||
JSON_S("bigint") ","
|
JSON_S("bigint") ","
|
||||||
JSON_S("object shape")) ","
|
JSON_S("object shape") ","
|
||||||
|
JSON_S("wasm object")) ","
|
||||||
JSON_S("string") ","
|
JSON_S("string") ","
|
||||||
JSON_S("number") ","
|
JSON_S("number") ","
|
||||||
JSON_S("number") ","
|
JSON_S("number") ","
|
||||||
|
@ -120,6 +120,8 @@ class HeapEntry {
|
|||||||
kSymbol = v8::HeapGraphNode::kSymbol,
|
kSymbol = v8::HeapGraphNode::kSymbol,
|
||||||
kBigInt = v8::HeapGraphNode::kBigInt,
|
kBigInt = v8::HeapGraphNode::kBigInt,
|
||||||
kObjectShape = v8::HeapGraphNode::kObjectShape,
|
kObjectShape = v8::HeapGraphNode::kObjectShape,
|
||||||
|
kWasmObject = v8::HeapGraphNode::kWasmObject,
|
||||||
|
kNumTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
HeapEntry(HeapSnapshot* snapshot, int index, Type type, const char* name,
|
HeapEntry(HeapSnapshot* snapshot, int index, Type type, const char* name,
|
||||||
@ -189,7 +191,8 @@ class HeapEntry {
|
|||||||
V8_INLINE std::vector<HeapGraphEdge*>::iterator children_end() const;
|
V8_INLINE std::vector<HeapGraphEdge*>::iterator children_end() const;
|
||||||
const char* TypeAsString() const;
|
const char* TypeAsString() const;
|
||||||
|
|
||||||
unsigned type_: 4;
|
static_assert(kNumTypes <= 1 << 4);
|
||||||
|
unsigned type_ : 4;
|
||||||
unsigned index_ : 28; // Supports up to ~250M objects.
|
unsigned index_ : 28; // Supports up to ~250M objects.
|
||||||
union {
|
union {
|
||||||
// The count is used during the snapshot build phase,
|
// The count is used during the snapshot build phase,
|
||||||
@ -466,6 +469,11 @@ class V8_EXPORT_PRIVATE V8HeapExplorer : public HeapEntriesAllocator {
|
|||||||
void ExtractElementReferences(JSObject js_obj, HeapEntry* entry);
|
void ExtractElementReferences(JSObject js_obj, HeapEntry* entry);
|
||||||
void ExtractInternalReferences(JSObject js_obj, HeapEntry* entry);
|
void ExtractInternalReferences(JSObject js_obj, HeapEntry* entry);
|
||||||
|
|
||||||
|
#if V8_ENABLE_WEBASSEMBLY
|
||||||
|
void ExtractWasmStructReferences(WasmStruct obj, HeapEntry* entry);
|
||||||
|
void ExtractWasmArrayReferences(WasmArray obj, HeapEntry* entry);
|
||||||
|
#endif // V8_ENABLE_WEBASSEMBLY
|
||||||
|
|
||||||
bool IsEssentialObject(Object object);
|
bool IsEssentialObject(Object object);
|
||||||
bool IsEssentialHiddenReference(Object parent, int field_offset);
|
bool IsEssentialHiddenReference(Object parent, int field_offset);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user