Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(170)

Side by Side Diff: runtime/vm/code_descriptors.cc

Issue 2670843006: Encode inlining information in CodeSourceMap and remove inlining interval arrays. (Closed)
Patch Set: . Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/code_descriptors.h" 5 #include "vm/code_descriptors.h"
6 6
7 #include "vm/log.h"
8
7 namespace dart { 9 namespace dart {
8 10
9 void DescriptorList::AddDescriptor(RawPcDescriptors::Kind kind, 11 void DescriptorList::AddDescriptor(RawPcDescriptors::Kind kind,
10 intptr_t pc_offset, 12 intptr_t pc_offset,
11 intptr_t deopt_id, 13 intptr_t deopt_id,
12 TokenPosition token_pos, 14 TokenPosition token_pos,
13 intptr_t try_index) { 15 intptr_t try_index) {
14 ASSERT((kind == RawPcDescriptors::kRuntimeCall) || 16 ASSERT((kind == RawPcDescriptors::kRuntimeCall) ||
15 (kind == RawPcDescriptors::kOther) || 17 (kind == RawPcDescriptors::kOther) ||
16 (deopt_id != Thread::kNoDeoptId)); 18 (deopt_id != Thread::kNoDeoptId));
(...skipping 17 matching lines...) Expand all
34 36
35 37
36 RawPcDescriptors* DescriptorList::FinalizePcDescriptors(uword entry_point) { 38 RawPcDescriptors* DescriptorList::FinalizePcDescriptors(uword entry_point) {
37 if (encoded_data_.length() == 0) { 39 if (encoded_data_.length() == 0) {
38 return Object::empty_descriptors().raw(); 40 return Object::empty_descriptors().raw();
39 } 41 }
40 return PcDescriptors::New(&encoded_data_); 42 return PcDescriptors::New(&encoded_data_);
41 } 43 }
42 44
43 45
44 void CodeSourceMapBuilder::AddEntry(intptr_t pc_offset,
45 TokenPosition token_pos) {
46 // Require pc offset to monotonically increase.
47 ASSERT((prev_pc_offset < pc_offset) ||
48 ((prev_pc_offset == 0) && (pc_offset == 0)));
49 CodeSourceMap::EncodeInteger(&encoded_data_, pc_offset - prev_pc_offset);
50 CodeSourceMap::EncodeInteger(&encoded_data_,
51 token_pos.value() - prev_token_pos);
52
53 prev_pc_offset = pc_offset;
54 prev_token_pos = token_pos.value();
55 }
56
57
58 RawCodeSourceMap* CodeSourceMapBuilder::Finalize() {
59 return CodeSourceMap::New(&encoded_data_);
60 }
61
62
63 void StackMapTableBuilder::AddEntry(intptr_t pc_offset, 46 void StackMapTableBuilder::AddEntry(intptr_t pc_offset,
64 BitmapBuilder* bitmap, 47 BitmapBuilder* bitmap,
65 intptr_t register_bit_count) { 48 intptr_t register_bit_count) {
66 stack_map_ = StackMap::New(pc_offset, bitmap, register_bit_count); 49 stack_map_ = StackMap::New(pc_offset, bitmap, register_bit_count);
67 list_.Add(stack_map_, Heap::kOld); 50 list_.Add(stack_map_, Heap::kOld);
68 } 51 }
69 52
70 53
71 bool StackMapTableBuilder::Verify() { 54 bool StackMapTableBuilder::Verify() {
72 intptr_t num_entries = Length(); 55 intptr_t num_entries = Length();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 const bool has_catch_all = ContainsDynamic(*list_[i].handler_types); 108 const bool has_catch_all = ContainsDynamic(*list_[i].handler_types);
126 handlers.SetHandlerInfo(i, list_[i].outer_try_index, list_[i].pc_offset, 109 handlers.SetHandlerInfo(i, list_[i].outer_try_index, list_[i].pc_offset,
127 list_[i].needs_stacktrace, has_catch_all); 110 list_[i].needs_stacktrace, has_catch_all);
128 handlers.SetHandledTypes(i, *list_[i].handler_types); 111 handlers.SetHandledTypes(i, *list_[i].handler_types);
129 } 112 }
130 } 113 }
131 return handlers.raw(); 114 return handlers.raw();
132 } 115 }
133 116
134 117
118 static uint8_t* zone_allocator(uint8_t* ptr,
119 intptr_t old_size,
120 intptr_t new_size) {
121 Zone* zone = Thread::Current()->zone();
122 return zone->Realloc<uint8_t>(ptr, old_size, new_size);
123 }
124
125
126 const TokenPosition CodeSourceMapBuilder::kInitialPosition =
127 TokenPosition::kDartCodePrologue;
128
129
130 CodeSourceMapBuilder::CodeSourceMapBuilder(
131 const GrowableArray<intptr_t>& caller_inline_id,
132 const GrowableArray<TokenPosition>& inline_id_to_token_pos,
133 const GrowableArray<const Function*>& inline_id_to_function)
134 : pc_offset_(0),
135 advance_pc_peephole_(0),
136 inline_id_stack_(),
137 token_pos_stack_(),
138 caller_inline_id_(caller_inline_id),
139 inline_id_to_token_pos_(inline_id_to_token_pos),
140 inline_id_to_function_(inline_id_to_function),
141 buffer_(NULL),
142 stream_(&buffer_, zone_allocator, 64) {
143 inline_id_stack_.Add(0);
144 token_pos_stack_.Add(TokenPosition::kDartCodePrologue);
145 }
146
147
148 void CodeSourceMapBuilder::StartInliningInterval(int32_t pc_offset,
149 intptr_t inline_id) {
150 if (inline_id_stack_.Last() == inline_id) {
151 // No change in function stack.
152 return;
153 }
154 if (inline_id == -1) {
155 // Basic blocking missing an inline_id.
156 return;
157 }
158
159 // Find a minimal set of pops and pushes to bring us to the new function
160 // stack.
161
162 // Pop to a common ancestor.
163 intptr_t common_parent = inline_id;
164 while (!IsOnStack(common_parent)) {
165 common_parent = caller_inline_id_[common_parent];
166 }
167 while (inline_id_stack_.Last() != common_parent) {
168 EmitPop();
169 inline_id_stack_.RemoveLast();
170 token_pos_stack_.RemoveLast();
171 }
172
173 // Push to the new top-of-stack function.
174 GrowableArray<intptr_t> to_push;
175 intptr_t id = inline_id;
176 while (id != common_parent) {
177 to_push.Add(id);
178 id = caller_inline_id_[id];
179 }
180 for (intptr_t i = to_push.length() - 1; i >= 0; i--) {
181 intptr_t push_id = to_push[i];
182 TokenPosition call_token;
183 if (push_id != 0) {
184 // TODO(rmacnak): Should make this array line up with the others.
185 call_token = inline_id_to_token_pos_[push_id - 1];
186 }
187
188 // Report caller as at the position of the call.
189 if (call_token != token_pos_stack_.Last()) {
190 EmitPosition(call_token);
191 token_pos_stack_[token_pos_stack_.length() - 1] = call_token;
192 }
193
194 // Push the callee.
195 EmitPush(push_id);
196 inline_id_stack_.Add(push_id);
197 token_pos_stack_.Add(TokenPosition::kDartCodePrologue);
198 }
199 }
200
201
202 void CodeSourceMapBuilder::BeginCodeSourceRange(int32_t pc_offset) {}
203
204
205 void CodeSourceMapBuilder::EndCodeSourceRange(int32_t pc_offset,
206 TokenPosition pos) {
207 if (pc_offset == pc_offset_) {
208 return; // Empty intermediate instruction.
209 }
210 if (pos != token_pos_stack_.Last()) {
211 EmitPosition(pos);
212 token_pos_stack_[token_pos_stack_.length() - 1] = pos;
213 }
214 EmitAdvancePC(pc_offset - pc_offset_);
215 pc_offset_ = pc_offset;
216 }
217
218
219 RawArray* CodeSourceMapBuilder::InliningIdToFunction() {
220 if (inline_id_to_function_.length() <= 1) {
221 // Not optimizing, or optimizing and nothing inlined.
222 return Object::empty_array().raw();
223 }
224 const Array& res =
225 Array::Handle(Array::New(inline_id_to_function_.length(), Heap::kOld));
226 for (intptr_t i = 0; i < inline_id_to_function_.length(); i++) {
227 res.SetAt(i, *inline_id_to_function_[i]);
228 }
229 return res.raw();
230 }
231
232
233 RawCodeSourceMap* CodeSourceMapBuilder::Finalize() {
234 FlushPeephole();
235 intptr_t length = stream_.bytes_written();
236 const CodeSourceMap& map = CodeSourceMap::Handle(CodeSourceMap::New(length));
237 NoSafepointScope no_safepoint;
238 memmove(map.Data(), buffer_, length);
239 return map.raw();
240 }
241
242
243 void CodeSourceMapReader::GetInlinedFunctionsAt(
244 int32_t pc_offset,
245 GrowableArray<const Function*>* function_stack,
246 GrowableArray<TokenPosition>* token_positions) {
247 function_stack->Clear();
248 token_positions->Clear();
249
250 NoSafepointScope no_safepoint;
251 ReadStream stream(map_.Data(), map_.Length());
252
253 int32_t current_pc_offset = 0;
254 function_stack->Add(&root_);
255 token_positions->Add(CodeSourceMapBuilder::kInitialPosition);
256
257 while (stream.PendingBytes() > 0) {
258 uint8_t opcode = stream.Read<uint8_t>();
259 switch (opcode) {
260 case CodeSourceMapBuilder::kChangePosition: {
261 int32_t position = stream.Read<int32_t>();
262 (*token_positions)[token_positions->length() - 1] =
263 TokenPosition(position);
264 break;
265 }
266 case CodeSourceMapBuilder::kAdvancePC: {
267 int32_t delta = stream.Read<int32_t>();
268 current_pc_offset += delta;
269 if (current_pc_offset > pc_offset) {
270 return;
271 }
272 break;
273 }
274 case CodeSourceMapBuilder::kPushFunction: {
275 int32_t func = stream.Read<int32_t>();
276 function_stack->Add(
277 &Function::Handle(Function::RawCast(functions_.At(func))));
278 token_positions->Add(CodeSourceMapBuilder::kInitialPosition);
279 break;
280 }
281 case CodeSourceMapBuilder::kPopFunction: {
282 // We never pop the root function.
283 ASSERT(function_stack->length() > 1);
284 ASSERT(token_positions->length() > 1);
285 function_stack->RemoveLast();
286 token_positions->RemoveLast();
287 break;
288 }
289 default:
290 UNREACHABLE();
291 }
292 }
293 }
294
295
296 #ifndef PRODUCT
297 void CodeSourceMapReader::PrintJSONInlineIntervals(JSONObject* jsobj) {
298 {
299 JSONArray inlined_functions(jsobj, "_inlinedFunctions");
300 Function& function = Function::Handle();
301 for (intptr_t i = 0; i < functions_.Length(); i++) {
302 function ^= functions_.At(i);
303 ASSERT(!function.IsNull());
304 inlined_functions.AddValue(function);
305 }
306 }
307
308 GrowableArray<intptr_t> function_stack;
309 JSONArray inline_intervals(jsobj, "_inlinedIntervals");
310 NoSafepointScope no_safepoint;
311 ReadStream stream(map_.Data(), map_.Length());
312
313 int32_t current_pc_offset = 0;
314 function_stack.Add(0);
315
316 while (stream.PendingBytes() > 0) {
317 uint8_t opcode = stream.Read<uint8_t>();
318 switch (opcode) {
319 case CodeSourceMapBuilder::kChangePosition: {
320 stream.Read<int32_t>();
321 break;
322 }
323 case CodeSourceMapBuilder::kAdvancePC: {
324 int32_t delta = stream.Read<int32_t>();
325 // Format: [start, end, inline functions...]
326 JSONArray inline_interval(&inline_intervals);
327 inline_interval.AddValue(static_cast<intptr_t>(current_pc_offset));
328 inline_interval.AddValue(
329 static_cast<intptr_t>(current_pc_offset + delta - 1));
330 for (intptr_t i = 0; i < function_stack.length(); i++) {
331 inline_interval.AddValue(function_stack[i]);
332 }
333 current_pc_offset += delta;
334 break;
335 }
336 case CodeSourceMapBuilder::kPushFunction: {
337 int32_t func = stream.Read<int32_t>();
338 function_stack.Add(func);
339 break;
340 }
341 case CodeSourceMapBuilder::kPopFunction: {
342 // We never pop the root function.
343 ASSERT(function_stack.length() > 1);
344 function_stack.RemoveLast();
345 break;
346 }
347 default:
348 UNREACHABLE();
349 }
350 }
351 }
352 #endif // !PRODUCT
353
354
355 void CodeSourceMapReader::DumpInlineIntervals(uword start) {
356 GrowableArray<const Function*> function_stack;
357 LogBlock lb;
358 NoSafepointScope no_safepoint;
359 ReadStream stream(map_.Data(), map_.Length());
360
361 int32_t current_pc_offset = 0;
362 function_stack.Add(&root_);
363
364 THR_Print("Inline intervals {\n");
365 while (stream.PendingBytes() > 0) {
366 uint8_t opcode = stream.Read<uint8_t>();
367 switch (opcode) {
368 case CodeSourceMapBuilder::kChangePosition: {
369 stream.Read<int32_t>();
370 break;
371 }
372 case CodeSourceMapBuilder::kAdvancePC: {
373 int32_t delta = stream.Read<int32_t>();
374 THR_Print("%" Px "-%" Px ": ", start + current_pc_offset,
375 start + current_pc_offset + delta - 1);
376 for (intptr_t i = 0; i < function_stack.length(); i++) {
377 THR_Print("%s ", function_stack[i]->ToCString());
378 }
379 THR_Print("\n");
380 current_pc_offset += delta;
381 break;
382 }
383 case CodeSourceMapBuilder::kPushFunction: {
384 int32_t func = stream.Read<int32_t>();
385 function_stack.Add(
386 &Function::Handle(Function::RawCast(functions_.At(func))));
387 break;
388 }
389 case CodeSourceMapBuilder::kPopFunction: {
390 // We never pop the root function.
391 ASSERT(function_stack.length() > 1);
392 function_stack.RemoveLast();
393 break;
394 }
395 default:
396 UNREACHABLE();
397 }
398 }
399 THR_Print("}\n");
400 }
401
402
403 void CodeSourceMapReader::DumpSourcePositions(uword start) {
404 GrowableArray<const Function*> function_stack;
405 GrowableArray<TokenPosition> token_positions;
406 LogBlock lb;
407 NoSafepointScope no_safepoint;
408 ReadStream stream(map_.Data(), map_.Length());
409
410 int32_t current_pc_offset = 0;
411 function_stack.Add(&root_);
412 token_positions.Add(CodeSourceMapBuilder::kInitialPosition);
413
414 THR_Print("Source positions {\n");
415 while (stream.PendingBytes() > 0) {
416 uint8_t opcode = stream.Read<uint8_t>();
417 switch (opcode) {
418 case CodeSourceMapBuilder::kChangePosition: {
419 int32_t position = stream.Read<int32_t>();
420 token_positions[token_positions.length() - 1] = TokenPosition(position);
421 break;
422 }
423 case CodeSourceMapBuilder::kAdvancePC: {
424 int32_t delta = stream.Read<int32_t>();
425 THR_Print("%" Px "-%" Px ": ", start + current_pc_offset,
426 start + current_pc_offset + delta - 1);
427 for (intptr_t i = 0; i < function_stack.length(); i++) {
428 THR_Print("%s@%" Pd " ", function_stack[i]->ToCString(),
429 token_positions[i].value());
430 }
431 THR_Print("\n");
432 current_pc_offset += delta;
433 break;
434 }
435 case CodeSourceMapBuilder::kPushFunction: {
436 int32_t func = stream.Read<int32_t>();
437 function_stack.Add(
438 &Function::Handle(Function::RawCast(functions_.At(func))));
439 token_positions.Add(CodeSourceMapBuilder::kInitialPosition);
440 break;
441 }
442 case CodeSourceMapBuilder::kPopFunction: {
443 // We never pop the root function.
444 ASSERT(function_stack.length() > 1);
445 ASSERT(token_positions.length() > 1);
446 function_stack.RemoveLast();
447 token_positions.RemoveLast();
448 break;
449 }
450 default:
451 UNREACHABLE();
452 }
453 }
454 THR_Print("}\n");
455 }
456
135 } // namespace dart 457 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698