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

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

Issue 904763003: Redesign inlining interval computation. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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/globals.h" // Needed here to get TARGET_ARCH_XXX. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_XXX.
6 6
7 #include "vm/flow_graph_compiler.h" 7 #include "vm/flow_graph_compiler.h"
8 8
9 #include "vm/bit_vector.h" 9 #include "vm/bit_vector.h"
10 #include "vm/cha.h" 10 #include "vm/cha.h"
11 #include "vm/dart_entry.h" 11 #include "vm/dart_entry.h"
12 #include "vm/debugger.h" 12 #include "vm/debugger.h"
13 #include "vm/deopt_instructions.h" 13 #include "vm/deopt_instructions.h"
14 #include "vm/exceptions.h" 14 #include "vm/exceptions.h"
15 #include "vm/flow_graph_allocator.h" 15 #include "vm/flow_graph_allocator.h"
16 #include "vm/il_printer.h" 16 #include "vm/il_printer.h"
17 #include "vm/intrinsifier.h" 17 #include "vm/intrinsifier.h"
18 #include "vm/locations.h" 18 #include "vm/locations.h"
19 #include "vm/longjump.h" 19 #include "vm/longjump.h"
20 #include "vm/object_store.h" 20 #include "vm/object_store.h"
21 #include "vm/parser.h" 21 #include "vm/parser.h"
22 #include "vm/raw_object.h" 22 #include "vm/raw_object.h"
23 #include "vm/stack_frame.h" 23 #include "vm/stack_frame.h"
24 #include "vm/stub_code.h" 24 #include "vm/stub_code.h"
25 #include "vm/symbols.h" 25 #include "vm/symbols.h"
26 26
27 namespace dart { 27 namespace dart {
28 28
29 DEFINE_FLAG(bool, trace_inlining_intervals, false,
30 "Inlining interval diagnostics");
31 DEFINE_FLAG(bool, enable_simd_inline, true,
32 "Enable inlining of SIMD related method calls.");
33 DEFINE_FLAG(int, min_optimization_counter_threshold, 5000,
34 "The minimum invocation count for a function.");
35 DEFINE_FLAG(int, optimization_counter_scale, 2000,
36 "The scale of invocation count, by size of the function.");
37 DEFINE_FLAG(bool, source_lines, false, "Emit source line as assembly comment.");
38
29 DECLARE_FLAG(bool, code_comments); 39 DECLARE_FLAG(bool, code_comments);
40 DECLARE_FLAG(int, deoptimize_every);
41 DECLARE_FLAG(charp, deoptimize_filter);
30 DECLARE_FLAG(bool, disassemble); 42 DECLARE_FLAG(bool, disassemble);
31 DECLARE_FLAG(bool, disassemble_optimized); 43 DECLARE_FLAG(bool, disassemble_optimized);
32 DECLARE_FLAG(bool, emit_edge_counters); 44 DECLARE_FLAG(bool, emit_edge_counters);
33 DECLARE_FLAG(bool, enable_type_checks); 45 DECLARE_FLAG(bool, enable_type_checks);
34 DECLARE_FLAG(bool, intrinsify); 46 DECLARE_FLAG(bool, intrinsify);
47 DECLARE_FLAG(int, optimization_counter_threshold);
35 DECLARE_FLAG(bool, propagate_ic_data); 48 DECLARE_FLAG(bool, propagate_ic_data);
36 DECLARE_FLAG(int, optimization_counter_threshold);
37 DECLARE_FLAG(int, regexp_optimization_counter_threshold); 49 DECLARE_FLAG(int, regexp_optimization_counter_threshold);
38 DEFINE_FLAG(int, optimization_counter_scale, 2000,
39 "The scale of invocation count, by size of the function.");
40 DEFINE_FLAG(int, min_optimization_counter_threshold, 5000,
41 "The minimum invocation count for a function.");
42 DECLARE_FLAG(int, reoptimization_counter_threshold); 50 DECLARE_FLAG(int, reoptimization_counter_threshold);
51 DECLARE_FLAG(int, stacktrace_every);
52 DECLARE_FLAG(charp, stacktrace_filter);
43 DECLARE_FLAG(bool, use_cha); 53 DECLARE_FLAG(bool, use_cha);
44 DECLARE_FLAG(bool, use_osr); 54 DECLARE_FLAG(bool, use_osr);
45 DECLARE_FLAG(int, stacktrace_every);
46 DECLARE_FLAG(charp, stacktrace_filter);
47 DECLARE_FLAG(int, deoptimize_every);
48 DECLARE_FLAG(charp, deoptimize_filter);
49 DECLARE_FLAG(bool, warn_on_javascript_compatibility); 55 DECLARE_FLAG(bool, warn_on_javascript_compatibility);
50 DEFINE_FLAG(bool, enable_simd_inline, true,
51 "Enable inlining of SIMD related method calls.");
52 DEFINE_FLAG(bool, source_lines, false, "Emit source line as assembly comment.");
53 56
54 // Quick access to the locally defined isolate() method. 57 // Quick access to the locally defined isolate() method.
55 #define I (isolate()) 58 #define I (isolate())
56 59
57 // Assign locations to incoming arguments, i.e., values pushed above spill slots 60 // Assign locations to incoming arguments, i.e., values pushed above spill slots
58 // with PushArgument. Recursively allocates from outermost to innermost 61 // with PushArgument. Recursively allocates from outermost to innermost
59 // environment. 62 // environment.
60 void CompilerDeoptInfo::AllocateIncomingParametersRecursive( 63 void CompilerDeoptInfo::AllocateIncomingParametersRecursive(
61 Environment* env, 64 Environment* env,
62 intptr_t* stack_height) { 65 intptr_t* stack_height) {
(...skipping 19 matching lines...) Expand all
82 } 85 }
83 } 86 }
84 } 87 }
85 88
86 89
87 FlowGraphCompiler::FlowGraphCompiler( 90 FlowGraphCompiler::FlowGraphCompiler(
88 Assembler* assembler, 91 Assembler* assembler,
89 FlowGraph* flow_graph, 92 FlowGraph* flow_graph,
90 const ParsedFunction& parsed_function, 93 const ParsedFunction& parsed_function,
91 bool is_optimizing, 94 bool is_optimizing,
92 const GrowableArray<const Function*>& inline_id_to_function) 95 const GrowableArray<const Function*>& inline_id_to_function,
96 const GrowableArray<intptr_t>& caller_inline_id)
93 : isolate_(Isolate::Current()), 97 : isolate_(Isolate::Current()),
94 assembler_(assembler), 98 assembler_(assembler),
95 parsed_function_(parsed_function), 99 parsed_function_(parsed_function),
96 flow_graph_(*flow_graph), 100 flow_graph_(*flow_graph),
97 block_order_(*flow_graph->CodegenBlockOrder(is_optimizing)), 101 block_order_(*flow_graph->CodegenBlockOrder(is_optimizing)),
98 current_block_(NULL), 102 current_block_(NULL),
99 exception_handlers_list_(NULL), 103 exception_handlers_list_(NULL),
100 pc_descriptors_list_(NULL), 104 pc_descriptors_list_(NULL),
101 stackmap_table_builder_( 105 stackmap_table_builder_(
102 is_optimizing ? new StackmapTableBuilder() : NULL), 106 is_optimizing ? new StackmapTableBuilder() : NULL),
(...skipping 17 matching lines...) Expand all
120 list_class_(Class::ZoneHandle( 124 list_class_(Class::ZoneHandle(
121 Library::Handle(Library::CoreLibrary()). 125 Library::Handle(Library::CoreLibrary()).
122 LookupClass(Symbols::List()))), 126 LookupClass(Symbols::List()))),
123 parallel_move_resolver_(this), 127 parallel_move_resolver_(this),
124 pending_deoptimization_env_(NULL), 128 pending_deoptimization_env_(NULL),
125 entry_patch_pc_offset_(Code::kInvalidPc), 129 entry_patch_pc_offset_(Code::kInvalidPc),
126 patch_code_pc_offset_(Code::kInvalidPc), 130 patch_code_pc_offset_(Code::kInvalidPc),
127 lazy_deopt_pc_offset_(Code::kInvalidPc), 131 lazy_deopt_pc_offset_(Code::kInvalidPc),
128 deopt_id_to_ic_data_(NULL), 132 deopt_id_to_ic_data_(NULL),
129 inlined_code_intervals_(NULL), 133 inlined_code_intervals_(NULL),
130 inline_id_to_function_(inline_id_to_function) { 134 inline_id_to_function_(inline_id_to_function),
135 caller_inline_id_(caller_inline_id) {
131 ASSERT(flow_graph->parsed_function().function().raw() == 136 ASSERT(flow_graph->parsed_function().function().raw() ==
132 parsed_function.function().raw()); 137 parsed_function.function().raw());
133 if (!is_optimizing) { 138 if (!is_optimizing) {
134 const intptr_t len = isolate()->deopt_id(); 139 const intptr_t len = isolate()->deopt_id();
135 deopt_id_to_ic_data_ = new(isolate()) ZoneGrowableArray<const ICData*>(len); 140 deopt_id_to_ic_data_ = new(isolate()) ZoneGrowableArray<const ICData*>(len);
136 deopt_id_to_ic_data_->SetLength(len); 141 deopt_id_to_ic_data_->SetLength(len);
137 for (intptr_t i = 0; i < len; i++) { 142 for (intptr_t i = 0; i < len; i++) {
138 (*deopt_id_to_ic_data_)[i] = NULL; 143 (*deopt_id_to_ic_data_)[i] = NULL;
139 } 144 }
140 const Array& old_saved_icdata = Array::Handle(isolate(), 145 const Array& old_saved_icdata = Array::Handle(isolate(),
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 } 350 }
346 } 351 }
347 } 352 }
348 } 353 }
349 354
350 355
351 // We collect intervals while generating code. 356 // We collect intervals while generating code.
352 struct IntervalStruct { 357 struct IntervalStruct {
353 // 'start' and 'end' are pc-offsets. 358 // 'start' and 'end' are pc-offsets.
354 intptr_t start; 359 intptr_t start;
355 intptr_t end;
356 intptr_t inlining_id; 360 intptr_t inlining_id;
357 IntervalStruct(intptr_t s, intptr_t e, intptr_t id) 361 IntervalStruct(intptr_t s, intptr_t id) : start(s), inlining_id(id) {}
358 : start(s), end(e), inlining_id(id) {} 362 void Dump() {
363 OS::Print("start: %" Px " id: %" Pd "", start, inlining_id);
364 }
359 }; 365 };
360 366
361 367
362 void FlowGraphCompiler::VisitBlocks() { 368 void FlowGraphCompiler::VisitBlocks() {
363 CompactBlocks(); 369 CompactBlocks();
364 const ZoneGrowableArray<BlockEntryInstr*>* loop_headers = NULL; 370 const ZoneGrowableArray<BlockEntryInstr*>* loop_headers = NULL;
365 if (Assembler::EmittingComments()) { 371 if (Assembler::EmittingComments()) {
366 // 'loop_headers' were cleared, recompute. 372 // 'loop_headers' were cleared, recompute.
367 loop_headers = flow_graph().ComputeLoops(); 373 loop_headers = flow_graph().ComputeLoops();
368 ASSERT(loop_headers != NULL); 374 ASSERT(loop_headers != NULL);
(...skipping 18 matching lines...) Expand all
387 393
388 entry->set_offset(assembler()->CodeSize()); 394 entry->set_offset(assembler()->CodeSize());
389 entry->EmitNativeCode(this); 395 entry->EmitNativeCode(this);
390 // Compile all successors until an exit, branch, or a block entry. 396 // Compile all successors until an exit, branch, or a block entry.
391 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 397 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
392 Instruction* instr = it.Current(); 398 Instruction* instr = it.Current();
393 // Compose intervals. 399 // Compose intervals.
394 if (instr->has_inlining_id() && is_optimizing()) { 400 if (instr->has_inlining_id() && is_optimizing()) {
395 if (prev_inlining_id != instr->inlining_id()) { 401 if (prev_inlining_id != instr->inlining_id()) {
396 intervals.Add(IntervalStruct(prev_offset, 402 intervals.Add(IntervalStruct(prev_offset,
397 assembler()->CodeSize(),
398 prev_inlining_id)); 403 prev_inlining_id));
399 prev_offset = assembler()->CodeSize(); 404 prev_offset = assembler()->CodeSize();
400 prev_inlining_id = instr->inlining_id(); 405 prev_inlining_id = instr->inlining_id();
401 if (prev_inlining_id > max_inlining_id) { 406 if (prev_inlining_id > max_inlining_id) {
402 max_inlining_id = prev_inlining_id; 407 max_inlining_id = prev_inlining_id;
403 } 408 }
404 } 409 }
405 } 410 }
406 if (FLAG_code_comments || 411 if (FLAG_code_comments ||
407 FLAG_disassemble || 412 FLAG_disassemble ||
408 FLAG_disassemble_optimized) { 413 FLAG_disassemble_optimized) {
409 if (FLAG_source_lines) { 414 if (FLAG_source_lines) {
410 EmitSourceLine(instr); 415 EmitSourceLine(instr);
411 } 416 }
412 EmitComment(instr); 417 EmitComment(instr);
413 } 418 }
414 if (instr->IsParallelMove()) { 419 if (instr->IsParallelMove()) {
415 parallel_move_resolver_.EmitNativeCode(instr->AsParallelMove()); 420 parallel_move_resolver_.EmitNativeCode(instr->AsParallelMove());
416 } else { 421 } else {
417 EmitInstructionPrologue(instr); 422 EmitInstructionPrologue(instr);
418 ASSERT(pending_deoptimization_env_ == NULL); 423 ASSERT(pending_deoptimization_env_ == NULL);
419 pending_deoptimization_env_ = instr->env(); 424 pending_deoptimization_env_ = instr->env();
420 instr->EmitNativeCode(this); 425 instr->EmitNativeCode(this);
421 pending_deoptimization_env_ = NULL; 426 pending_deoptimization_env_ = NULL;
422 EmitInstructionEpilogue(instr); 427 EmitInstructionEpilogue(instr);
423 } 428 }
424 } 429 }
425 } 430 }
426 431
427 intervals.Add(IntervalStruct(prev_offset, assembler()->CodeSize(), 432 if (inline_id_to_function_.length() > max_inlining_id + 1) {
428 prev_inlining_id)); 433 // TODO(srdjan): Some inlined function can disappear,
429 // Note that ranges [start..end] must be monotonically increasing in 434 // truncate 'inline_id_to_function_'.
430 // 'intervals' array. 435 }
436
437 intervals.Add(IntervalStruct(prev_offset, prev_inlining_id));
431 inlined_code_intervals_ = &Array::ZoneHandle(Array::New( 438 inlined_code_intervals_ = &Array::ZoneHandle(Array::New(
432 (max_inlining_id + 1) * Code::kInlIntNumEntries, Heap::kOld)); 439 intervals.length() * Code::kInlIntNumEntries, Heap::kOld));
433
434 Smi& start_h = Smi::Handle(); 440 Smi& start_h = Smi::Handle();
435 Smi& end_h = Smi::Handle(); 441 Smi& caller_inline_id = Smi::Handle();
442 Smi& inline_id = Smi::Handle();
436 for (intptr_t i = 0; i < intervals.length(); i++) { 443 for (intptr_t i = 0; i < intervals.length(); i++) {
437 const intptr_t id = intervals[i].inlining_id; 444 if (FLAG_trace_inlining_intervals && is_optimizing()) {
438 end_h = Smi::New(intervals[i].end);
439 if (inlined_code_intervals_->At
440 (id * Code::kInlIntNumEntries + Code::kInlIntFunction) ==
441 Object::null()) {
442 start_h = Smi::New(intervals[i].start);
443 inlined_code_intervals_->SetAt(
444 id * Code::kInlIntNumEntries + Code::kInlIntStart, start_h);
445 inlined_code_intervals_->SetAt(
446 id * Code::kInlIntNumEntries + Code::kInlIntEnd, end_h);
447 const Function* function = 445 const Function* function =
448 inline_id_to_function_.At(intervals[i].inlining_id); 446 inline_id_to_function_.At(intervals[i].inlining_id);
449 inlined_code_intervals_->SetAt( 447 intervals[i].Dump();
450 id * Code::kInlIntNumEntries + Code::kInlIntFunction, *function); 448 OS::Print(" %s parent %" Pd "\n",
451 } else { 449 function->ToQualifiedCString(),
452 // Check for monotonic increase. 450 caller_inline_id_[intervals[i].inlining_id]);
453 #if defined(DEBUG) 451 }
454 Smi& temp = Smi::Handle(); 452 const intptr_t id = intervals[i].inlining_id;
455 temp ^= inlined_code_intervals_->At( 453 start_h = Smi::New(intervals[i].start);
456 id * Code::kInlIntNumEntries + Code::kInlIntStart); 454 inline_id = Smi::New(id);
457 start_h = Smi::New(intervals[i].start); 455 caller_inline_id = Smi::New(caller_inline_id_[intervals[i].inlining_id]);
458 ASSERT(temp.Value() <= start_h.Value()); 456
459 temp ^= inlined_code_intervals_->At( 457 const intptr_t p = i * Code::kInlIntNumEntries;
460 id * Code::kInlIntNumEntries + Code::kInlIntEnd); 458 inlined_code_intervals_->SetAt(p + Code::kInlIntStart, start_h);
461 ASSERT(temp.Value() <= end_h.Value()); 459 inlined_code_intervals_->SetAt(p + Code::kInlIntInliningId, inline_id);
462 const Function* function = 460 inlined_code_intervals_->SetAt(p + Code::kInlIntCallerId, caller_inline_id);
463 inline_id_to_function_.At(intervals[i].inlining_id); 461 }
464 Function& f = Function::Handle(); 462 set_current_block(NULL);
465 f ^= inlined_code_intervals_->At( 463 if (FLAG_trace_inlining_intervals && is_optimizing()) {
466 id * Code::kInlIntNumEntries + Code::kInlIntFunction); 464 OS::Print("Intervals:\n");
467 ASSERT(function->raw() == f.raw()); 465 Smi& temp = Smi::Handle();
468 #endif 466 for (intptr_t i = 0; i < inlined_code_intervals_->Length();
469 inlined_code_intervals_->SetAt( 467 i += Code::kInlIntNumEntries) {
470 id * Code::kInlIntNumEntries + Code::kInlIntEnd, end_h); 468 temp ^= inlined_code_intervals_->At(i + Code::kInlIntStart);
469 ASSERT(!temp.IsNull());
470 OS::Print("% " Pd " start: %" Px " ", i, temp.Value());
471 temp ^= inlined_code_intervals_->At(i + Code::kInlIntInliningId);
472 OS::Print("inl-id: %" Pd " ", temp.Value());
473 temp ^= inlined_code_intervals_->At(i + Code::kInlIntCallerId);
474 OS::Print("caller-id: %" Pd " \n", temp.Value());
471 } 475 }
472 } 476 }
473 set_current_block(NULL);
474 } 477 }
475 478
476 479
477 void FlowGraphCompiler::Bailout(const char* reason) { 480 void FlowGraphCompiler::Bailout(const char* reason) {
478 const Function& function = parsed_function_.function(); 481 const Function& function = parsed_function_.function();
479 Report::MessageF(Report::kBailout, 482 Report::MessageF(Report::kBailout,
480 Script::Handle(function.script()), 483 Script::Handle(function.script()),
481 function.token_pos(), 484 function.token_pos(),
482 "FlowGraphCompiler Bailout: %s %s", 485 "FlowGraphCompiler Bailout: %s %s",
483 String::Handle(function.name()).ToCString(), 486 String::Handle(function.name()).ToCString(),
(...skipping 1089 matching lines...) Expand 10 before | Expand all | Expand 10 after
1573 return int32x4_class(); 1576 return int32x4_class();
1574 case kUnboxedMint: 1577 case kUnboxedMint:
1575 return mint_class(); 1578 return mint_class();
1576 default: 1579 default:
1577 UNREACHABLE(); 1580 UNREACHABLE();
1578 return Class::ZoneHandle(); 1581 return Class::ZoneHandle();
1579 } 1582 }
1580 } 1583 }
1581 1584
1582 1585
1586 RawArray* FlowGraphCompiler::InliningIdToFunction() const {
1587 const Array& res = Array::Handle(
1588 Array::New(inline_id_to_function_.length(), Heap::kOld));
1589 for (intptr_t i = 0; i < inline_id_to_function_.length(); i++) {
1590 res.SetAt(i, *inline_id_to_function_[i]);
1591 }
1592 return res.raw();
1593 }
1594
1595
1583 } // namespace dart 1596 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698