| 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 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 } | 172 } |
| 173 } | 173 } |
| 174 | 174 |
| 175 | 175 |
| 176 FlowGraphCompiler::FlowGraphCompiler( | 176 FlowGraphCompiler::FlowGraphCompiler( |
| 177 Assembler* assembler, | 177 Assembler* assembler, |
| 178 FlowGraph* flow_graph, | 178 FlowGraph* flow_graph, |
| 179 const ParsedFunction& parsed_function, | 179 const ParsedFunction& parsed_function, |
| 180 bool is_optimizing, | 180 bool is_optimizing, |
| 181 const GrowableArray<const Function*>& inline_id_to_function, | 181 const GrowableArray<const Function*>& inline_id_to_function, |
| 182 const GrowableArray<TokenPosition>& inline_id_to_token_pos, |
| 182 const GrowableArray<intptr_t>& caller_inline_id) | 183 const GrowableArray<intptr_t>& caller_inline_id) |
| 183 : thread_(Thread::Current()), | 184 : thread_(Thread::Current()), |
| 184 zone_(Thread::Current()->zone()), | 185 zone_(Thread::Current()->zone()), |
| 185 assembler_(assembler), | 186 assembler_(assembler), |
| 186 parsed_function_(parsed_function), | 187 parsed_function_(parsed_function), |
| 187 flow_graph_(*flow_graph), | 188 flow_graph_(*flow_graph), |
| 188 block_order_(*flow_graph->CodegenBlockOrder(is_optimizing)), | 189 block_order_(*flow_graph->CodegenBlockOrder(is_optimizing)), |
| 189 current_block_(NULL), | 190 current_block_(NULL), |
| 190 exception_handlers_list_(NULL), | 191 exception_handlers_list_(NULL), |
| 191 pc_descriptors_list_(NULL), | 192 pc_descriptors_list_(NULL), |
| (...skipping 17 matching lines...) Expand all Loading... |
| 209 list_class_(Class::ZoneHandle( | 210 list_class_(Class::ZoneHandle( |
| 210 Library::Handle(Library::CoreLibrary()). | 211 Library::Handle(Library::CoreLibrary()). |
| 211 LookupClass(Symbols::List()))), | 212 LookupClass(Symbols::List()))), |
| 212 parallel_move_resolver_(this), | 213 parallel_move_resolver_(this), |
| 213 pending_deoptimization_env_(NULL), | 214 pending_deoptimization_env_(NULL), |
| 214 lazy_deopt_pc_offset_(Code::kInvalidPc), | 215 lazy_deopt_pc_offset_(Code::kInvalidPc), |
| 215 deopt_id_to_ic_data_(NULL), | 216 deopt_id_to_ic_data_(NULL), |
| 216 edge_counters_array_(Array::ZoneHandle()), | 217 edge_counters_array_(Array::ZoneHandle()), |
| 217 inlined_code_intervals_(Array::ZoneHandle(Object::empty_array().raw())), | 218 inlined_code_intervals_(Array::ZoneHandle(Object::empty_array().raw())), |
| 218 inline_id_to_function_(inline_id_to_function), | 219 inline_id_to_function_(inline_id_to_function), |
| 220 inline_id_to_token_pos_(inline_id_to_token_pos), |
| 219 caller_inline_id_(caller_inline_id) { | 221 caller_inline_id_(caller_inline_id) { |
| 220 ASSERT(flow_graph->parsed_function().function().raw() == | 222 ASSERT(flow_graph->parsed_function().function().raw() == |
| 221 parsed_function.function().raw()); | 223 parsed_function.function().raw()); |
| 222 if (!is_optimizing) { | 224 if (!is_optimizing) { |
| 223 const intptr_t len = thread()->deopt_id(); | 225 const intptr_t len = thread()->deopt_id(); |
| 224 deopt_id_to_ic_data_ = new(zone()) ZoneGrowableArray<const ICData*>(len); | 226 deopt_id_to_ic_data_ = new(zone()) ZoneGrowableArray<const ICData*>(len); |
| 225 deopt_id_to_ic_data_->SetLength(len); | 227 deopt_id_to_ic_data_->SetLength(len); |
| 226 for (intptr_t i = 0; i < len; i++) { | 228 for (intptr_t i = 0; i < len; i++) { |
| 227 (*deopt_id_to_ic_data_)[i] = NULL; | 229 (*deopt_id_to_ic_data_)[i] = NULL; |
| 228 } | 230 } |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 470 assembler->Comment(" Loop %" Pd "", loop_id); | 472 assembler->Comment(" Loop %" Pd "", loop_id); |
| 471 } | 473 } |
| 472 } | 474 } |
| 473 } | 475 } |
| 474 } | 476 } |
| 475 } | 477 } |
| 476 | 478 |
| 477 | 479 |
| 478 // We collect intervals while generating code. | 480 // We collect intervals while generating code. |
| 479 struct IntervalStruct { | 481 struct IntervalStruct { |
| 480 // 'start' and 'end' are pc-offsets. | 482 // 'start' is the pc-offsets where the inlined code started. |
| 483 // 'pos' is the token position where the inlined call occured. |
| 481 intptr_t start; | 484 intptr_t start; |
| 485 TokenPosition pos; |
| 482 intptr_t inlining_id; | 486 intptr_t inlining_id; |
| 483 IntervalStruct(intptr_t s, intptr_t id) : start(s), inlining_id(id) {} | 487 IntervalStruct(intptr_t s, TokenPosition tp, intptr_t id) |
| 488 : start(s), pos(tp), inlining_id(id) {} |
| 484 void Dump() { | 489 void Dump() { |
| 485 THR_Print("start: 0x%" Px " iid: %" Pd " ", start, inlining_id); | 490 THR_Print("start: 0x%" Px " iid: %" Pd " pos: %s", |
| 491 start, inlining_id, pos.ToCString()); |
| 486 } | 492 } |
| 487 }; | 493 }; |
| 488 | 494 |
| 489 | 495 |
| 490 void FlowGraphCompiler::VisitBlocks() { | 496 void FlowGraphCompiler::VisitBlocks() { |
| 491 CompactBlocks(); | 497 CompactBlocks(); |
| 492 const ZoneGrowableArray<BlockEntryInstr*>* loop_headers = NULL; | 498 const ZoneGrowableArray<BlockEntryInstr*>* loop_headers = NULL; |
| 493 if (Assembler::EmittingComments()) { | 499 if (Assembler::EmittingComments()) { |
| 494 // 'loop_headers' were cleared, recompute. | 500 // 'loop_headers' were cleared, recompute. |
| 495 loop_headers = flow_graph().ComputeLoops(); | 501 loop_headers = flow_graph().ComputeLoops(); |
| 496 ASSERT(loop_headers != NULL); | 502 ASSERT(loop_headers != NULL); |
| 497 } | 503 } |
| 498 | 504 |
| 499 // For collecting intervals of inlined code. | 505 // For collecting intervals of inlined code. |
| 500 GrowableArray<IntervalStruct> intervals; | 506 GrowableArray<IntervalStruct> intervals; |
| 501 intptr_t prev_offset = 0; | 507 intptr_t prev_offset = 0; |
| 502 intptr_t prev_inlining_id = 0; | 508 intptr_t prev_inlining_id = 0; |
| 509 TokenPosition prev_inlining_pos = parsed_function_.function().token_pos(); |
| 503 intptr_t max_inlining_id = 0; | 510 intptr_t max_inlining_id = 0; |
| 504 for (intptr_t i = 0; i < block_order().length(); ++i) { | 511 for (intptr_t i = 0; i < block_order().length(); ++i) { |
| 505 // Compile the block entry. | 512 // Compile the block entry. |
| 506 BlockEntryInstr* entry = block_order()[i]; | 513 BlockEntryInstr* entry = block_order()[i]; |
| 507 assembler()->Comment("B%" Pd "", entry->block_id()); | 514 assembler()->Comment("B%" Pd "", entry->block_id()); |
| 508 set_current_block(entry); | 515 set_current_block(entry); |
| 509 | 516 |
| 510 if (WasCompacted(entry)) { | 517 if (WasCompacted(entry)) { |
| 511 continue; | 518 continue; |
| 512 } | 519 } |
| 513 | 520 |
| 514 #if defined(DEBUG) | 521 #if defined(DEBUG) |
| 515 if (!is_optimizing()) { | 522 if (!is_optimizing()) { |
| 516 FrameStateClear(); | 523 FrameStateClear(); |
| 517 } | 524 } |
| 518 #endif | 525 #endif |
| 519 | 526 |
| 520 LoopInfoComment(assembler(), *entry, *loop_headers); | 527 LoopInfoComment(assembler(), *entry, *loop_headers); |
| 521 | 528 |
| 522 entry->set_offset(assembler()->CodeSize()); | 529 entry->set_offset(assembler()->CodeSize()); |
| 523 entry->EmitNativeCode(this); | 530 entry->EmitNativeCode(this); |
| 524 // Compile all successors until an exit, branch, or a block entry. | 531 // Compile all successors until an exit, branch, or a block entry. |
| 525 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { | 532 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
| 526 Instruction* instr = it.Current(); | 533 Instruction* instr = it.Current(); |
| 527 // Compose intervals. | 534 // Compose intervals. |
| 528 if (instr->has_inlining_id() && is_optimizing()) { | 535 if (instr->has_inlining_id() && is_optimizing()) { |
| 529 if (prev_inlining_id != instr->inlining_id()) { | 536 if (prev_inlining_id != instr->inlining_id()) { |
| 530 intervals.Add(IntervalStruct(prev_offset, prev_inlining_id)); | 537 intervals.Add( |
| 538 IntervalStruct(prev_offset, prev_inlining_pos, prev_inlining_id)); |
| 531 prev_offset = assembler()->CodeSize(); | 539 prev_offset = assembler()->CodeSize(); |
| 532 prev_inlining_id = instr->inlining_id(); | 540 prev_inlining_id = instr->inlining_id(); |
| 541 prev_inlining_pos = inline_id_to_token_pos_[prev_inlining_id]; |
| 533 if (prev_inlining_id > max_inlining_id) { | 542 if (prev_inlining_id > max_inlining_id) { |
| 534 max_inlining_id = prev_inlining_id; | 543 max_inlining_id = prev_inlining_id; |
| 535 } | 544 } |
| 536 } | 545 } |
| 537 } | 546 } |
| 538 if (FLAG_code_comments || | 547 if (FLAG_code_comments || |
| 539 FLAG_disassemble || FLAG_disassemble_optimized) { | 548 FLAG_disassemble || FLAG_disassemble_optimized) { |
| 540 if (FLAG_source_lines) { | 549 if (FLAG_source_lines) { |
| 541 EmitSourceLine(instr); | 550 EmitSourceLine(instr); |
| 542 } | 551 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 560 #endif | 569 #endif |
| 561 } | 570 } |
| 562 | 571 |
| 563 #if defined(DEBUG) | 572 #if defined(DEBUG) |
| 564 ASSERT(is_optimizing() || FrameStateIsSafeToCall()); | 573 ASSERT(is_optimizing() || FrameStateIsSafeToCall()); |
| 565 #endif | 574 #endif |
| 566 } | 575 } |
| 567 | 576 |
| 568 if (is_optimizing()) { | 577 if (is_optimizing()) { |
| 569 LogBlock lb; | 578 LogBlock lb; |
| 570 intervals.Add(IntervalStruct(prev_offset, prev_inlining_id)); | 579 intervals.Add( |
| 580 IntervalStruct(prev_offset, prev_inlining_pos, prev_inlining_id)); |
| 571 inlined_code_intervals_ = | 581 inlined_code_intervals_ = |
| 572 Array::New(intervals.length() * Code::kInlIntNumEntries, Heap::kOld); | 582 Array::New(intervals.length() * Code::kInlIntNumEntries, Heap::kOld); |
| 573 Smi& start_h = Smi::Handle(); | 583 Smi& start_h = Smi::Handle(); |
| 574 Smi& caller_inline_id = Smi::Handle(); | 584 Smi& caller_inline_id = Smi::Handle(); |
| 575 Smi& inline_id = Smi::Handle(); | 585 Smi& inline_id = Smi::Handle(); |
| 576 for (intptr_t i = 0; i < intervals.length(); i++) { | 586 for (intptr_t i = 0; i < intervals.length(); i++) { |
| 577 if (FLAG_trace_inlining_intervals && is_optimizing()) { | 587 if (FLAG_trace_inlining_intervals && is_optimizing()) { |
| 578 const Function& function = | 588 const Function& function = |
| 579 *inline_id_to_function_.At(intervals[i].inlining_id); | 589 *inline_id_to_function_.At(intervals[i].inlining_id); |
| 580 intervals[i].Dump(); | 590 intervals[i].Dump(); |
| (...skipping 1164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1745 } | 1755 } |
| 1746 const Array& res = Array::Handle( | 1756 const Array& res = Array::Handle( |
| 1747 Array::New(inline_id_to_function_.length(), Heap::kOld)); | 1757 Array::New(inline_id_to_function_.length(), Heap::kOld)); |
| 1748 for (intptr_t i = 0; i < inline_id_to_function_.length(); i++) { | 1758 for (intptr_t i = 0; i < inline_id_to_function_.length(); i++) { |
| 1749 res.SetAt(i, *inline_id_to_function_[i]); | 1759 res.SetAt(i, *inline_id_to_function_[i]); |
| 1750 } | 1760 } |
| 1751 return res.raw(); | 1761 return res.raw(); |
| 1752 } | 1762 } |
| 1753 | 1763 |
| 1754 | 1764 |
| 1765 RawArray* FlowGraphCompiler::InliningIdToTokenPos() const { |
| 1766 if (inline_id_to_token_pos_.length() == 0) { |
| 1767 return Object::empty_array().raw(); |
| 1768 } |
| 1769 const Array& res = Array::Handle(zone(), |
| 1770 Array::New(inline_id_to_token_pos_.length(), Heap::kOld)); |
| 1771 Smi& smi = Smi::Handle(zone()); |
| 1772 for (intptr_t i = 0; i < inline_id_to_token_pos_.length(); i++) { |
| 1773 smi = Smi::New(inline_id_to_token_pos_[i].value()); |
| 1774 res.SetAt(i, smi); |
| 1775 } |
| 1776 return res.raw(); |
| 1777 } |
| 1778 |
| 1779 |
| 1755 RawArray* FlowGraphCompiler::CallerInliningIdMap() const { | 1780 RawArray* FlowGraphCompiler::CallerInliningIdMap() const { |
| 1756 if (caller_inline_id_.length() == 0) { | 1781 if (caller_inline_id_.length() == 0) { |
| 1757 return Object::empty_array().raw(); | 1782 return Object::empty_array().raw(); |
| 1758 } | 1783 } |
| 1759 const Array& res = Array::Handle( | 1784 const Array& res = Array::Handle( |
| 1760 Array::New(caller_inline_id_.length(), Heap::kOld)); | 1785 Array::New(caller_inline_id_.length(), Heap::kOld)); |
| 1761 Smi& smi = Smi::Handle(); | 1786 Smi& smi = Smi::Handle(); |
| 1762 for (intptr_t i = 0; i < caller_inline_id_.length(); i++) { | 1787 for (intptr_t i = 0; i < caller_inline_id_.length(); i++) { |
| 1763 smi = Smi::New(caller_inline_id_[i]); | 1788 smi = Smi::New(caller_inline_id_[i]); |
| 1764 res.SetAt(i, smi); | 1789 res.SetAt(i, smi); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1870 | 1895 |
| 1871 | 1896 |
| 1872 void FlowGraphCompiler::FrameStateClear() { | 1897 void FlowGraphCompiler::FrameStateClear() { |
| 1873 ASSERT(!is_optimizing()); | 1898 ASSERT(!is_optimizing()); |
| 1874 frame_state_.TruncateTo(0); | 1899 frame_state_.TruncateTo(0); |
| 1875 } | 1900 } |
| 1876 #endif | 1901 #endif |
| 1877 | 1902 |
| 1878 | 1903 |
| 1879 } // namespace dart | 1904 } // namespace dart |
| OLD | NEW |