[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:
Seth Brenith 2021-01-04 11:34:37 -08:00 committed by Commit Bot
parent 4d5b878b61
commit e3f8b5dba5
5 changed files with 58 additions and 57 deletions

View File

@ -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;

View File

@ -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:

View File

@ -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,

View File

@ -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,8 +669,7 @@ HeapEntry* V8HeapExplorer::AddEntry(Address address,
}
const char* V8HeapExplorer::GetSystemEntryName(HeapObject object) {
switch (object.map().instance_type()) {
case MAP_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 ")";
@ -674,18 +677,27 @@ const char* V8HeapExplorer::GetSystemEntryName(HeapObject object) {
#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) \
}
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
}
}

View File

@ -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,20 +329,22 @@ 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 =
std::ostream& type_checker_list =
root->type->HasUndefinedLayout()
? only_declared_single_instance_types
: fully_defined_single_instance_types;
single_instance_types << " V(" << root->type->name() << ", " << type_name
? (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,
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_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) {
@ -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";