[heap-profiler][torque] Report types of all internal objects
Heap-profiler changes: Currently, a whole lot of types are all reported as just "system" in heap snapshots. With this change, we can use Torque-generated macro lists to easily report type names such as "system / BytecodeArray". Those objects still show up in a single category named "(system)" in the dev tools UI, so they don't clutter the output. For V8 developers or anybody who is interested in an extra-detailed view, this change also includes a runtime flag that instructs V8 to upgrade nodes of type kHidden to type kNative. After a snapshot is collected with this flag enabled, the dev tools UI then shows each internal object type separately. Torque changes: Currently, Torque emits several macro lists containing pairs of (ClassName, CLASS_NAME_TYPE) which can be used to associate instance types with Torque class names. However, some Torque classes are not included in any of these three lists. In cases like the heap profiler, it would be nice to easily generate a complete list including every instance type, so this CL includes two changes: - Include classes in TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED even if they're not marked `extern`. I'm not sure what exactly we were hoping to accomplish in filtering by extern-ness, but it's simpler not to and slightly reduces clutter in a couple of files that use that macro list. - Add a fourth macro list for the previously-ignored category: classes which have their own instance type (are not `abstract`), and have subtypes, but do not have their fields defined in Torque. This list contains just a single item (HashTable), but I like the consistency of generating the full set of lists. Change-Id: Ib24953e12ed13ce353206bbec23a52d8f684dfcc Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2610172 Commit-Queue: Nico Hartmann <nicohartmann@chromium.org> Reviewed-by: Peter Marshall <petermarshall@chromium.org> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org> Cr-Commit-Position: refs/heads/master@{#72138}
This commit is contained in:
parent
4d5b878b61
commit
e3f8b5dba5
@ -182,7 +182,6 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
|
||||
case NUMBER_DICTIONARY_TYPE:
|
||||
case SIMPLE_NUMBER_DICTIONARY_TYPE:
|
||||
case EPHEMERON_HASH_TABLE_TYPE:
|
||||
case FIXED_ARRAY_TYPE:
|
||||
case SCOPE_INFO_TYPE:
|
||||
case SCRIPT_CONTEXT_TABLE_TYPE:
|
||||
FixedArray::cast(*this).FixedArrayVerify(isolate);
|
||||
@ -201,9 +200,6 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
|
||||
case NATIVE_CONTEXT_TYPE:
|
||||
NativeContext::cast(*this).NativeContextVerify(isolate);
|
||||
break;
|
||||
case WEAK_FIXED_ARRAY_TYPE:
|
||||
WeakFixedArray::cast(*this).WeakFixedArrayVerify(isolate);
|
||||
break;
|
||||
case FEEDBACK_METADATA_TYPE:
|
||||
FeedbackMetadata::cast(*this).FeedbackMetadataVerify(isolate);
|
||||
break;
|
||||
@ -221,7 +217,6 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
|
||||
case JS_ITERATOR_PROTOTYPE_TYPE:
|
||||
case JS_MAP_ITERATOR_PROTOTYPE_TYPE:
|
||||
case JS_OBJECT_PROTOTYPE_TYPE:
|
||||
case JS_OBJECT_TYPE:
|
||||
case JS_PROMISE_PROTOTYPE_TYPE:
|
||||
case JS_REG_EXP_PROTOTYPE_TYPE:
|
||||
case JS_SET_ITERATOR_PROTOTYPE_TYPE:
|
||||
@ -234,9 +229,6 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
|
||||
case WASM_INSTANCE_OBJECT_TYPE:
|
||||
WasmInstanceObject::cast(*this).WasmInstanceObjectVerify(isolate);
|
||||
break;
|
||||
case JS_GENERATOR_OBJECT_TYPE:
|
||||
JSGeneratorObject::cast(*this).JSGeneratorObjectVerify(isolate);
|
||||
break;
|
||||
case JS_SET_KEY_VALUE_ITERATOR_TYPE:
|
||||
case JS_SET_VALUE_ITERATOR_TYPE:
|
||||
JSSetIterator::cast(*this).JSSetIteratorVerify(isolate);
|
||||
@ -262,9 +254,6 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
|
||||
TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
|
||||
#undef MAKE_TORQUE_CASE
|
||||
|
||||
case FOREIGN_TYPE:
|
||||
break; // No interesting fields.
|
||||
|
||||
case ALLOCATION_SITE_TYPE:
|
||||
AllocationSite::cast(*this).AllocationSiteVerify(isolate);
|
||||
break;
|
||||
|
@ -100,9 +100,6 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
|
||||
}
|
||||
|
||||
switch (instance_type) {
|
||||
case FIXED_ARRAY_TYPE:
|
||||
FixedArray::cast(*this).FixedArrayPrint(os);
|
||||
break;
|
||||
case AWAIT_CONTEXT_TYPE:
|
||||
case BLOCK_CONTEXT_TYPE:
|
||||
case CATCH_CONTEXT_TYPE:
|
||||
@ -166,7 +163,6 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
|
||||
case JS_ITERATOR_PROTOTYPE_TYPE:
|
||||
case JS_MAP_ITERATOR_PROTOTYPE_TYPE:
|
||||
case JS_OBJECT_PROTOTYPE_TYPE:
|
||||
case JS_OBJECT_TYPE:
|
||||
case JS_PROMISE_PROTOTYPE_TYPE:
|
||||
case JS_REG_EXP_PROTOTYPE_TYPE:
|
||||
case JS_SET_ITERATOR_PROTOTYPE_TYPE:
|
||||
@ -179,9 +175,6 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
|
||||
case WASM_INSTANCE_OBJECT_TYPE:
|
||||
WasmInstanceObject::cast(*this).WasmInstanceObjectPrint(os);
|
||||
break;
|
||||
case JS_GENERATOR_OBJECT_TYPE:
|
||||
JSGeneratorObject::cast(*this).JSGeneratorObjectPrint(os);
|
||||
break;
|
||||
case CODE_TYPE:
|
||||
Code::cast(*this).CodePrint(os);
|
||||
break;
|
||||
@ -207,9 +200,6 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
|
||||
TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
|
||||
#undef MAKE_TORQUE_CASE
|
||||
|
||||
case FOREIGN_TYPE:
|
||||
Foreign::cast(*this).ForeignPrint(os);
|
||||
break;
|
||||
case ALLOCATION_SITE_TYPE:
|
||||
AllocationSite::cast(*this).AllocationSitePrint(os);
|
||||
break;
|
||||
@ -225,9 +215,6 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
|
||||
case FEEDBACK_METADATA_TYPE:
|
||||
FeedbackMetadata::cast(*this).FeedbackMetadataPrint(os);
|
||||
break;
|
||||
case WEAK_FIXED_ARRAY_TYPE:
|
||||
WeakFixedArray::cast(*this).WeakFixedArrayPrint(os);
|
||||
break;
|
||||
case INTERNALIZED_STRING_TYPE:
|
||||
case EXTERNAL_INTERNALIZED_STRING_TYPE:
|
||||
case ONE_BYTE_INTERNALIZED_STRING_TYPE:
|
||||
|
@ -1352,6 +1352,8 @@ DEFINE_BOOL(heap_profiler_use_embedder_graph, true,
|
||||
"Use the new EmbedderGraph API to get embedder nodes")
|
||||
DEFINE_INT(heap_snapshot_string_limit, 1024,
|
||||
"truncate strings to this length in the heap snapshot")
|
||||
DEFINE_BOOL(heap_profiler_show_hidden_objects, false,
|
||||
"use 'native' rather than 'hidden' node type in snapshot")
|
||||
|
||||
// sampling-heap-profiler.cc
|
||||
DEFINE_BOOL(sampling_heap_profiler_suppress_randomness, false,
|
||||
|
@ -646,6 +646,10 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject object) {
|
||||
|
||||
HeapEntry* V8HeapExplorer::AddEntry(HeapObject object, HeapEntry::Type type,
|
||||
const char* name) {
|
||||
if (FLAG_heap_profiler_show_hidden_objects && type == HeapEntry::kHidden) {
|
||||
type = HeapEntry::kNative;
|
||||
}
|
||||
|
||||
return AddEntry(object.address(), type, name, object.Size());
|
||||
}
|
||||
|
||||
@ -665,27 +669,35 @@ HeapEntry* V8HeapExplorer::AddEntry(Address address,
|
||||
}
|
||||
|
||||
const char* V8HeapExplorer::GetSystemEntryName(HeapObject object) {
|
||||
switch (object.map().instance_type()) {
|
||||
case MAP_TYPE:
|
||||
switch (Map::cast(object).instance_type()) {
|
||||
if (object.IsMap()) {
|
||||
switch (Map::cast(object).instance_type()) {
|
||||
#define MAKE_STRING_MAP_CASE(instance_type, size, name, Name) \
|
||||
case instance_type: return "system / Map (" #Name ")";
|
||||
STRING_TYPE_LIST(MAKE_STRING_MAP_CASE)
|
||||
#undef MAKE_STRING_MAP_CASE
|
||||
default: return "system / Map";
|
||||
}
|
||||
case CELL_TYPE: return "system / Cell";
|
||||
case PROPERTY_CELL_TYPE: return "system / PropertyCell";
|
||||
case FOREIGN_TYPE: return "system / Foreign";
|
||||
case ODDBALL_TYPE: return "system / Oddball";
|
||||
case ALLOCATION_SITE_TYPE:
|
||||
return "system / AllocationSite";
|
||||
#define MAKE_STRUCT_CASE(TYPE, Name, name) \
|
||||
case TYPE: \
|
||||
}
|
||||
}
|
||||
|
||||
switch (object.map().instance_type()) {
|
||||
#define MAKE_TORQUE_CASE(Name, TYPE) \
|
||||
case TYPE: \
|
||||
return "system / " #Name;
|
||||
STRUCT_LIST(MAKE_STRUCT_CASE)
|
||||
#undef MAKE_STRUCT_CASE
|
||||
default: return "system";
|
||||
// The following lists include every non-String instance type.
|
||||
// This includes a few types that already have non-"system" names assigned
|
||||
// by AddEntry, but this is a convenient way to avoid manual upkeep here.
|
||||
TORQUE_INSTANCE_CHECKERS_SINGLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
|
||||
TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
|
||||
TORQUE_INSTANCE_CHECKERS_SINGLE_ONLY_DECLARED(MAKE_TORQUE_CASE)
|
||||
TORQUE_INSTANCE_CHECKERS_MULTIPLE_ONLY_DECLARED(MAKE_TORQUE_CASE)
|
||||
#undef MAKE_TORQUE_CASE
|
||||
|
||||
// Strings were already handled by AddEntry.
|
||||
#define MAKE_STRING_CASE(instance_type, size, name, Name) \
|
||||
case instance_type: \
|
||||
UNREACHABLE();
|
||||
STRING_TYPE_LIST(MAKE_STRING_CASE)
|
||||
#undef MAKE_STRING_CASE
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,6 +297,9 @@ std::unique_ptr<InstanceTypeTree> AssignInstanceTypes() {
|
||||
// - only_declared_single_instance_types: This list is pairs of class name and
|
||||
// instance type, for classes which have a single corresponding instance type
|
||||
// and do not have layout definitions in Torque.
|
||||
// - only_declared_multiple_instance_types: This list is pairs of class name and
|
||||
// instance type, for classes which have subclasses but also have a single
|
||||
// corresponding instance type, and do not have layout definitions in Torque.
|
||||
// - fully_defined_range_instance_types: This list is triples of class name,
|
||||
// first instance type, and last instance type, for classes which have defined
|
||||
// layouts and multiple corresponding instance types.
|
||||
@ -309,6 +312,7 @@ void PrintInstanceTypes(InstanceTypeTree* root, std::ostream& definitions,
|
||||
std::ostream& fully_defined_single_instance_types,
|
||||
std::ostream& fully_defined_multiple_instance_types,
|
||||
std::ostream& only_declared_single_instance_types,
|
||||
std::ostream& only_declared_multiple_instance_types,
|
||||
std::ostream& fully_defined_range_instance_types,
|
||||
std::ostream& only_declared_range_instance_types,
|
||||
const std::string& indent) {
|
||||
@ -325,21 +329,23 @@ void PrintInstanceTypes(InstanceTypeTree* root, std::ostream& definitions,
|
||||
definitions << inner_indent << "V(" << type_name << ", " << root->value
|
||||
<< ") \\\n";
|
||||
values << " V(" << type_name << ") \\\n";
|
||||
if (root->num_values == 1) {
|
||||
std::ostream& single_instance_types =
|
||||
root->type->HasUndefinedLayout()
|
||||
? only_declared_single_instance_types
|
||||
: fully_defined_single_instance_types;
|
||||
single_instance_types << " V(" << root->type->name() << ", " << type_name
|
||||
<< ") \\\n";
|
||||
}
|
||||
std::ostream& type_checker_list =
|
||||
root->type->HasUndefinedLayout()
|
||||
? (root->num_values == 1 ? only_declared_single_instance_types
|
||||
: only_declared_multiple_instance_types)
|
||||
: (root->num_values == 1 ? fully_defined_single_instance_types
|
||||
: fully_defined_multiple_instance_types);
|
||||
type_checker_list << " V(" << root->type->name() << ", " << type_name
|
||||
<< ") \\\n";
|
||||
}
|
||||
for (auto& child : root->children) {
|
||||
PrintInstanceTypes(
|
||||
child.get(), definitions, values, fully_defined_single_instance_types,
|
||||
fully_defined_multiple_instance_types,
|
||||
only_declared_single_instance_types, fully_defined_range_instance_types,
|
||||
only_declared_range_instance_types, inner_indent);
|
||||
PrintInstanceTypes(child.get(), definitions, values,
|
||||
fully_defined_single_instance_types,
|
||||
fully_defined_multiple_instance_types,
|
||||
only_declared_single_instance_types,
|
||||
only_declared_multiple_instance_types,
|
||||
fully_defined_range_instance_types,
|
||||
only_declared_range_instance_types, inner_indent);
|
||||
}
|
||||
if (root->num_values > 1) {
|
||||
// We can't emit LAST_STRING_TYPE because it's not a valid flags
|
||||
@ -358,11 +364,6 @@ void PrintInstanceTypes(InstanceTypeTree* root, std::ostream& definitions,
|
||||
: fully_defined_range_instance_types;
|
||||
range_instance_types << " V(" << root->type->name() << ", FIRST_"
|
||||
<< type_name << ", LAST_" << type_name << ") \\\n";
|
||||
if (!root->type->IsExtern() && !root->type->IsAbstract() &&
|
||||
!root->type->HasUndefinedLayout()) {
|
||||
fully_defined_multiple_instance_types << " V(" << root->type->name()
|
||||
<< ", " << type_name << ") \\\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -384,6 +385,7 @@ void ImplementationVisitor::GenerateInstanceTypes(
|
||||
std::stringstream fully_defined_single_instance_types;
|
||||
std::stringstream fully_defined_multiple_instance_types;
|
||||
std::stringstream only_declared_single_instance_types;
|
||||
std::stringstream only_declared_multiple_instance_types;
|
||||
std::stringstream fully_defined_range_instance_types;
|
||||
std::stringstream only_declared_range_instance_types;
|
||||
if (instance_types != nullptr) {
|
||||
@ -391,6 +393,7 @@ void ImplementationVisitor::GenerateInstanceTypes(
|
||||
fully_defined_single_instance_types,
|
||||
fully_defined_multiple_instance_types,
|
||||
only_declared_single_instance_types,
|
||||
only_declared_multiple_instance_types,
|
||||
fully_defined_range_instance_types,
|
||||
only_declared_range_instance_types, " ");
|
||||
}
|
||||
@ -422,6 +425,14 @@ void ImplementationVisitor::GenerateInstanceTypes(
|
||||
header << only_declared_single_instance_types.str();
|
||||
header << "\n";
|
||||
|
||||
header << "// Pairs of (ClassName, INSTANCE_TYPE) for classes that are\n";
|
||||
header << "// declared but not defined in Torque, and have subclasses.\n";
|
||||
header << "// These classes may correspond with actual C++ classes, but\n";
|
||||
header << "// they are not guaranteed to.\n";
|
||||
header << "#define TORQUE_INSTANCE_CHECKERS_MULTIPLE_ONLY_DECLARED(V) \\\n";
|
||||
header << only_declared_multiple_instance_types.str();
|
||||
header << "\n";
|
||||
|
||||
header << "// Triples of (ClassName, FIRST_TYPE, LAST_TYPE) for classes\n";
|
||||
header << "// that have full Torque definitions.\n";
|
||||
header << "#define TORQUE_INSTANCE_CHECKERS_RANGE_FULLY_DEFINED(V) \\\n";
|
||||
|
Loading…
Reference in New Issue
Block a user