mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:19:47 +00:00
[vm/snapshot] Name Code and Function objects in V8 snapshot profiles
Issue https://github.com/dart-lang/sdk/issues/41249 Cq-Include-Trybots: luci.dart.try:pkg-linux-debug-try,pkg-linux-release-try,pkg-win-release-try,pkg-mac-release-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-x64-try Change-Id: Idd7644714884e4ea1461718285c1b01f12d811e7 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151225 Commit-Queue: Vyacheslav Egorov <vegorov@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
parent
5944ff823f
commit
572aa45c21
|
@ -27,6 +27,7 @@
|
|||
#include "vm/symbols.h"
|
||||
#include "vm/timeline.h"
|
||||
#include "vm/version.h"
|
||||
#include "vm/zone_text_buffer.h"
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
#include "vm/compiler/backend/code_statistics.h"
|
||||
|
@ -602,7 +603,7 @@ class FunctionSerializationCluster : public SerializationCluster {
|
|||
const intptr_t count = objects_.length();
|
||||
for (intptr_t i = 0; i < count; i++) {
|
||||
FunctionPtr func = objects_[i];
|
||||
AutoTraceObjectName(func, func->ptr()->name_);
|
||||
AutoTraceObjectName(func, MakeDisambiguatedFunctionName(s, func));
|
||||
WriteFromTo(func);
|
||||
if (kind == Snapshot::kFull) {
|
||||
NOT_IN_PRECOMPILED(WriteField(func, bytecode_));
|
||||
|
@ -626,6 +627,22 @@ class FunctionSerializationCluster : public SerializationCluster {
|
|||
}
|
||||
}
|
||||
|
||||
static const char* MakeDisambiguatedFunctionName(Serializer* s,
|
||||
FunctionPtr f) {
|
||||
if (s->profile_writer() == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
REUSABLE_FUNCTION_HANDLESCOPE(s->thread());
|
||||
Function& fun = reused_function_handle.Handle();
|
||||
fun = f;
|
||||
ZoneTextBuffer printer(s->thread()->zone());
|
||||
fun.PrintName(NameFormattingParams::DisambiguatedUnqualified(
|
||||
Object::NameVisibility::kInternalName),
|
||||
&printer);
|
||||
return printer.buffer();
|
||||
}
|
||||
|
||||
private:
|
||||
GrowableArray<FunctionPtr> objects_;
|
||||
};
|
||||
|
@ -1561,7 +1578,7 @@ class CodeSerializationCluster : public SerializationCluster {
|
|||
const intptr_t count = objects_.length();
|
||||
for (intptr_t i = 0; i < count; i++) {
|
||||
CodePtr code = objects_[i];
|
||||
AutoTraceObject(code);
|
||||
AutoTraceObjectName(code, MakeDisambiguatedCodeName(s, code));
|
||||
|
||||
intptr_t pointer_offsets_length =
|
||||
Code::PtrOffBits::decode(code->ptr()->state_bits_);
|
||||
|
@ -1652,6 +1669,19 @@ class CodeSerializationCluster : public SerializationCluster {
|
|||
}
|
||||
|
||||
private:
|
||||
static const char* MakeDisambiguatedCodeName(Serializer* s, CodePtr c) {
|
||||
if (s->profile_writer() == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
REUSABLE_CODE_HANDLESCOPE(s->thread());
|
||||
Code& code = reused_code_handle.Handle();
|
||||
code = c;
|
||||
return code.QualifiedName(
|
||||
NameFormattingParams::DisambiguatedWithoutClassName(
|
||||
Object::NameVisibility::kInternalName));
|
||||
}
|
||||
|
||||
GrowableArray<CodePtr> objects_;
|
||||
};
|
||||
#endif // !DART_PRECOMPILED_RUNTIME
|
||||
|
@ -4812,6 +4842,22 @@ void Serializer::TraceStartWritingObject(const char* type,
|
|||
StringPtr name) {
|
||||
if (profile_writer_ == nullptr) return;
|
||||
|
||||
const char* name_str = nullptr;
|
||||
if (name != nullptr) {
|
||||
REUSABLE_STRING_HANDLESCOPE(thread());
|
||||
String& str = reused_string_handle.Handle();
|
||||
str = name;
|
||||
name_str = str.ToCString();
|
||||
}
|
||||
|
||||
TraceStartWritingObject(type, obj, name_str);
|
||||
}
|
||||
|
||||
void Serializer::TraceStartWritingObject(const char* type,
|
||||
ObjectPtr obj,
|
||||
const char* name) {
|
||||
if (profile_writer_ == nullptr) return;
|
||||
|
||||
intptr_t cid = -1;
|
||||
intptr_t id = 0;
|
||||
if (obj->IsHeapObject()) {
|
||||
|
@ -4826,20 +4872,13 @@ void Serializer::TraceStartWritingObject(const char* type,
|
|||
}
|
||||
ASSERT(IsAllocatedReference(id));
|
||||
|
||||
const char* name_str = nullptr;
|
||||
if (name != nullptr) {
|
||||
String& str = thread()->StringHandle();
|
||||
str = name;
|
||||
name_str = str.ToCString();
|
||||
}
|
||||
|
||||
FlushBytesWrittenToRoot();
|
||||
object_currently_writing_.object_ = obj;
|
||||
object_currently_writing_.id_ = id;
|
||||
object_currently_writing_.stream_start_ = stream_.Position();
|
||||
object_currently_writing_.cid_ = cid;
|
||||
profile_writer_->SetObjectTypeAndName(
|
||||
{V8SnapshotProfileWriter::kSnapshot, id}, type, name_str);
|
||||
{V8SnapshotProfileWriter::kSnapshot, id}, type, name);
|
||||
}
|
||||
|
||||
void Serializer::TraceEndWritingObject() {
|
||||
|
@ -4853,6 +4892,7 @@ void Serializer::TraceEndWritingObject() {
|
|||
}
|
||||
}
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
bool Serializer::CreateArtificalNodeIfNeeded(ObjectPtr obj) {
|
||||
ASSERT(profile_writer() != nullptr);
|
||||
|
||||
|
@ -4867,14 +4907,16 @@ bool Serializer::CreateArtificalNodeIfNeeded(ObjectPtr obj) {
|
|||
id = AssignArtificialRef(obj);
|
||||
|
||||
const char* type = nullptr;
|
||||
StringPtr name = nullptr;
|
||||
StringPtr name_string = nullptr;
|
||||
const char* name = nullptr;
|
||||
ObjectPtr owner = nullptr;
|
||||
const char* owner_ref_name = nullptr;
|
||||
switch (obj->GetClassId()) {
|
||||
case kFunctionCid: {
|
||||
FunctionPtr func = static_cast<FunctionPtr>(obj);
|
||||
type = "Function";
|
||||
name = func->ptr()->name_;
|
||||
name = FunctionSerializationCluster::MakeDisambiguatedFunctionName(this,
|
||||
func);
|
||||
owner_ref_name = "owner_";
|
||||
owner = func->ptr()->owner_;
|
||||
break;
|
||||
|
@ -4882,7 +4924,7 @@ bool Serializer::CreateArtificalNodeIfNeeded(ObjectPtr obj) {
|
|||
case kClassCid: {
|
||||
ClassPtr cls = static_cast<ClassPtr>(obj);
|
||||
type = "Class";
|
||||
name = cls->ptr()->name_;
|
||||
name_string = cls->ptr()->name_;
|
||||
owner_ref_name = "library_";
|
||||
owner = cls->ptr()->library_;
|
||||
break;
|
||||
|
@ -4897,13 +4939,20 @@ bool Serializer::CreateArtificalNodeIfNeeded(ObjectPtr obj) {
|
|||
case kLibraryCid: {
|
||||
LibraryPtr lib = static_cast<LibraryPtr>(obj);
|
||||
type = "Library";
|
||||
name = lib->ptr()->url_;
|
||||
name_string = lib->ptr()->url_;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
if (name_string != nullptr) {
|
||||
REUSABLE_STRING_HANDLESCOPE(thread());
|
||||
String& str = reused_string_handle.Handle();
|
||||
str = name_string;
|
||||
name = str.ToCString();
|
||||
}
|
||||
|
||||
TraceStartWritingObject(type, obj, name);
|
||||
if (owner != nullptr) {
|
||||
CreateArtificalNodeIfNeeded(owner);
|
||||
|
@ -4913,6 +4962,7 @@ bool Serializer::CreateArtificalNodeIfNeeded(ObjectPtr obj) {
|
|||
TraceEndWritingObject();
|
||||
return true;
|
||||
}
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
const char* Serializer::ReadOnlyObjectType(intptr_t cid) {
|
||||
switch (cid) {
|
||||
|
|
|
@ -255,6 +255,9 @@ class Serializer : public ThreadStackResource {
|
|||
|
||||
void FlushBytesWrittenToRoot();
|
||||
void TraceStartWritingObject(const char* type, ObjectPtr obj, StringPtr name);
|
||||
void TraceStartWritingObject(const char* type,
|
||||
ObjectPtr obj,
|
||||
const char* name);
|
||||
void TraceEndWritingObject();
|
||||
|
||||
// Writes raw data to the stream (basic type).
|
||||
|
@ -494,7 +497,8 @@ class Serializer : public ThreadStackResource {
|
|||
|
||||
#define WriteField(obj, field) s->WritePropertyRef(obj->ptr()->field, #field)
|
||||
|
||||
struct SerializerWritingObjectScope {
|
||||
class SerializerWritingObjectScope {
|
||||
public:
|
||||
SerializerWritingObjectScope(Serializer* serializer,
|
||||
const char* type,
|
||||
ObjectPtr object,
|
||||
|
@ -503,6 +507,14 @@ struct SerializerWritingObjectScope {
|
|||
serializer_->TraceStartWritingObject(type, object, name);
|
||||
}
|
||||
|
||||
SerializerWritingObjectScope(Serializer* serializer,
|
||||
const char* type,
|
||||
ObjectPtr object,
|
||||
const char* name)
|
||||
: serializer_(serializer) {
|
||||
serializer_->TraceStartWritingObject(type, object, name);
|
||||
}
|
||||
|
||||
~SerializerWritingObjectScope() { serializer_->TraceEndWritingObject(); }
|
||||
|
||||
private:
|
||||
|
|
|
@ -8853,19 +8853,19 @@ StringPtr Function::UserVisibleName() const {
|
|||
StringPtr Function::QualifiedScrubbedName() const {
|
||||
Thread* thread = Thread::Current();
|
||||
ZoneTextBuffer printer(thread->zone());
|
||||
PrintQualifiedName(NameFormattingParams(kScrubbedName), &printer);
|
||||
PrintName(NameFormattingParams(kScrubbedName), &printer);
|
||||
return Symbols::New(thread, printer.buffer());
|
||||
}
|
||||
|
||||
StringPtr Function::QualifiedUserVisibleName() const {
|
||||
Thread* thread = Thread::Current();
|
||||
ZoneTextBuffer printer(thread->zone());
|
||||
PrintQualifiedName(NameFormattingParams(kUserVisibleName), &printer);
|
||||
PrintName(NameFormattingParams(kUserVisibleName), &printer);
|
||||
return Symbols::New(thread, printer.buffer());
|
||||
}
|
||||
|
||||
void Function::PrintQualifiedName(const NameFormattingParams& params,
|
||||
ZoneTextBuffer* printer) const {
|
||||
void Function::PrintName(const NameFormattingParams& params,
|
||||
ZoneTextBuffer* printer) const {
|
||||
// If |this| is the generated asynchronous body closure, use the
|
||||
// name of the parent function.
|
||||
Function& fun = Function::Handle(raw());
|
||||
|
@ -8902,9 +8902,11 @@ void Function::PrintQualifiedName(const NameFormattingParams& params,
|
|||
// the parent.
|
||||
parent = parent.parent_function();
|
||||
}
|
||||
parent.PrintQualifiedName(params, printer);
|
||||
// A function's scrubbed name and its user visible name are identical.
|
||||
printer->AddString(".");
|
||||
if (params.include_parent_name) {
|
||||
parent.PrintName(params, printer);
|
||||
// A function's scrubbed name and its user visible name are identical.
|
||||
printer->AddString(".");
|
||||
}
|
||||
if (params.disambiguate_names &&
|
||||
fun.name() == Symbols::AnonymousClosure().raw()) {
|
||||
printer->Printf("<anonymous closure @%" Pd ">", fun.token_pos().Pos());
|
||||
|
@ -16240,9 +16242,8 @@ const char* Code::Name() const {
|
|||
Object::Handle(zone, WeakSerializationReference::UnwrapIfTarget(owner()));
|
||||
if (obj.IsClass()) {
|
||||
// Allocation stub.
|
||||
String& cls_name = String::Handle(zone, Class::Cast(obj).ScrubbedName());
|
||||
ASSERT(!cls_name.IsNull());
|
||||
return OS::SCreate(zone, "[Stub] Allocate %s", cls_name.ToCString());
|
||||
return OS::SCreate(zone, "[Stub] Allocate %s",
|
||||
Class::Cast(obj).ScrubbedNameCString());
|
||||
} else if (obj.IsAbstractType()) {
|
||||
// Type test stub.
|
||||
return OS::SCreate(zone, "[Stub] Type Test %s",
|
||||
|
@ -16267,7 +16268,7 @@ const char* Code::QualifiedName(const NameFormattingParams& params) const {
|
|||
if (obj.IsFunction()) {
|
||||
ZoneTextBuffer printer(zone);
|
||||
printer.AddString(is_optimized() ? "[Optimized] " : "[Unoptimized] ");
|
||||
Function::Cast(obj).PrintQualifiedName(params, &printer);
|
||||
Function::Cast(obj).PrintName(params, &printer);
|
||||
return printer.buffer();
|
||||
}
|
||||
return Name();
|
||||
|
@ -18737,7 +18738,7 @@ void AbstractType::PrintName(
|
|||
} else if (param.parameterized_function() != Function::null()) {
|
||||
const Function& func =
|
||||
Function::Handle(zone, param.parameterized_function());
|
||||
func.PrintQualifiedName(
|
||||
func.PrintName(
|
||||
NameFormattingParams(name_visibility, name_disambiguation),
|
||||
printer);
|
||||
printer->AddString("::");
|
||||
|
|
|
@ -2424,17 +2424,24 @@ enum {
|
|||
kAllFree = kMaxInt32,
|
||||
};
|
||||
|
||||
// Formatting configuration for Function::PrintQualifiedName.
|
||||
// Formatting configuration for Function::PrintName.
|
||||
struct NameFormattingParams {
|
||||
Object::NameVisibility name_visibility;
|
||||
bool disambiguate_names;
|
||||
|
||||
// By default function name includes the name of the enclosing class if any.
|
||||
// However in some context this information is redundant and class name
|
||||
// However in some contexts this information is redundant and class name
|
||||
// is already known. In this case setting |include_class_name| to false
|
||||
// allows you to exclude this information from the formatted name.
|
||||
bool include_class_name = true;
|
||||
|
||||
// By default function name includes the name of the enclosing function if
|
||||
// any. However in some contexts this information is redundant and
|
||||
// the name of the enclosing function is already known. In this case
|
||||
// setting |include_parent_name| to false allows to exclude this information
|
||||
// from the formatted name.
|
||||
bool include_parent_name = true;
|
||||
|
||||
NameFormattingParams(Object::NameVisibility visibility,
|
||||
Object::NameDisambiguation name_disambiguation =
|
||||
Object::NameDisambiguation::kNo)
|
||||
|
@ -2448,6 +2455,14 @@ struct NameFormattingParams {
|
|||
params.include_class_name = false;
|
||||
return params;
|
||||
}
|
||||
|
||||
static NameFormattingParams DisambiguatedUnqualified(
|
||||
Object::NameVisibility visibility) {
|
||||
NameFormattingParams params(visibility, Object::NameDisambiguation::kYes);
|
||||
params.include_class_name = false;
|
||||
params.include_parent_name = false;
|
||||
return params;
|
||||
}
|
||||
};
|
||||
|
||||
class Function : public Object {
|
||||
|
@ -2458,8 +2473,8 @@ class Function : public Object {
|
|||
|
||||
const char* NameCString(NameVisibility name_visibility) const;
|
||||
|
||||
void PrintQualifiedName(const NameFormattingParams& params,
|
||||
ZoneTextBuffer* printer) const;
|
||||
void PrintName(const NameFormattingParams& params,
|
||||
ZoneTextBuffer* printer) const;
|
||||
StringPtr QualifiedScrubbedName() const;
|
||||
StringPtr QualifiedUserVisibleName() const;
|
||||
|
||||
|
|
Loading…
Reference in a new issue