[heap-snapshot] Prepare for Code-less builtins

Drive-by fixes:
* categorize CodeDataContainer objects as kCode,
* when external code space is enabled report CodeDataContainers as
  (%s builtin handle),
* replace a sequence of obj.IsXXX() with a respective sequence of
  InstanceTypeChecker::IsXXX().

Bug: v8:11880
Change-Id: Ib50b168eb28af5f8388be7f9b9f4feba2ee784af
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3780534
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81898}
This commit is contained in:
ishell@chromium.org 2022-07-21 18:56:42 +02:00 committed by V8 LUCI CQ
parent c1d5c1c5aa
commit b71b8887e2
2 changed files with 72 additions and 35 deletions

View File

@ -801,59 +801,73 @@ void V8HeapExplorer::ExtractLocationForJSFunction(HeapEntry* entry,
}
HeapEntry* V8HeapExplorer::AddEntry(HeapObject object) {
if (object.IsJSFunction()) {
JSFunction func = JSFunction::cast(object);
SharedFunctionInfo shared = func.shared();
const char* name = names_->GetName(shared.Name());
return AddEntry(object, HeapEntry::kClosure, name);
} else if (object.IsJSBoundFunction()) {
return AddEntry(object, HeapEntry::kClosure, "native_bind");
} else if (object.IsJSRegExp()) {
JSRegExp re = JSRegExp::cast(object);
return AddEntry(object, HeapEntry::kRegExp, names_->GetName(re.source()));
} else if (object.IsJSObject()) {
PtrComprCageBase cage_base(isolate());
InstanceType instance_type = object.map(cage_base).instance_type();
if (InstanceTypeChecker::IsJSObject(instance_type)) {
if (InstanceTypeChecker::IsJSFunction(instance_type)) {
JSFunction func = JSFunction::cast(object);
SharedFunctionInfo shared = func.shared();
const char* name = names_->GetName(shared.Name());
return AddEntry(object, HeapEntry::kClosure, name);
} else if (InstanceTypeChecker::IsJSBoundFunction(instance_type)) {
return AddEntry(object, HeapEntry::kClosure, "native_bind");
}
if (InstanceTypeChecker::IsJSRegExp(instance_type)) {
JSRegExp re = JSRegExp::cast(object);
return AddEntry(object, HeapEntry::kRegExp, names_->GetName(re.source()));
}
// TODO(v8:12674) Fix and run full gcmole.
DisableGCMole no_gcmole;
const char* name = names_->GetName(
GetConstructorName(heap_->isolate(), JSObject::cast(object)));
if (object.IsJSGlobalObject()) {
if (InstanceTypeChecker::IsJSGlobalObject(instance_type)) {
auto it = global_object_tag_map_.find(JSGlobalObject::cast(object));
if (it != global_object_tag_map_.end()) {
name = names_->GetFormatted("%s / %s", name, it->second);
}
}
return AddEntry(object, HeapEntry::kObject, name);
} else if (object.IsString()) {
} else if (InstanceTypeChecker::IsString(instance_type)) {
String string = String::cast(object);
if (string.IsConsString()) {
if (string.IsConsString(cage_base)) {
return AddEntry(object, HeapEntry::kConsString, "(concatenated string)");
} else if (string.IsSlicedString()) {
} else if (string.IsSlicedString(cage_base)) {
return AddEntry(object, HeapEntry::kSlicedString, "(sliced string)");
} else {
return AddEntry(object, HeapEntry::kString,
names_->GetName(String::cast(object)));
}
} else if (object.IsSymbol()) {
} else if (InstanceTypeChecker::IsSymbol(instance_type)) {
if (Symbol::cast(object).is_private())
return AddEntry(object, HeapEntry::kHidden, "private symbol");
else
return AddEntry(object, HeapEntry::kSymbol, "symbol");
} else if (object.IsBigInt()) {
} else if (InstanceTypeChecker::IsBigInt(instance_type)) {
return AddEntry(object, HeapEntry::kBigInt, "bigint");
} else if (object.IsCode()) {
} else if (InstanceTypeChecker::IsCode(instance_type) ||
InstanceTypeChecker::IsCodeDataContainer(instance_type)) {
return AddEntry(object, HeapEntry::kCode, "");
} else if (object.IsSharedFunctionInfo()) {
} else if (InstanceTypeChecker::IsSharedFunctionInfo(instance_type)) {
String name = SharedFunctionInfo::cast(object).Name();
return AddEntry(object, HeapEntry::kCode, names_->GetName(name));
} else if (object.IsScript()) {
} else if (InstanceTypeChecker::IsScript(instance_type)) {
Object name = Script::cast(object).name();
return AddEntry(object, HeapEntry::kCode,
name.IsString() ? names_->GetName(String::cast(name)) : "");
} else if (object.IsNativeContext()) {
} else if (InstanceTypeChecker::IsNativeContext(instance_type)) {
return AddEntry(object, HeapEntry::kHidden, "system / NativeContext");
} else if (object.IsContext()) {
} else if (InstanceTypeChecker::IsContext(instance_type)) {
return AddEntry(object, HeapEntry::kObject, "system / Context");
} else if (object.IsHeapNumber()) {
} else if (InstanceTypeChecker::IsHeapNumber(instance_type)) {
return AddEntry(object, HeapEntry::kHeapNumber, "heap number");
}
return AddEntry(object, GetSystemEntryType(object),
@ -1439,13 +1453,18 @@ void V8HeapExplorer::ExtractMapReferences(HeapEntry* entry, Map map) {
void V8HeapExplorer::ExtractSharedFunctionInfoReferences(
HeapEntry* entry, SharedFunctionInfo shared) {
std::unique_ptr<char[]> name = shared.DebugNameCStr();
CodeT code = shared.GetCode();
// Don't try to get the Code object from Code-less embedded builtin.
HeapObject maybe_code_obj =
V8_REMOVE_BUILTINS_CODE_OBJECTS && code.is_off_heap_trampoline()
? HeapObject::cast(code)
: FromCodeT(code);
if (name[0] != '\0') {
TagObject(FromCodeT(shared.GetCode()),
TagObject(maybe_code_obj,
names_->GetFormatted("(code for %s)", name.get()));
} else {
TagObject(FromCodeT(shared.GetCode()),
names_->GetFormatted("(%s code)",
CodeKindToString(shared.GetCode().kind())));
TagObject(maybe_code_obj,
names_->GetFormatted("(%s code)", CodeKindToString(code.kind())));
}
Object name_or_scope_info = shared.name_or_scope_info(kAcquireLoad);
@ -1511,7 +1530,12 @@ void V8HeapExplorer::ExtractWeakCellReferences(HeapEntry* entry,
}
void V8HeapExplorer::TagBuiltinCodeObject(CodeT code, const char* name) {
TagObject(FromCodeT(code), names_->GetFormatted("(%s builtin)", name));
if (V8_EXTERNAL_CODE_SPACE_BOOL) {
TagObject(code, names_->GetFormatted("(%s builtin handle)", name));
}
if (!V8_REMOVE_BUILTINS_CODE_OBJECTS || !code.is_off_heap_trampoline()) {
TagObject(FromCodeT(code), names_->GetFormatted("(%s builtin)", name));
}
}
void V8HeapExplorer::ExtractCodeReferences(HeapEntry* entry, Code code) {

View File

@ -2772,25 +2772,38 @@ TEST(CheckCodeNames) {
CHECK(ValidateSnapshot(snapshot));
const char* builtin_path1[] = {
"::(GC roots)", "::(Builtins)",
"::(GC roots)",
"::(Builtins)",
#ifdef V8_EXTERNAL_CODE_SPACE
"KeyedLoadIC_PolymorphicName::system / CodeDataContainer",
"::(KeyedLoadIC_PolymorphicName builtin handle)",
#endif
"::(KeyedLoadIC_PolymorphicName builtin)"};
#if !V8_REMOVE_BUILTINS_CODE_OBJECTS
"::(KeyedLoadIC_PolymorphicName builtin)"
#endif
};
const v8::HeapGraphNode* node = GetNodeByPath(
env->GetIsolate(), snapshot, builtin_path1, arraysize(builtin_path1));
CHECK(node);
const char* builtin_path2[] = {"::(GC roots)", "::(Builtins)",
const char* builtin_path2[] = {
"::(GC roots)",
"::(Builtins)",
#ifdef V8_EXTERNAL_CODE_SPACE
"CompileLazy::system / CodeDataContainer",
"::(CompileLazy builtin handle)",
#endif
"::(CompileLazy builtin)"};
#if !V8_REMOVE_BUILTINS_CODE_OBJECTS
"::(CompileLazy builtin)"
#endif
};
node = GetNodeByPath(env->GetIsolate(), snapshot, builtin_path2,
arraysize(builtin_path2));
CHECK(node);
v8::String::Utf8Value node_name(env->GetIsolate(), node->GetName());
CHECK_EQ(0, strcmp("(CompileLazy builtin)", *node_name));
if (V8_REMOVE_BUILTINS_CODE_OBJECTS) {
CHECK_EQ(0, strcmp("(CompileLazy builtin handle)", *node_name));
} else {
CHECK_EQ(0, strcmp("(CompileLazy builtin)", *node_name));
}
}