Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
precompiler_tracer.cc
Go to the documentation of this file.
1// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
6
9
10namespace dart {
11
12#if defined(DART_PRECOMPILER)
13
15 trace_precompiler_to,
16 nullptr,
17 "Output machine readable precompilation trace into the given file");
18
19PrecompilerTracer* PrecompilerTracer::StartTracingIfRequested(
20 Precompiler* precompiler) {
21 const char* filename = FLAG_trace_precompiler_to;
22 if (filename == nullptr) {
23 return nullptr;
24 }
25 if ((Dart::file_write_callback() == nullptr) ||
26 (Dart::file_open_callback() == nullptr) ||
27 (Dart::file_close_callback() == nullptr)) {
28 OS::PrintErr("warning: Could not access file callbacks.");
29 return nullptr;
30 }
31 void* file = Dart::file_open_callback()(filename, /*write=*/true);
32 if (file == nullptr) {
33 OS::PrintErr("warning: Failed to write precompiler trace: %s\n", filename);
34 return nullptr;
35 }
36 return new PrecompilerTracer(precompiler, file);
37}
38
39PrecompilerTracer::PrecompilerTracer(Precompiler* precompiler, void* stream)
40 : zone_(Thread::Current()->zone()),
41 precompiler_(precompiler),
42 buffer_(1024),
43 stream_(stream),
44 strings_(HashTables::New<StringTable>(1024)),
45 entities_(HashTables::New<EntityTable>(1024)),
46 object_(Object::Handle()),
47 cls_(Class::Handle()) {
48 Write("{\"trace\":[\"R\",");
49}
50
51void PrecompilerTracer::Finalize() {
52 Write("\"E\"],");
53 WriteEntityTable();
54 Write(",");
55 WriteStringTable();
56 Write("}\n");
57
58 const intptr_t output_length = buffer_.length();
59 char* output = buffer_.Steal();
60 Dart::file_write_callback()(output, output_length, stream_);
61 free(output);
62 Dart::file_close_callback()(stream_);
63
64 strings_.Release();
65 entities_.Release();
66}
67
68void PrecompilerTracer::WriteEntityTable() {
69 Write("\"entities\":[");
70 const auto& entities_by_id =
71 Array::Handle(zone_, Array::New(entities_.NumOccupied()));
72
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_);
79 }
80
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++) {
85 if (i > 0) {
86 Write(",");
87 }
88 obj = entities_by_id.At(i);
89 if (obj.IsFunction()) {
90 const auto& fun = Function::Cast(obj);
91 cls_ = fun.Owner();
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);
99 cls_ = field.Owner();
100 str = field.name();
101 Write("\"V\",%" Pd ",%" Pd ",0", InternEntity(cls_), InternString(str));
102 } else if (obj.IsClass()) {
103 const auto& cls = Class::Cast(obj);
104 lib = cls.library();
105 str = lib.url();
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);
110 } else {
111 UNREACHABLE();
112 }
113 }
114 Write("]");
115}
116
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();
127 }
128 auto comma = false;
129 for (auto str : strings_by_id) {
130 Write("%s\"%s\"", comma ? "," : "", str);
131 comma = true;
132 }
133 Write("]");
134}
135
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();
140}
141
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();
146}
147
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();
160 }
161 if (cls_.ptr() != Class::null()) {
162 InternEntity(cls_);
163 }
164 }
165 return id;
166}
167
168PrecompilerTracer::CString PrecompilerTracer::NameForTrace(const Function& f) {
169 ZoneTextBuffer buffer(zone_);
170 f.PrintName(NameFormattingParams::DisambiguatedWithoutClassName(
171 Object::NameVisibility::kInternalName),
172 &buffer);
173 return {buffer.buffer(), buffer.length(),
174 String::Hash(buffer.buffer(), buffer.length())};
175}
176
177#endif // defined(DART_PRECOMPILER)
178
179} // namespace dart
#define UNREACHABLE()
Definition assert.h:248
static Dart_FileWriteCallback file_write_callback()
Definition dart.h:125
static Dart_FileOpenCallback file_open_callback()
Definition dart.h:119
static Dart_FileCloseCallback file_close_callback()
Definition dart.h:128
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
#define ASSERT(E)
static const uint8_t buffer[]
const char * charp
Definition flags.h:12
#define DEFINE_FLAG(type, name, default_value, comment)
Definition flags.h:16
#define Pd
Definition globals.h:408
const uintptr_t id