| 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 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 } | 418 } |
| 419 | 419 |
| 420 | 420 |
| 421 // We collect intervals while generating code. | 421 // We collect intervals while generating code. |
| 422 struct IntervalStruct { | 422 struct IntervalStruct { |
| 423 // 'start' and 'end' are pc-offsets. | 423 // 'start' and 'end' are pc-offsets. |
| 424 intptr_t start; | 424 intptr_t start; |
| 425 intptr_t inlining_id; | 425 intptr_t inlining_id; |
| 426 IntervalStruct(intptr_t s, intptr_t id) : start(s), inlining_id(id) {} | 426 IntervalStruct(intptr_t s, intptr_t id) : start(s), inlining_id(id) {} |
| 427 void Dump() { | 427 void Dump() { |
| 428 OS::Print("start: %" Px " id: %" Pd "", start, inlining_id); | 428 ISL_Print("start: 0x%" Px " iid: %" Pd " ", start, inlining_id); |
| 429 } | 429 } |
| 430 }; | 430 }; |
| 431 | 431 |
| 432 | 432 |
| 433 void FlowGraphCompiler::VisitBlocks() { | 433 void FlowGraphCompiler::VisitBlocks() { |
| 434 CompactBlocks(); | 434 CompactBlocks(); |
| 435 const ZoneGrowableArray<BlockEntryInstr*>* loop_headers = NULL; | 435 const ZoneGrowableArray<BlockEntryInstr*>* loop_headers = NULL; |
| 436 if (Assembler::EmittingComments()) { | 436 if (Assembler::EmittingComments()) { |
| 437 // 'loop_headers' were cleared, recompute. | 437 // 'loop_headers' were cleared, recompute. |
| 438 loop_headers = flow_graph().ComputeLoops(); | 438 loop_headers = flow_graph().ComputeLoops(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 463 LoopInfoComment(assembler(), *entry, *loop_headers); | 463 LoopInfoComment(assembler(), *entry, *loop_headers); |
| 464 | 464 |
| 465 entry->set_offset(assembler()->CodeSize()); | 465 entry->set_offset(assembler()->CodeSize()); |
| 466 entry->EmitNativeCode(this); | 466 entry->EmitNativeCode(this); |
| 467 // Compile all successors until an exit, branch, or a block entry. | 467 // Compile all successors until an exit, branch, or a block entry. |
| 468 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { | 468 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
| 469 Instruction* instr = it.Current(); | 469 Instruction* instr = it.Current(); |
| 470 // Compose intervals. | 470 // Compose intervals. |
| 471 if (instr->has_inlining_id() && is_optimizing()) { | 471 if (instr->has_inlining_id() && is_optimizing()) { |
| 472 if (prev_inlining_id != instr->inlining_id()) { | 472 if (prev_inlining_id != instr->inlining_id()) { |
| 473 intervals.Add(IntervalStruct(prev_offset, | 473 intervals.Add(IntervalStruct(prev_offset, prev_inlining_id)); |
| 474 prev_inlining_id)); | |
| 475 prev_offset = assembler()->CodeSize(); | 474 prev_offset = assembler()->CodeSize(); |
| 476 prev_inlining_id = instr->inlining_id(); | 475 prev_inlining_id = instr->inlining_id(); |
| 477 if (prev_inlining_id > max_inlining_id) { | 476 if (prev_inlining_id > max_inlining_id) { |
| 478 max_inlining_id = prev_inlining_id; | 477 max_inlining_id = prev_inlining_id; |
| 479 } | 478 } |
| 480 } | 479 } |
| 481 } | 480 } |
| 482 if (FLAG_code_comments || | 481 if (FLAG_code_comments || |
| 483 FLAG_disassemble || | 482 FLAG_disassemble || FLAG_disassemble_optimized) { |
| 484 FLAG_disassemble_optimized) { | |
| 485 if (FLAG_source_lines) { | 483 if (FLAG_source_lines) { |
| 486 EmitSourceLine(instr); | 484 EmitSourceLine(instr); |
| 487 } | 485 } |
| 488 EmitComment(instr); | 486 EmitComment(instr); |
| 489 } | 487 } |
| 490 if (instr->IsParallelMove()) { | 488 if (instr->IsParallelMove()) { |
| 491 parallel_move_resolver_.EmitNativeCode(instr->AsParallelMove()); | 489 parallel_move_resolver_.EmitNativeCode(instr->AsParallelMove()); |
| 492 } else { | 490 } else { |
| 493 EmitInstructionPrologue(instr); | 491 EmitInstructionPrologue(instr); |
| 494 ASSERT(pending_deoptimization_env_ == NULL); | 492 ASSERT(pending_deoptimization_env_ == NULL); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 509 ASSERT(is_optimizing() || FrameStateIsSafeToCall()); | 507 ASSERT(is_optimizing() || FrameStateIsSafeToCall()); |
| 510 #endif | 508 #endif |
| 511 } | 509 } |
| 512 | 510 |
| 513 if (inline_id_to_function_.length() > max_inlining_id + 1) { | 511 if (inline_id_to_function_.length() > max_inlining_id + 1) { |
| 514 // TODO(srdjan): Some inlined function can disappear, | 512 // TODO(srdjan): Some inlined function can disappear, |
| 515 // truncate 'inline_id_to_function_'. | 513 // truncate 'inline_id_to_function_'. |
| 516 } | 514 } |
| 517 | 515 |
| 518 if (is_optimizing()) { | 516 if (is_optimizing()) { |
| 517 LogBlock lb(Isolate::Current()); |
| 519 intervals.Add(IntervalStruct(prev_offset, prev_inlining_id)); | 518 intervals.Add(IntervalStruct(prev_offset, prev_inlining_id)); |
| 520 inlined_code_intervals_ = | 519 inlined_code_intervals_ = |
| 521 Array::New(intervals.length() * Code::kInlIntNumEntries, Heap::kOld); | 520 Array::New(intervals.length() * Code::kInlIntNumEntries, Heap::kOld); |
| 522 Smi& start_h = Smi::Handle(); | 521 Smi& start_h = Smi::Handle(); |
| 523 Smi& caller_inline_id = Smi::Handle(); | 522 Smi& caller_inline_id = Smi::Handle(); |
| 524 Smi& inline_id = Smi::Handle(); | 523 Smi& inline_id = Smi::Handle(); |
| 525 for (intptr_t i = 0; i < intervals.length(); i++) { | 524 for (intptr_t i = 0; i < intervals.length(); i++) { |
| 526 if (FLAG_trace_inlining_intervals && is_optimizing()) { | 525 if (FLAG_trace_inlining_intervals && is_optimizing()) { |
| 527 const Function* function = | 526 const Function& function = |
| 528 inline_id_to_function_.At(intervals[i].inlining_id); | 527 *inline_id_to_function_.At(intervals[i].inlining_id); |
| 529 intervals[i].Dump(); | 528 intervals[i].Dump(); |
| 530 OS::Print(" %s parent %" Pd "\n", | 529 ISL_Print(" parent iid %" Pd " %s\n", |
| 531 function->ToQualifiedCString(), | 530 caller_inline_id_[intervals[i].inlining_id], |
| 532 caller_inline_id_[intervals[i].inlining_id]); | 531 function.ToQualifiedCString()); |
| 533 } | 532 } |
| 533 |
| 534 const intptr_t id = intervals[i].inlining_id; | 534 const intptr_t id = intervals[i].inlining_id; |
| 535 start_h = Smi::New(intervals[i].start); | 535 start_h = Smi::New(intervals[i].start); |
| 536 inline_id = Smi::New(id); | 536 inline_id = Smi::New(id); |
| 537 caller_inline_id = Smi::New(caller_inline_id_[intervals[i].inlining_id]); | 537 caller_inline_id = Smi::New(caller_inline_id_[intervals[i].inlining_id]); |
| 538 | 538 |
| 539 const intptr_t p = i * Code::kInlIntNumEntries; | 539 const intptr_t p = i * Code::kInlIntNumEntries; |
| 540 inlined_code_intervals_.SetAt(p + Code::kInlIntStart, start_h); | 540 inlined_code_intervals_.SetAt(p + Code::kInlIntStart, start_h); |
| 541 inlined_code_intervals_.SetAt(p + Code::kInlIntInliningId, inline_id); | 541 inlined_code_intervals_.SetAt(p + Code::kInlIntInliningId, inline_id); |
| 542 inlined_code_intervals_.SetAt( | |
| 543 p + Code::kInlIntCallerId, caller_inline_id); | |
| 544 } | 542 } |
| 545 } | 543 } |
| 546 set_current_block(NULL); | 544 set_current_block(NULL); |
| 547 if (FLAG_trace_inlining_intervals && is_optimizing()) { | 545 if (FLAG_trace_inlining_intervals && is_optimizing()) { |
| 548 OS::Print("Intervals:\n"); | 546 LogBlock lb(Isolate::Current()); |
| 547 ISL_Print("Intervals:\n"); |
| 548 for (intptr_t cc = 0; cc < caller_inline_id_.length(); cc++) { |
| 549 ISL_Print(" iid: %" Pd " caller iid: %" Pd "\n", |
| 550 cc, caller_inline_id_[cc]); |
| 551 } |
| 549 Smi& temp = Smi::Handle(); | 552 Smi& temp = Smi::Handle(); |
| 550 for (intptr_t i = 0; i < inlined_code_intervals_.Length(); | 553 for (intptr_t i = 0; i < inlined_code_intervals_.Length(); |
| 551 i += Code::kInlIntNumEntries) { | 554 i += Code::kInlIntNumEntries) { |
| 552 temp ^= inlined_code_intervals_.At(i + Code::kInlIntStart); | 555 temp ^= inlined_code_intervals_.At(i + Code::kInlIntStart); |
| 553 ASSERT(!temp.IsNull()); | 556 ASSERT(!temp.IsNull()); |
| 554 OS::Print("% " Pd " start: %" Px " ", i, temp.Value()); | 557 ISL_Print("% " Pd " start: 0x%" Px " ", i, temp.Value()); |
| 555 temp ^= inlined_code_intervals_.At(i + Code::kInlIntInliningId); | 558 temp ^= inlined_code_intervals_.At(i + Code::kInlIntInliningId); |
| 556 OS::Print("inl-id: %" Pd " ", temp.Value()); | 559 ISL_Print("iid: %" Pd " ", temp.Value()); |
| 557 temp ^= inlined_code_intervals_.At(i + Code::kInlIntCallerId); | |
| 558 OS::Print("caller-id: %" Pd " \n", temp.Value()); | |
| 559 } | 560 } |
| 560 } | 561 } |
| 561 } | 562 } |
| 562 | 563 |
| 563 | 564 |
| 564 void FlowGraphCompiler::Bailout(const char* reason) { | 565 void FlowGraphCompiler::Bailout(const char* reason) { |
| 565 const Function& function = parsed_function_.function(); | 566 const Function& function = parsed_function_.function(); |
| 566 Report::MessageF(Report::kBailout, | 567 Report::MessageF(Report::kBailout, |
| 567 Script::Handle(function.script()), | 568 Script::Handle(function.script()), |
| 568 function.token_pos(), | 569 function.token_pos(), |
| (...skipping 1121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1690 } | 1691 } |
| 1691 const Array& res = Array::Handle( | 1692 const Array& res = Array::Handle( |
| 1692 Array::New(inline_id_to_function_.length(), Heap::kOld)); | 1693 Array::New(inline_id_to_function_.length(), Heap::kOld)); |
| 1693 for (intptr_t i = 0; i < inline_id_to_function_.length(); i++) { | 1694 for (intptr_t i = 0; i < inline_id_to_function_.length(); i++) { |
| 1694 res.SetAt(i, *inline_id_to_function_[i]); | 1695 res.SetAt(i, *inline_id_to_function_[i]); |
| 1695 } | 1696 } |
| 1696 return res.raw(); | 1697 return res.raw(); |
| 1697 } | 1698 } |
| 1698 | 1699 |
| 1699 | 1700 |
| 1701 RawArray* FlowGraphCompiler::CallerInliningIdMap() const { |
| 1702 if (caller_inline_id_.length() == 0) { |
| 1703 return Object::empty_array().raw(); |
| 1704 } |
| 1705 const Array& res = Array::Handle( |
| 1706 Array::New(caller_inline_id_.length(), Heap::kOld)); |
| 1707 Smi& smi = Smi::Handle(); |
| 1708 for (intptr_t i = 0; i < caller_inline_id_.length(); i++) { |
| 1709 smi = Smi::New(caller_inline_id_[i]); |
| 1710 res.SetAt(i, smi); |
| 1711 } |
| 1712 return res.raw(); |
| 1713 } |
| 1714 |
| 1715 |
| 1700 void FlowGraphCompiler::EmitPolymorphicInstanceCall( | 1716 void FlowGraphCompiler::EmitPolymorphicInstanceCall( |
| 1701 const ICData& ic_data, | 1717 const ICData& ic_data, |
| 1702 intptr_t argument_count, | 1718 intptr_t argument_count, |
| 1703 const Array& argument_names, | 1719 const Array& argument_names, |
| 1704 intptr_t deopt_id, | 1720 intptr_t deopt_id, |
| 1705 intptr_t token_pos, | 1721 intptr_t token_pos, |
| 1706 LocationSummary* locs) { | 1722 LocationSummary* locs) { |
| 1707 if (FLAG_polymorphic_with_deopt) { | 1723 if (FLAG_polymorphic_with_deopt) { |
| 1708 Label* deopt = AddDeoptStub(deopt_id, | 1724 Label* deopt = AddDeoptStub(deopt_id, |
| 1709 ICData::kDeoptPolymorphicInstanceCallTestFail); | 1725 ICData::kDeoptPolymorphicInstanceCallTestFail); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1799 | 1815 |
| 1800 | 1816 |
| 1801 void FlowGraphCompiler::FrameStateClear() { | 1817 void FlowGraphCompiler::FrameStateClear() { |
| 1802 ASSERT(!is_optimizing()); | 1818 ASSERT(!is_optimizing()); |
| 1803 frame_state_.TruncateTo(0); | 1819 frame_state_.TruncateTo(0); |
| 1804 } | 1820 } |
| 1805 #endif | 1821 #endif |
| 1806 | 1822 |
| 1807 | 1823 |
| 1808 } // namespace dart | 1824 } // namespace dart |
| OLD | NEW |