12#if defined(DART_PRECOMPILER)
17 "Output machine readable precompilation trace into the given file");
19PrecompilerTracer* PrecompilerTracer::StartTracingIfRequested(
20 Precompiler* precompiler) {
21 const char* filename = FLAG_trace_precompiler_to;
22 if (filename ==
nullptr) {
28 OS::PrintErr(
"warning: Could not access file callbacks.");
32 if (file ==
nullptr) {
33 OS::PrintErr(
"warning: Failed to write precompiler trace: %s\n", filename);
36 return new PrecompilerTracer(precompiler, file);
39PrecompilerTracer::PrecompilerTracer(Precompiler* precompiler,
void* stream)
40 : zone_(Thread::Current()->zone()),
41 precompiler_(precompiler),
44 strings_(HashTables::New<StringTable>(1024)),
45 entities_(HashTables::New<EntityTable>(1024)),
46 object_(Object::Handle()),
47 cls_(Class::Handle()) {
48 Write(
"{\"trace\":[\"R\",");
51void PrecompilerTracer::Finalize() {
58 const intptr_t output_length = buffer_.length();
59 char*
output = buffer_.Steal();
60 Dart::file_write_callback()(
output, output_length, stream_);
62 Dart::file_close_callback()(stream_);
68void PrecompilerTracer::WriteEntityTable() {
69 Write(
"\"entities\":[");
70 const auto& entities_by_id =
71 Array::Handle(zone_, Array::New(entities_.NumOccupied()));
73 EntityTable::Iterator it(&entities_);
74 while (it.MoveNext()) {
75 object_ = entities_.GetPayload(it.Current(), 0);
76 const intptr_t index = Smi::Cast(object_).Value();
77 object_ = entities_.GetKey(it.Current());
78 entities_by_id.SetAt(index, object_);
81 auto& obj = Object::Handle(zone_);
82 auto& lib = Library::Handle(zone_);
83 auto& str = String::Handle(zone_);
84 for (intptr_t i = 0; i < entities_by_id.Length(); i++) {
88 obj = entities_by_id.At(i);
89 if (obj.IsFunction()) {
90 const auto& fun = Function::Cast(obj);
92 const intptr_t selector_id =
93 precompiler_->selector_map()->SelectorId(fun);
94 Write(
"\"%c\",%" Pd ",%" Pd ",%" Pd "",
95 fun.IsDynamicFunction() ?
'F' :
'S', InternEntity(cls_),
96 InternString(NameForTrace(fun)), selector_id);
97 }
else if (obj.IsField()) {
98 const auto& field = Field::Cast(obj);
101 Write(
"\"V\",%" Pd ",%" Pd ",0", InternEntity(cls_), InternString(str));
102 }
else if (obj.IsClass()) {
103 const auto& cls = Class::Cast(obj);
106 const auto url_id = InternString(str);
107 str = cls.ScrubbedName();
108 const auto name_id = InternString(str);
109 Write(
"\"C\",%" Pd ",%" Pd ",0", url_id, name_id);
117void PrecompilerTracer::WriteStringTable() {
118 Write(
"\"strings\":[");
119 GrowableArray<const char*> strings_by_id(strings_.NumOccupied());
120 strings_by_id.EnsureLength(strings_.NumOccupied(),
nullptr);
121 StringTable::Iterator it(&strings_);
122 while (it.MoveNext()) {
123 object_ = strings_.GetPayload(it.Current(), 0);
124 const auto index = Smi::Cast(object_).Value();
125 object_ = strings_.GetKey(it.Current());
126 strings_by_id[index] = String::Cast(object_).ToCString();
129 for (
auto str : strings_by_id) {
130 Write(
"%s\"%s\"", comma ?
"," :
"", str);
136intptr_t PrecompilerTracer::InternString(
const CString& cstr) {
137 object_ = Smi::New(strings_.NumOccupied());
138 object_ = strings_.InsertNewOrGetValue(cstr, object_);
139 return Smi::Cast(object_).Value();
142intptr_t PrecompilerTracer::InternString(
const String& str) {
143 object_ = Smi::New(strings_.NumOccupied());
144 object_ = strings_.InsertOrGetValue(str, object_);
145 return Smi::Cast(object_).Value();
148intptr_t PrecompilerTracer::InternEntity(
const Object& obj) {
149 ASSERT(obj.IsFunction() || obj.IsClass() || obj.IsField());
150 const auto num_occupied = entities_.NumOccupied();
151 object_ = Smi::New(num_occupied);
152 object_ = entities_.InsertOrGetValue(obj, object_);
153 const auto id = Smi::Cast(object_).Value();
154 if (
id == num_occupied) {
155 cls_ = Class::null();
156 if (obj.IsFunction()) {
157 cls_ = Function::Cast(obj).Owner();
158 }
else if (obj.IsField()) {
159 cls_ = Field::Cast(obj).Owner();
161 if (cls_.ptr() != Class::null()) {
168PrecompilerTracer::CString PrecompilerTracer::NameForTrace(
const Function& f) {
169 ZoneTextBuffer
buffer(zone_);
170 f.PrintName(NameFormattingParams::DisambiguatedWithoutClassName(
171 Object::NameVisibility::kInternalName),
static Dart_FileWriteCallback file_write_callback()
static Dart_FileOpenCallback file_open_callback()
static Dart_FileCloseCallback file_close_callback()
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static const uint8_t buffer[]
#define DEFINE_FLAG(type, name, default_value, comment)