Chromium Code Reviews| OLD | NEW |
|---|---|
| 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" |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 73 if (it.CurrentLocation().IsInvalid()) { | 73 if (it.CurrentLocation().IsInvalid()) { |
| 74 MaterializeObjectInstr* mat = | 74 MaterializeObjectInstr* mat = |
| 75 it.CurrentValue()->definition()->AsMaterializeObject(); | 75 it.CurrentValue()->definition()->AsMaterializeObject(); |
| 76 ASSERT(mat != NULL); | 76 ASSERT(mat != NULL); |
| 77 builder->AddMaterialization(mat); | 77 builder->AddMaterialization(mat); |
| 78 } | 78 } |
| 79 } | 79 } |
| 80 } | 80 } |
| 81 | 81 |
| 82 | 82 |
| 83 FlowGraphCompiler::FlowGraphCompiler(Assembler* assembler, | 83 FlowGraphCompiler::FlowGraphCompiler( |
| 84 FlowGraph* flow_graph, | 84 Assembler* assembler, |
| 85 bool is_optimizing) | 85 FlowGraph* flow_graph, |
| 86 : isolate_(Isolate::Current()), | 86 bool is_optimizing, |
| 87 assembler_(assembler), | 87 const GrowableArray<const Function*>& inline_id_to_function) |
| 88 parsed_function_(*flow_graph->parsed_function()), | 88 : isolate_(Isolate::Current()), |
| 89 flow_graph_(*flow_graph), | 89 assembler_(assembler), |
| 90 block_order_(*flow_graph->CodegenBlockOrder(is_optimizing)), | 90 parsed_function_(*flow_graph->parsed_function()), |
| 91 current_block_(NULL), | 91 flow_graph_(*flow_graph), |
| 92 exception_handlers_list_(NULL), | 92 block_order_(*flow_graph->CodegenBlockOrder(is_optimizing)), |
| 93 pc_descriptors_list_(NULL), | 93 current_block_(NULL), |
| 94 stackmap_table_builder_( | 94 exception_handlers_list_(NULL), |
| 95 is_optimizing ? new StackmapTableBuilder() : NULL), | 95 pc_descriptors_list_(NULL), |
| 96 block_info_(block_order_.length()), | 96 stackmap_table_builder_( |
| 97 deopt_infos_(), | 97 is_optimizing ? new StackmapTableBuilder() : NULL), |
| 98 static_calls_target_table_(GrowableObjectArray::ZoneHandle( | 98 block_info_(block_order_.length()), |
| 99 GrowableObjectArray::New())), | 99 deopt_infos_(), |
| 100 is_optimizing_(is_optimizing), | 100 static_calls_target_table_(GrowableObjectArray::ZoneHandle( |
| 101 may_reoptimize_(false), | 101 GrowableObjectArray::New())), |
| 102 intrinsic_mode_(false), | 102 is_optimizing_(is_optimizing), |
| 103 double_class_(Class::ZoneHandle( | 103 may_reoptimize_(false), |
| 104 isolate_->object_store()->double_class())), | 104 intrinsic_mode_(false), |
| 105 mint_class_(Class::ZoneHandle( | 105 double_class_(Class::ZoneHandle( |
| 106 isolate_->object_store()->mint_class())), | 106 isolate_->object_store()->double_class())), |
| 107 float32x4_class_(Class::ZoneHandle( | 107 mint_class_(Class::ZoneHandle( |
| 108 isolate_->object_store()->float32x4_class())), | 108 isolate_->object_store()->mint_class())), |
| 109 float64x2_class_(Class::ZoneHandle( | 109 float32x4_class_(Class::ZoneHandle( |
| 110 isolate_->object_store()->float64x2_class())), | 110 isolate_->object_store()->float32x4_class())), |
| 111 int32x4_class_(Class::ZoneHandle( | 111 float64x2_class_(Class::ZoneHandle( |
| 112 isolate_->object_store()->int32x4_class())), | 112 isolate_->object_store()->float64x2_class())), |
| 113 list_class_(Class::ZoneHandle( | 113 int32x4_class_(Class::ZoneHandle( |
| 114 Library::Handle(Library::CoreLibrary()). | 114 isolate_->object_store()->int32x4_class())), |
| 115 LookupClass(Symbols::List()))), | 115 list_class_(Class::ZoneHandle( |
| 116 parallel_move_resolver_(this), | 116 Library::Handle(Library::CoreLibrary()). |
| 117 pending_deoptimization_env_(NULL), | 117 LookupClass(Symbols::List()))), |
| 118 entry_patch_pc_offset_(Code::kInvalidPc), | 118 parallel_move_resolver_(this), |
| 119 patch_code_pc_offset_(Code::kInvalidPc), | 119 pending_deoptimization_env_(NULL), |
| 120 lazy_deopt_pc_offset_(Code::kInvalidPc) { | 120 entry_patch_pc_offset_(Code::kInvalidPc), |
| 121 patch_code_pc_offset_(Code::kInvalidPc), | |
| 122 lazy_deopt_pc_offset_(Code::kInvalidPc), | |
| 123 deopt_id_to_ic_data_(NULL), | |
| 124 inlined_code_intervals_(NULL), | |
| 125 inline_id_to_function_(inline_id_to_function) { | |
| 121 if (!is_optimizing) { | 126 if (!is_optimizing) { |
| 122 const intptr_t len = isolate()->deopt_id(); | 127 const intptr_t len = isolate()->deopt_id(); |
| 123 deopt_id_to_ic_data_ = new(isolate()) ZoneGrowableArray<const ICData*>(len); | 128 deopt_id_to_ic_data_ = new(isolate()) ZoneGrowableArray<const ICData*>(len); |
| 124 deopt_id_to_ic_data_->SetLength(len); | 129 deopt_id_to_ic_data_->SetLength(len); |
| 125 for (intptr_t i = 0; i < len; i++) { | 130 for (intptr_t i = 0; i < len; i++) { |
| 126 (*deopt_id_to_ic_data_)[i] = NULL; | 131 (*deopt_id_to_ic_data_)[i] = NULL; |
| 127 } | 132 } |
| 128 const Array& old_saved_icdata = Array::Handle(isolate(), | 133 const Array& old_saved_icdata = Array::Handle(isolate(), |
| 129 flow_graph->parsed_function()->function().ic_data_array()); | 134 flow_graph->parsed_function()->function().ic_data_array()); |
| 130 const intptr_t saved_len = | 135 const intptr_t saved_len = |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 329 loop_it.Advance()) { | 334 loop_it.Advance()) { |
| 330 if (loop_it.Current() == block.preorder_number()) { | 335 if (loop_it.Current() == block.preorder_number()) { |
| 331 assembler->Comment(" Loop %" Pd "", loop_id); | 336 assembler->Comment(" Loop %" Pd "", loop_id); |
| 332 } | 337 } |
| 333 } | 338 } |
| 334 } | 339 } |
| 335 } | 340 } |
| 336 } | 341 } |
| 337 | 342 |
| 338 | 343 |
| 344 // We collect intervals while generating code. | |
| 345 struct IntervalStruct { | |
| 346 // 'start' and 'end' are pc-offsets. | |
| 347 intptr_t start; | |
| 348 intptr_t end; | |
| 349 intptr_t inlining_id; | |
| 350 IntervalStruct(intptr_t s, intptr_t e, intptr_t id) | |
| 351 : start(s), end(e), inlining_id(id) {} | |
| 352 }; | |
| 353 | |
| 354 | |
| 339 void FlowGraphCompiler::VisitBlocks() { | 355 void FlowGraphCompiler::VisitBlocks() { |
| 340 CompactBlocks(); | 356 CompactBlocks(); |
| 341 const ZoneGrowableArray<BlockEntryInstr*>* loop_headers = NULL; | 357 const ZoneGrowableArray<BlockEntryInstr*>* loop_headers = NULL; |
| 342 if (Assembler::EmittingComments()) { | 358 if (Assembler::EmittingComments()) { |
| 343 // 'loop_headers' were cleared, recompute. | 359 // 'loop_headers' were cleared, recompute. |
| 344 loop_headers = flow_graph().ComputeLoops(); | 360 loop_headers = flow_graph().ComputeLoops(); |
| 345 ASSERT(loop_headers != NULL); | 361 ASSERT(loop_headers != NULL); |
| 346 } | 362 } |
| 347 | 363 |
| 364 // For collecting intervals of inlined code. | |
| 365 GrowableArray<IntervalStruct> intervals; | |
| 366 intptr_t prev_offset = 0; | |
| 367 intptr_t prev_inlining_id = 0; | |
| 368 intptr_t max_inlining_id = 0; | |
| 348 for (intptr_t i = 0; i < block_order().length(); ++i) { | 369 for (intptr_t i = 0; i < block_order().length(); ++i) { |
| 349 // Compile the block entry. | 370 // Compile the block entry. |
| 350 BlockEntryInstr* entry = block_order()[i]; | 371 BlockEntryInstr* entry = block_order()[i]; |
| 351 assembler()->Comment("B%" Pd "", entry->block_id()); | 372 assembler()->Comment("B%" Pd "", entry->block_id()); |
| 352 set_current_block(entry); | 373 set_current_block(entry); |
| 353 | 374 |
| 354 if (WasCompacted(entry)) { | 375 if (WasCompacted(entry)) { |
| 355 continue; | 376 continue; |
| 356 } | 377 } |
| 357 | 378 |
| 358 LoopInfoComment(assembler(), *entry, *loop_headers); | 379 LoopInfoComment(assembler(), *entry, *loop_headers); |
| 359 | 380 |
| 360 entry->set_offset(assembler()->CodeSize()); | 381 entry->set_offset(assembler()->CodeSize()); |
| 361 entry->EmitNativeCode(this); | 382 entry->EmitNativeCode(this); |
| 362 // Compile all successors until an exit, branch, or a block entry. | 383 // Compile all successors until an exit, branch, or a block entry. |
| 363 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { | 384 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
| 364 Instruction* instr = it.Current(); | 385 Instruction* instr = it.Current(); |
| 386 // Compose intervals. | |
| 387 if (instr->has_inlining_id() && is_optimizing()) { | |
| 388 if (prev_inlining_id != instr->inlining_id()) { | |
| 389 intervals.Add(IntervalStruct(prev_offset, | |
| 390 assembler()->CodeSize(), | |
| 391 prev_inlining_id)); | |
| 392 prev_offset = assembler()->CodeSize(); | |
| 393 prev_inlining_id = instr->inlining_id(); | |
| 394 if (prev_inlining_id > max_inlining_id) { | |
| 395 max_inlining_id = prev_inlining_id; | |
| 396 } | |
| 397 } | |
| 398 } | |
| 365 if (FLAG_code_comments || | 399 if (FLAG_code_comments || |
| 366 FLAG_disassemble || | 400 FLAG_disassemble || |
| 367 FLAG_disassemble_optimized) { | 401 FLAG_disassemble_optimized) { |
| 368 if (FLAG_source_lines) { | 402 if (FLAG_source_lines) { |
| 369 EmitSourceLine(instr); | 403 EmitSourceLine(instr); |
| 370 } | 404 } |
| 371 EmitComment(instr); | 405 EmitComment(instr); |
| 372 } | 406 } |
| 373 if (instr->IsParallelMove()) { | 407 if (instr->IsParallelMove()) { |
| 374 parallel_move_resolver_.EmitNativeCode(instr->AsParallelMove()); | 408 parallel_move_resolver_.EmitNativeCode(instr->AsParallelMove()); |
| 375 } else { | 409 } else { |
| 376 EmitInstructionPrologue(instr); | 410 EmitInstructionPrologue(instr); |
| 377 ASSERT(pending_deoptimization_env_ == NULL); | 411 ASSERT(pending_deoptimization_env_ == NULL); |
| 378 pending_deoptimization_env_ = instr->env(); | 412 pending_deoptimization_env_ = instr->env(); |
| 379 instr->EmitNativeCode(this); | 413 instr->EmitNativeCode(this); |
| 380 pending_deoptimization_env_ = NULL; | 414 pending_deoptimization_env_ = NULL; |
| 381 EmitInstructionEpilogue(instr); | 415 EmitInstructionEpilogue(instr); |
| 382 } | 416 } |
| 383 } | 417 } |
| 384 } | 418 } |
| 419 | |
| 420 intervals.Add(IntervalStruct(prev_offset, assembler()->CodeSize(), | |
| 421 prev_inlining_id)); | |
| 422 // Note that ranges [start..end] must be monotonically increasing in | |
| 423 // 'intervals' array. | |
| 424 inlined_code_intervals_ = &Array::ZoneHandle(Array::New( | |
| 425 (max_inlining_id + 1) * Code::kInlIntNumEntries, Heap::kOld)); | |
| 426 | |
| 427 Smi& start_h = Smi::Handle(); | |
| 428 Smi& end_h = Smi::Handle(); | |
| 429 for (intptr_t i = 0; i < intervals.length(); i++) { | |
| 430 const intptr_t id = intervals[i].inlining_id; | |
| 431 end_h = Smi::New(intervals[i].end); | |
| 432 if (inlined_code_intervals_->At | |
| 433 (id * Code::kInlIntNumEntries + Code::kInlIntFunction) == | |
| 434 Object::null()) { | |
| 435 start_h = Smi::New(intervals[i].start); | |
| 436 inlined_code_intervals_->SetAt( | |
| 437 id * Code::kInlIntNumEntries + Code::kInlIntStart, start_h); | |
| 438 inlined_code_intervals_->SetAt( | |
| 439 id * Code::kInlIntNumEntries + Code::kInlIntEnd, end_h); | |
| 440 const Function* function = | |
| 441 inline_id_to_function_.At(intervals[i].inlining_id); | |
| 442 inlined_code_intervals_->SetAt( | |
| 443 id * Code::kInlIntNumEntries + Code::kInlIntFunction, *function); | |
| 444 } else { | |
| 445 // Check for monotonic increase. | |
| 446 #if defined(DEBUG) | |
| 447 Smi& temp = Smi::Handle(); | |
| 448 temp ^= inlined_code_intervals_->At( | |
| 449 id * Code::kInlIntNumEntries + Code::kInlIntStart); | |
| 450 start_h = Smi::New(intervals[i].start); | |
| 451 ASSERT(temp.Value() <= start_h.Value()); | |
| 452 temp ^= inlined_code_intervals_->At( | |
| 453 id * Code::kInlIntNumEntries + Code::kInlIntEnd); | |
| 454 ASSERT(temp.Value() <= end_h.Value()); | |
| 455 #endif | |
|
Cutch
2014/12/19 18:15:01
Also add an ASSERT that functions match.
srdjan
2014/12/19 19:58:44
Done.
| |
| 456 inlined_code_intervals_->SetAt( | |
| 457 id * Code::kInlIntNumEntries + Code::kInlIntEnd, end_h); | |
| 458 } | |
| 459 } | |
| 385 set_current_block(NULL); | 460 set_current_block(NULL); |
| 386 } | 461 } |
| 387 | 462 |
| 388 | 463 |
| 389 void FlowGraphCompiler::Bailout(const char* reason) { | 464 void FlowGraphCompiler::Bailout(const char* reason) { |
| 390 const Function& function = parsed_function_.function(); | 465 const Function& function = parsed_function_.function(); |
| 391 Report::MessageF(Report::kBailout, | 466 Report::MessageF(Report::kBailout, |
| 392 Script::Handle(function.script()), | 467 Script::Handle(function.script()), |
| 393 function.token_pos(), | 468 function.token_pos(), |
| 394 "FlowGraphCompiler Bailout: %s %s", | 469 "FlowGraphCompiler Bailout: %s %s", |
| (...skipping 1085 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1480 case kUnboxedMint: | 1555 case kUnboxedMint: |
| 1481 return mint_class(); | 1556 return mint_class(); |
| 1482 default: | 1557 default: |
| 1483 UNREACHABLE(); | 1558 UNREACHABLE(); |
| 1484 return Class::ZoneHandle(); | 1559 return Class::ZoneHandle(); |
| 1485 } | 1560 } |
| 1486 } | 1561 } |
| 1487 | 1562 |
| 1488 | 1563 |
| 1489 } // namespace dart | 1564 } // namespace dart |
| OLD | NEW |