Commit ee72b7a1 authored by Seth Brenith's avatar Seth Brenith Committed by V8 LUCI CQ

Categorize object shape info in heap snapshots

One of the biggest categories in heap snapshots is named “(system)”,
which gives developers no indication of why all that memory is used or
what they might do to reduce it. In this change, I propose that we
create a new category for Maps, DescriptorArrays, and related objects,
and call this new category “(object shape)” in the devtools. I think
that this category name would be more meaningful, while still grouping
those objects together so that they mostly stay out of the way.

Bug: v8:12769
Doc: https://docs.google.com/document/d/1a-6V_2LIJuRcsppwh6E18g8OSnC9j6gN4ao2gq--BiU
Change-Id: I282a7b87c34ca6ed371ff32f3c7332d794ae42ca
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3587974Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Seth Brenith <seth.brenith@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#80123}
parent 370cae1d
...@@ -542,7 +542,9 @@ class V8_EXPORT HeapGraphNode { ...@@ -542,7 +542,9 @@ class V8_EXPORT HeapGraphNode {
kConsString = 10, // Concatenated string. A pair of pointers to strings. kConsString = 10, // Concatenated string. A pair of pointers to strings.
kSlicedString = 11, // Sliced string. A fragment of another string. kSlicedString = 11, // Sliced string. A fragment of another string.
kSymbol = 12, // A Symbol (ES6). kSymbol = 12, // A Symbol (ES6).
kBigInt = 13 // BigInt. kBigInt = 13, // BigInt.
kObjectShape = 14, // Internal data used for tracking the shapes (or
// "hidden classes") of JS objects.
}; };
/** Returns node type (see HeapGraphNode::Type). */ /** Returns node type (see HeapGraphNode::Type). */
......
...@@ -380,6 +380,8 @@ const char* HeapEntry::TypeAsString() const { ...@@ -380,6 +380,8 @@ const char* HeapEntry::TypeAsString() const {
case kSymbol: return "/symbol/"; case kSymbol: return "/symbol/";
case kBigInt: case kBigInt:
return "/bigint/"; return "/bigint/";
case kObjectShape:
return "/object shape/";
default: return "???"; default: return "???";
} }
} }
...@@ -955,6 +957,17 @@ HeapEntry::Type V8HeapExplorer::GetSystemEntryType(HeapObject object) { ...@@ -955,6 +957,17 @@ HeapEntry::Type V8HeapExplorer::GetSystemEntryType(HeapObject object) {
return HeapEntry::kArray; return HeapEntry::kArray;
} }
// Maps in read-only space are for internal V8 data, not user-defined object
// shapes.
if ((InstanceTypeChecker::IsMap(type) &&
!BasicMemoryChunk::FromHeapObject(object)->InReadOnlySpace()) ||
InstanceTypeChecker::IsDescriptorArray(type) ||
InstanceTypeChecker::IsTransitionArray(type) ||
InstanceTypeChecker::IsPrototypeInfo(type) ||
InstanceTypeChecker::IsEnumCache(type)) {
return HeapEntry::kObjectShape;
}
return HeapEntry::kHidden; return HeapEntry::kHidden;
} }
...@@ -1098,6 +1111,8 @@ void V8HeapExplorer::ExtractReferences(HeapEntry* entry, HeapObject obj) { ...@@ -1098,6 +1111,8 @@ void V8HeapExplorer::ExtractReferences(HeapEntry* entry, HeapObject obj) {
ExtractFeedbackCellReferences(entry, FeedbackCell::cast(obj)); ExtractFeedbackCellReferences(entry, FeedbackCell::cast(obj));
} else if (obj.IsPropertyCell()) { } else if (obj.IsPropertyCell()) {
ExtractPropertyCellReferences(entry, PropertyCell::cast(obj)); ExtractPropertyCellReferences(entry, PropertyCell::cast(obj));
} else if (obj.IsPrototypeInfo()) {
ExtractPrototypeInfoReferences(entry, PrototypeInfo::cast(obj));
} else if (obj.IsAllocationSite()) { } else if (obj.IsAllocationSite()) {
ExtractAllocationSiteReferences(entry, AllocationSite::cast(obj)); ExtractAllocationSiteReferences(entry, AllocationSite::cast(obj));
} else if (obj.IsArrayBoilerplateDescription()) { } else if (obj.IsArrayBoilerplateDescription()) {
...@@ -1110,6 +1125,10 @@ void V8HeapExplorer::ExtractReferences(HeapEntry* entry, HeapObject obj) { ...@@ -1110,6 +1125,10 @@ void V8HeapExplorer::ExtractReferences(HeapEntry* entry, HeapObject obj) {
ExtractFeedbackVectorReferences(entry, FeedbackVector::cast(obj)); ExtractFeedbackVectorReferences(entry, FeedbackVector::cast(obj));
} else if (obj.IsDescriptorArray()) { } else if (obj.IsDescriptorArray()) {
ExtractDescriptorArrayReferences(entry, DescriptorArray::cast(obj)); ExtractDescriptorArrayReferences(entry, DescriptorArray::cast(obj));
} else if (obj.IsEnumCache()) {
ExtractEnumCacheReferences(entry, EnumCache::cast(obj));
} else if (obj.IsTransitionArray()) {
ExtractTransitionArrayReferences(entry, TransitionArray::cast(obj));
} else if (obj.IsWeakFixedArray()) { } else if (obj.IsWeakFixedArray()) {
ExtractWeakArrayReferences(WeakFixedArray::kHeaderSize, entry, ExtractWeakArrayReferences(WeakFixedArray::kHeaderSize, entry,
WeakFixedArray::cast(obj)); WeakFixedArray::cast(obj));
...@@ -1412,6 +1431,8 @@ void V8HeapExplorer::ExtractMapReferences(HeapEntry* entry, Map map) { ...@@ -1412,6 +1431,8 @@ void V8HeapExplorer::ExtractMapReferences(HeapEntry* entry, Map map) {
TagObject(map.dependent_code(), "(dependent code)"); TagObject(map.dependent_code(), "(dependent code)");
SetInternalReference(entry, "dependent_code", map.dependent_code(), SetInternalReference(entry, "dependent_code", map.dependent_code(),
Map::kDependentCodeOffset); Map::kDependentCodeOffset);
TagObject(map.prototype_validity_cell(), "(prototype validity cell)",
HeapEntry::kObjectShape);
} }
void V8HeapExplorer::ExtractSharedFunctionInfoReferences( void V8HeapExplorer::ExtractSharedFunctionInfoReferences(
...@@ -1556,6 +1577,14 @@ void V8HeapExplorer::ExtractPropertyCellReferences(HeapEntry* entry, ...@@ -1556,6 +1577,14 @@ void V8HeapExplorer::ExtractPropertyCellReferences(HeapEntry* entry,
PropertyCell::kDependentCodeOffset); PropertyCell::kDependentCodeOffset);
} }
void V8HeapExplorer::ExtractPrototypeInfoReferences(HeapEntry* entry,
PrototypeInfo info) {
TagObject(info.prototype_chain_enum_cache(), "(prototype chain enum cache)",
HeapEntry::kObjectShape);
TagObject(info.prototype_users(), "(prototype users)",
HeapEntry::kObjectShape);
}
void V8HeapExplorer::ExtractAllocationSiteReferences(HeapEntry* entry, void V8HeapExplorer::ExtractAllocationSiteReferences(HeapEntry* entry,
AllocationSite site) { AllocationSite site) {
SetInternalReference(entry, "transition_info", SetInternalReference(entry, "transition_info",
...@@ -1723,6 +1752,20 @@ void V8HeapExplorer::ExtractDescriptorArrayReferences(HeapEntry* entry, ...@@ -1723,6 +1752,20 @@ void V8HeapExplorer::ExtractDescriptorArrayReferences(HeapEntry* entry,
} }
} }
void V8HeapExplorer::ExtractEnumCacheReferences(HeapEntry* entry,
EnumCache cache) {
TagObject(cache.keys(), "(enum cache)", HeapEntry::kObjectShape);
TagObject(cache.indices(), "(enum cache)", HeapEntry::kObjectShape);
}
void V8HeapExplorer::ExtractTransitionArrayReferences(
HeapEntry* entry, TransitionArray transitions) {
if (transitions.HasPrototypeTransitions()) {
TagObject(transitions.GetPrototypeTransitions(), "(prototype transitions)",
HeapEntry::kObjectShape);
}
}
template <typename T> template <typename T>
void V8HeapExplorer::ExtractWeakArrayReferences(int header_size, void V8HeapExplorer::ExtractWeakArrayReferences(int header_size,
HeapEntry* entry, T array) { HeapEntry* entry, T array) {
...@@ -3015,7 +3058,8 @@ void HeapSnapshotJSONSerializer::SerializeSnapshot() { ...@@ -3015,7 +3058,8 @@ void HeapSnapshotJSONSerializer::SerializeSnapshot() {
JSON_S("concatenated string") "," JSON_S("concatenated string") ","
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("string") "," JSON_S("string") ","
JSON_S("number") "," JSON_S("number") ","
JSON_S("number") "," JSON_S("number") ","
......
...@@ -118,7 +118,8 @@ class HeapEntry { ...@@ -118,7 +118,8 @@ class HeapEntry {
kConsString = v8::HeapGraphNode::kConsString, kConsString = v8::HeapGraphNode::kConsString,
kSlicedString = v8::HeapGraphNode::kSlicedString, kSlicedString = v8::HeapGraphNode::kSlicedString,
kSymbol = v8::HeapGraphNode::kSymbol, kSymbol = v8::HeapGraphNode::kSymbol,
kBigInt = v8::HeapGraphNode::kBigInt kBigInt = v8::HeapGraphNode::kBigInt,
kObjectShape = v8::HeapGraphNode::kObjectShape,
}; };
HeapEntry(HeapSnapshot* snapshot, int index, Type type, const char* name, HeapEntry(HeapSnapshot* snapshot, int index, Type type, const char* name,
...@@ -431,6 +432,7 @@ class V8_EXPORT_PRIVATE V8HeapExplorer : public HeapEntriesAllocator { ...@@ -431,6 +432,7 @@ class V8_EXPORT_PRIVATE V8HeapExplorer : public HeapEntriesAllocator {
void ExtractFeedbackCellReferences(HeapEntry* entry, void ExtractFeedbackCellReferences(HeapEntry* entry,
FeedbackCell feedback_cell); FeedbackCell feedback_cell);
void ExtractPropertyCellReferences(HeapEntry* entry, PropertyCell cell); void ExtractPropertyCellReferences(HeapEntry* entry, PropertyCell cell);
void ExtractPrototypeInfoReferences(HeapEntry* entry, PrototypeInfo info);
void ExtractAllocationSiteReferences(HeapEntry* entry, AllocationSite site); void ExtractAllocationSiteReferences(HeapEntry* entry, AllocationSite site);
void ExtractArrayBoilerplateDescriptionReferences( void ExtractArrayBoilerplateDescriptionReferences(
HeapEntry* entry, ArrayBoilerplateDescription value); HeapEntry* entry, ArrayBoilerplateDescription value);
...@@ -448,6 +450,9 @@ class V8_EXPORT_PRIVATE V8HeapExplorer : public HeapEntriesAllocator { ...@@ -448,6 +450,9 @@ class V8_EXPORT_PRIVATE V8HeapExplorer : public HeapEntriesAllocator {
FeedbackVector feedback_vector); FeedbackVector feedback_vector);
void ExtractDescriptorArrayReferences(HeapEntry* entry, void ExtractDescriptorArrayReferences(HeapEntry* entry,
DescriptorArray array); DescriptorArray array);
void ExtractEnumCacheReferences(HeapEntry* entry, EnumCache cache);
void ExtractTransitionArrayReferences(HeapEntry* entry,
TransitionArray transitions);
template <typename T> template <typename T>
void ExtractWeakArrayReferences(int header_size, HeapEntry* entry, T array); void ExtractWeakArrayReferences(int header_size, HeapEntry* entry, T array);
void ExtractPropertyReferences(JSObject js_obj, HeapEntry* entry); void ExtractPropertyReferences(JSObject js_obj, HeapEntry* entry);
......
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