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

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

Powered by Google App Engine
This is Rietveld 408576698