| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/flow_graph_builder.h" | 5 #include "vm/flow_graph_builder.h" |
| 6 | 6 |
| 7 #include "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
| 8 #include "vm/ast_printer.h" | 8 #include "vm/ast_printer.h" |
| 9 #include "vm/bit_vector.h" | 9 #include "vm/bit_vector.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 | 166 |
| 167 | 167 |
| 168 intptr_t FlowGraphBuilder::context_level() const { | 168 intptr_t FlowGraphBuilder::context_level() const { |
| 169 return (nesting_stack() == NULL) ? 0 : nesting_stack()->ContextLevel(); | 169 return (nesting_stack() == NULL) ? 0 : nesting_stack()->ContextLevel(); |
| 170 } | 170 } |
| 171 | 171 |
| 172 | 172 |
| 173 JoinEntryInstr* NestedStatement::BreakTargetFor(SourceLabel* label) { | 173 JoinEntryInstr* NestedStatement::BreakTargetFor(SourceLabel* label) { |
| 174 if (label != label_) return NULL; | 174 if (label != label_) return NULL; |
| 175 if (break_target_ == NULL) { | 175 if (break_target_ == NULL) { |
| 176 break_target_ = new (owner()->zone()) | 176 break_target_ = new (owner()->zone()) JoinEntryInstr( |
| 177 JoinEntryInstr(owner()->AllocateBlockId(), try_index()); | 177 owner()->AllocateBlockId(), try_index(), owner()->GetNextDeoptId()); |
| 178 } | 178 } |
| 179 return break_target_; | 179 return break_target_; |
| 180 } | 180 } |
| 181 | 181 |
| 182 | 182 |
| 183 JoinEntryInstr* NestedStatement::ContinueTargetFor(SourceLabel* label) { | 183 JoinEntryInstr* NestedStatement::ContinueTargetFor(SourceLabel* label) { |
| 184 return NULL; | 184 return NULL; |
| 185 } | 185 } |
| 186 | 186 |
| 187 | 187 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 virtual JoinEntryInstr* ContinueTargetFor(SourceLabel* label); | 239 virtual JoinEntryInstr* ContinueTargetFor(SourceLabel* label); |
| 240 | 240 |
| 241 private: | 241 private: |
| 242 JoinEntryInstr* continue_target_; | 242 JoinEntryInstr* continue_target_; |
| 243 }; | 243 }; |
| 244 | 244 |
| 245 | 245 |
| 246 JoinEntryInstr* NestedLoop::ContinueTargetFor(SourceLabel* label) { | 246 JoinEntryInstr* NestedLoop::ContinueTargetFor(SourceLabel* label) { |
| 247 if (label != this->label()) return NULL; | 247 if (label != this->label()) return NULL; |
| 248 if (continue_target_ == NULL) { | 248 if (continue_target_ == NULL) { |
| 249 continue_target_ = new (owner()->zone()) | 249 continue_target_ = new (owner()->zone()) JoinEntryInstr( |
| 250 JoinEntryInstr(owner()->AllocateBlockId(), try_index()); | 250 owner()->AllocateBlockId(), try_index(), owner()->GetNextDeoptId()); |
| 251 } | 251 } |
| 252 return continue_target_; | 252 return continue_target_; |
| 253 } | 253 } |
| 254 | 254 |
| 255 | 255 |
| 256 // A nested switch which can be the target of a break if labeled, and whose | 256 // A nested switch which can be the target of a break if labeled, and whose |
| 257 // cases can be the targets of continues. | 257 // cases can be the targets of continues. |
| 258 class NestedSwitch : public NestedStatement { | 258 class NestedSwitch : public NestedStatement { |
| 259 public: | 259 public: |
| 260 NestedSwitch(FlowGraphBuilder* owner, SwitchNode* node); | 260 NestedSwitch(FlowGraphBuilder* owner, SwitchNode* node); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 282 } | 282 } |
| 283 | 283 |
| 284 | 284 |
| 285 JoinEntryInstr* NestedSwitch::ContinueTargetFor(SourceLabel* label) { | 285 JoinEntryInstr* NestedSwitch::ContinueTargetFor(SourceLabel* label) { |
| 286 // Allocate a join for a case clause that matches the label. This block | 286 // Allocate a join for a case clause that matches the label. This block |
| 287 // is not necessarily targeted by a continue, but we always use a join in | 287 // is not necessarily targeted by a continue, but we always use a join in |
| 288 // the graph anyway. | 288 // the graph anyway. |
| 289 for (intptr_t i = 0; i < case_labels_.length(); ++i) { | 289 for (intptr_t i = 0; i < case_labels_.length(); ++i) { |
| 290 if (label != case_labels_[i]) continue; | 290 if (label != case_labels_[i]) continue; |
| 291 if (case_targets_[i] == NULL) { | 291 if (case_targets_[i] == NULL) { |
| 292 case_targets_[i] = new (owner()->zone()) | 292 case_targets_[i] = new (owner()->zone()) JoinEntryInstr( |
| 293 JoinEntryInstr(owner()->AllocateBlockId(), try_index()); | 293 owner()->AllocateBlockId(), try_index(), owner()->GetNextDeoptId()); |
| 294 } | 294 } |
| 295 return case_targets_[i]; | 295 return case_targets_[i]; |
| 296 } | 296 } |
| 297 return NULL; | 297 return NULL; |
| 298 } | 298 } |
| 299 | 299 |
| 300 | 300 |
| 301 FlowGraphBuilder::FlowGraphBuilder( | 301 FlowGraphBuilder::FlowGraphBuilder( |
| 302 const ParsedFunction& parsed_function, | 302 const ParsedFunction& parsed_function, |
| 303 const ZoneGrowableArray<const ICData*>& ic_data_array, | 303 const ZoneGrowableArray<const ICData*>& ic_data_array, |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 if (num_exits == 1) { | 435 if (num_exits == 1) { |
| 436 ReturnAt(0)->UnuseAllInputs(); | 436 ReturnAt(0)->UnuseAllInputs(); |
| 437 *exit_block = ExitBlockAt(0); | 437 *exit_block = ExitBlockAt(0); |
| 438 *last_instruction = LastInstructionAt(0); | 438 *last_instruction = LastInstructionAt(0); |
| 439 return call_->HasUses() ? ValueAt(0)->definition() : NULL; | 439 return call_->HasUses() ? ValueAt(0)->definition() : NULL; |
| 440 } else { | 440 } else { |
| 441 ASSERT(num_exits > 1); | 441 ASSERT(num_exits > 1); |
| 442 // Create a join of the returns. | 442 // Create a join of the returns. |
| 443 intptr_t join_id = caller_graph_->max_block_id() + 1; | 443 intptr_t join_id = caller_graph_->max_block_id() + 1; |
| 444 caller_graph_->set_max_block_id(join_id); | 444 caller_graph_->set_max_block_id(join_id); |
| 445 JoinEntryInstr* join = new (Z) JoinEntryInstr(join_id, try_index); | 445 JoinEntryInstr* join = new (Z) |
| 446 JoinEntryInstr(join_id, try_index, Thread::Current()->GetNextDeoptId()); |
| 446 | 447 |
| 447 // The dominator set of the join is the intersection of the dominator | 448 // The dominator set of the join is the intersection of the dominator |
| 448 // sets of all the predecessors. If we keep the dominator sets ordered | 449 // sets of all the predecessors. If we keep the dominator sets ordered |
| 449 // by height in the dominator tree, we can also get the immediate | 450 // by height in the dominator tree, we can also get the immediate |
| 450 // dominator of the join node from the intersection. | 451 // dominator of the join node from the intersection. |
| 451 // | 452 // |
| 452 // block_dominators is the dominator set for each block, ordered from | 453 // block_dominators is the dominator set for each block, ordered from |
| 453 // the immediate dominator to the root of the dominator tree. This is | 454 // the immediate dominator to the root of the dominator tree. This is |
| 454 // the order we collect them in (adding at the end). | 455 // the order we collect them in (adding at the end). |
| 455 // | 456 // |
| 456 // join_dominators is the join's dominators ordered from the root of the | 457 // join_dominators is the join's dominators ordered from the root of the |
| 457 // dominator tree to the immediate dominator. This order supports | 458 // dominator tree to the immediate dominator. This order supports |
| 458 // removing during intersection by truncating the list. | 459 // removing during intersection by truncating the list. |
| 459 GrowableArray<BlockEntryInstr*> block_dominators; | 460 GrowableArray<BlockEntryInstr*> block_dominators; |
| 460 GrowableArray<BlockEntryInstr*> join_dominators; | 461 GrowableArray<BlockEntryInstr*> join_dominators; |
| 461 for (intptr_t i = 0; i < num_exits; ++i) { | 462 for (intptr_t i = 0; i < num_exits; ++i) { |
| 462 // Add the control-flow edge. | 463 // Add the control-flow edge. |
| 463 GotoInstr* goto_instr = new (Z) GotoInstr(join); | 464 GotoInstr* goto_instr = |
| 465 new (Z) GotoInstr(join, Thread::Current()->GetNextDeoptId()); |
| 464 goto_instr->InheritDeoptTarget(zone(), ReturnAt(i)); | 466 goto_instr->InheritDeoptTarget(zone(), ReturnAt(i)); |
| 465 LastInstructionAt(i)->LinkTo(goto_instr); | 467 LastInstructionAt(i)->LinkTo(goto_instr); |
| 466 ExitBlockAt(i)->set_last_instruction(LastInstructionAt(i)->next()); | 468 ExitBlockAt(i)->set_last_instruction(LastInstructionAt(i)->next()); |
| 467 join->predecessors_.Add(ExitBlockAt(i)); | 469 join->predecessors_.Add(ExitBlockAt(i)); |
| 468 | 470 |
| 469 // Collect the block's dominators. | 471 // Collect the block's dominators. |
| 470 block_dominators.Clear(); | 472 block_dominators.Clear(); |
| 471 BlockEntryInstr* dominator = ExitBlockAt(i)->dominator(); | 473 BlockEntryInstr* dominator = ExitBlockAt(i)->dominator(); |
| 472 while (dominator != NULL) { | 474 while (dominator != NULL) { |
| 473 block_dominators.Add(dominator); | 475 block_dominators.Add(dominator); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 539 Instruction* callee_last_instruction = NULL; | 541 Instruction* callee_last_instruction = NULL; |
| 540 | 542 |
| 541 if (exits_.length() == 0) { | 543 if (exits_.length() == 0) { |
| 542 // Handle the case when there are no normal return exits from the callee | 544 // Handle the case when there are no normal return exits from the callee |
| 543 // (i.e. the callee unconditionally throws) by inserting an artificial | 545 // (i.e. the callee unconditionally throws) by inserting an artificial |
| 544 // branch (true === true). | 546 // branch (true === true). |
| 545 // The true successor is the inlined body, the false successor | 547 // The true successor is the inlined body, the false successor |
| 546 // goes to the rest of the caller graph. It is removed as unreachable code | 548 // goes to the rest of the caller graph. It is removed as unreachable code |
| 547 // by the constant propagation. | 549 // by the constant propagation. |
| 548 TargetEntryInstr* false_block = new (Z) TargetEntryInstr( | 550 TargetEntryInstr* false_block = new (Z) TargetEntryInstr( |
| 549 caller_graph_->allocate_block_id(), call_block->try_index()); | 551 caller_graph_->allocate_block_id(), call_block->try_index(), |
| 552 Thread::Current()->GetNextDeoptId()); |
| 550 false_block->InheritDeoptTargetAfter(caller_graph_, call_, NULL); | 553 false_block->InheritDeoptTargetAfter(caller_graph_, call_, NULL); |
| 551 false_block->LinkTo(call_->next()); | 554 false_block->LinkTo(call_->next()); |
| 552 call_block->ReplaceAsPredecessorWith(false_block); | 555 call_block->ReplaceAsPredecessorWith(false_block); |
| 553 | 556 |
| 554 ConstantInstr* true_const = caller_graph_->GetConstant(Bool::True()); | 557 ConstantInstr* true_const = caller_graph_->GetConstant(Bool::True()); |
| 555 BranchInstr* branch = new (Z) BranchInstr(new (Z) StrictCompareInstr( | 558 BranchInstr* branch = new (Z) |
| 556 TokenPosition::kNoSource, Token::kEQ_STRICT, new (Z) Value(true_const), | 559 BranchInstr(new (Z) StrictCompareInstr( |
| 557 new (Z) Value(true_const), | 560 TokenPosition::kNoSource, Token::kEQ_STRICT, |
| 558 false)); // No number check. | 561 new (Z) Value(true_const), new (Z) Value(true_const), |
| 562 false, Thread::Current()->GetNextDeoptId()), |
| 563 Thread::Current()->GetNextDeoptId()); // No number check. |
| 559 branch->InheritDeoptTarget(zone(), call_); | 564 branch->InheritDeoptTarget(zone(), call_); |
| 560 *branch->true_successor_address() = callee_entry; | 565 *branch->true_successor_address() = callee_entry; |
| 561 *branch->false_successor_address() = false_block; | 566 *branch->false_successor_address() = false_block; |
| 562 | 567 |
| 563 call_->previous()->AppendInstruction(branch); | 568 call_->previous()->AppendInstruction(branch); |
| 564 call_block->set_last_instruction(branch); | 569 call_block->set_last_instruction(branch); |
| 565 | 570 |
| 566 // Replace uses of the return value with null to maintain valid | 571 // Replace uses of the return value with null to maintain valid |
| 567 // SSA form - even though the rest of the caller is unreachable. | 572 // SSA form - even though the rest of the caller is unreachable. |
| 568 call_->ReplaceUsesWith(caller_graph_->constant_null()); | 573 call_->ReplaceUsesWith(caller_graph_->constant_null()); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 692 entry_ = exit_ = instruction; | 697 entry_ = exit_ = instruction; |
| 693 } else { | 698 } else { |
| 694 exit()->LinkTo(instruction); | 699 exit()->LinkTo(instruction); |
| 695 exit_ = instruction; | 700 exit_ = instruction; |
| 696 } | 701 } |
| 697 } | 702 } |
| 698 | 703 |
| 699 | 704 |
| 700 void EffectGraphVisitor::AddReturnExit(TokenPosition token_pos, Value* value) { | 705 void EffectGraphVisitor::AddReturnExit(TokenPosition token_pos, Value* value) { |
| 701 ASSERT(is_open()); | 706 ASSERT(is_open()); |
| 702 ReturnInstr* return_instr = new (Z) ReturnInstr(token_pos, value); | 707 ReturnInstr* return_instr = |
| 708 new (Z) ReturnInstr(token_pos, value, owner()->GetNextDeoptId()); |
| 703 AddInstruction(return_instr); | 709 AddInstruction(return_instr); |
| 704 InlineExitCollector* exit_collector = owner()->exit_collector(); | 710 InlineExitCollector* exit_collector = owner()->exit_collector(); |
| 705 if (exit_collector != NULL) { | 711 if (exit_collector != NULL) { |
| 706 exit_collector->AddExit(return_instr); | 712 exit_collector->AddExit(return_instr); |
| 707 } | 713 } |
| 708 CloseFragment(); | 714 CloseFragment(); |
| 709 } | 715 } |
| 710 | 716 |
| 711 | 717 |
| 712 void EffectGraphVisitor::Goto(JoinEntryInstr* join) { | 718 void EffectGraphVisitor::Goto(JoinEntryInstr* join) { |
| 713 ASSERT(is_open()); | 719 ASSERT(is_open()); |
| 714 if (is_empty()) { | 720 if (is_empty()) { |
| 715 entry_ = new (Z) GotoInstr(join); | 721 entry_ = new (Z) GotoInstr(join, owner()->GetNextDeoptId()); |
| 716 } else { | 722 } else { |
| 717 exit()->Goto(join); | 723 exit()->Goto(join); |
| 718 } | 724 } |
| 719 CloseFragment(); | 725 CloseFragment(); |
| 720 } | 726 } |
| 721 | 727 |
| 722 | 728 |
| 723 // Appends a graph fragment to a block entry instruction. Returns the entry | 729 // Appends a graph fragment to a block entry instruction. Returns the entry |
| 724 // instruction if the fragment was empty or else the exit of the fragment if | 730 // instruction if the fragment was empty or else the exit of the fragment if |
| 725 // it was non-empty (so NULL if the fragment is closed). | 731 // it was non-empty (so NULL if the fragment is closed). |
| (...skipping 28 matching lines...) Expand all Loading... |
| 754 | 760 |
| 755 BlockEntryInstr* false_entry = test_fragment.CreateFalseSuccessor(); | 761 BlockEntryInstr* false_entry = test_fragment.CreateFalseSuccessor(); |
| 756 Instruction* false_exit = AppendFragment(false_entry, false_fragment); | 762 Instruction* false_exit = AppendFragment(false_entry, false_fragment); |
| 757 | 763 |
| 758 // 3. Add a join or select one (or neither) of the arms as exit. | 764 // 3. Add a join or select one (or neither) of the arms as exit. |
| 759 if (true_exit == NULL) { | 765 if (true_exit == NULL) { |
| 760 exit_ = false_exit; // May be NULL. | 766 exit_ = false_exit; // May be NULL. |
| 761 } else if (false_exit == NULL) { | 767 } else if (false_exit == NULL) { |
| 762 exit_ = true_exit; | 768 exit_ = true_exit; |
| 763 } else { | 769 } else { |
| 764 JoinEntryInstr* join = new (Z) | 770 JoinEntryInstr* join = |
| 765 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 771 new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(), |
| 772 owner()->GetNextDeoptId()); |
| 766 true_exit->Goto(join); | 773 true_exit->Goto(join); |
| 767 false_exit->Goto(join); | 774 false_exit->Goto(join); |
| 768 exit_ = join; | 775 exit_ = join; |
| 769 } | 776 } |
| 770 } | 777 } |
| 771 | 778 |
| 772 | 779 |
| 773 void EffectGraphVisitor::TieLoop( | 780 void EffectGraphVisitor::TieLoop( |
| 774 TokenPosition token_pos, | 781 TokenPosition token_pos, |
| 775 const TestGraphVisitor& test_fragment, | 782 const TestGraphVisitor& test_fragment, |
| 776 const EffectGraphVisitor& body_fragment, | 783 const EffectGraphVisitor& body_fragment, |
| 777 const EffectGraphVisitor& test_preamble_fragment) { | 784 const EffectGraphVisitor& test_preamble_fragment) { |
| 778 // We have: a test graph fragment with zero, one, or two available exits; | 785 // We have: a test graph fragment with zero, one, or two available exits; |
| 779 // and an effect graph fragment with zero or one available exits. We want | 786 // and an effect graph fragment with zero or one available exits. We want |
| 780 // to append the 'while loop' consisting of the test graph fragment as | 787 // to append the 'while loop' consisting of the test graph fragment as |
| 781 // condition and the effect graph fragment as body. | 788 // condition and the effect graph fragment as body. |
| 782 ASSERT(is_open()); | 789 ASSERT(is_open()); |
| 783 | 790 |
| 784 // 1. Connect the body to the test if it is reachable, and if so record | 791 // 1. Connect the body to the test if it is reachable, and if so record |
| 785 // its exit (if any). | 792 // its exit (if any). |
| 786 BlockEntryInstr* body_entry = test_fragment.CreateTrueSuccessor(); | 793 BlockEntryInstr* body_entry = test_fragment.CreateTrueSuccessor(); |
| 787 Instruction* body_exit = AppendFragment(body_entry, body_fragment); | 794 Instruction* body_exit = AppendFragment(body_entry, body_fragment); |
| 788 | 795 |
| 789 // 2. Connect the test to this graph, including the body if reachable and | 796 // 2. Connect the test to this graph, including the body if reachable and |
| 790 // using a fresh join node if the body is reachable and has an open exit. | 797 // using a fresh join node if the body is reachable and has an open exit. |
| 791 if (body_exit == NULL) { | 798 if (body_exit == NULL) { |
| 792 Append(test_preamble_fragment); | 799 Append(test_preamble_fragment); |
| 793 Append(test_fragment); | 800 Append(test_fragment); |
| 794 } else { | 801 } else { |
| 795 JoinEntryInstr* join = new (Z) | 802 JoinEntryInstr* join = |
| 796 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 803 new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(), |
| 797 CheckStackOverflowInstr* check = | 804 owner()->GetNextDeoptId()); |
| 798 new (Z) CheckStackOverflowInstr(token_pos, owner()->loop_depth()); | 805 CheckStackOverflowInstr* check = new (Z) CheckStackOverflowInstr( |
| 806 token_pos, owner()->loop_depth(), owner()->GetNextDeoptId()); |
| 799 join->LinkTo(check); | 807 join->LinkTo(check); |
| 800 if (!test_preamble_fragment.is_empty()) { | 808 if (!test_preamble_fragment.is_empty()) { |
| 801 check->LinkTo(test_preamble_fragment.entry()); | 809 check->LinkTo(test_preamble_fragment.entry()); |
| 802 test_preamble_fragment.exit()->LinkTo(test_fragment.entry()); | 810 test_preamble_fragment.exit()->LinkTo(test_fragment.entry()); |
| 803 } else { | 811 } else { |
| 804 check->LinkTo(test_fragment.entry()); | 812 check->LinkTo(test_fragment.entry()); |
| 805 } | 813 } |
| 806 Goto(join); | 814 Goto(join); |
| 807 body_exit->Goto(join); | 815 body_exit->Goto(join); |
| 808 } | 816 } |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 922 *owner()->parsed_function().current_context_var(), token_pos); | 930 *owner()->parsed_function().current_context_var(), token_pos); |
| 923 } | 931 } |
| 924 | 932 |
| 925 | 933 |
| 926 void TestGraphVisitor::ConnectBranchesTo( | 934 void TestGraphVisitor::ConnectBranchesTo( |
| 927 const GrowableArray<TargetEntryInstr**>& branches, | 935 const GrowableArray<TargetEntryInstr**>& branches, |
| 928 JoinEntryInstr* join) const { | 936 JoinEntryInstr* join) const { |
| 929 ASSERT(!branches.is_empty()); | 937 ASSERT(!branches.is_empty()); |
| 930 for (intptr_t i = 0; i < branches.length(); i++) { | 938 for (intptr_t i = 0; i < branches.length(); i++) { |
| 931 TargetEntryInstr* target = new (Z) | 939 TargetEntryInstr* target = new (Z) |
| 932 TargetEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 940 TargetEntryInstr(owner()->AllocateBlockId(), owner()->try_index(), |
| 941 owner()->GetNextDeoptId()); |
| 933 *(branches[i]) = target; | 942 *(branches[i]) = target; |
| 934 target->Goto(join); | 943 target->Goto(join); |
| 935 } | 944 } |
| 936 } | 945 } |
| 937 | 946 |
| 938 | 947 |
| 939 void TestGraphVisitor::IfTrueGoto(JoinEntryInstr* join) const { | 948 void TestGraphVisitor::IfTrueGoto(JoinEntryInstr* join) const { |
| 940 ConnectBranchesTo(true_successor_addresses_, join); | 949 ConnectBranchesTo(true_successor_addresses_, join); |
| 941 } | 950 } |
| 942 | 951 |
| 943 | 952 |
| 944 void TestGraphVisitor::IfFalseGoto(JoinEntryInstr* join) const { | 953 void TestGraphVisitor::IfFalseGoto(JoinEntryInstr* join) const { |
| 945 ConnectBranchesTo(false_successor_addresses_, join); | 954 ConnectBranchesTo(false_successor_addresses_, join); |
| 946 } | 955 } |
| 947 | 956 |
| 948 | 957 |
| 949 BlockEntryInstr* TestGraphVisitor::CreateSuccessorFor( | 958 BlockEntryInstr* TestGraphVisitor::CreateSuccessorFor( |
| 950 const GrowableArray<TargetEntryInstr**>& branches) const { | 959 const GrowableArray<TargetEntryInstr**>& branches) const { |
| 951 ASSERT(!branches.is_empty()); | 960 ASSERT(!branches.is_empty()); |
| 952 | 961 |
| 953 if (branches.length() == 1) { | 962 if (branches.length() == 1) { |
| 954 TargetEntryInstr* target = new (Z) | 963 TargetEntryInstr* target = new (Z) |
| 955 TargetEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 964 TargetEntryInstr(owner()->AllocateBlockId(), owner()->try_index(), |
| 965 owner()->GetNextDeoptId()); |
| 956 *(branches[0]) = target; | 966 *(branches[0]) = target; |
| 957 return target; | 967 return target; |
| 958 } | 968 } |
| 959 | 969 |
| 960 JoinEntryInstr* join = | 970 JoinEntryInstr* join = |
| 961 new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 971 new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(), |
| 972 owner()->GetNextDeoptId()); |
| 962 ConnectBranchesTo(branches, join); | 973 ConnectBranchesTo(branches, join); |
| 963 return join; | 974 return join; |
| 964 } | 975 } |
| 965 | 976 |
| 966 | 977 |
| 967 BlockEntryInstr* TestGraphVisitor::CreateTrueSuccessor() const { | 978 BlockEntryInstr* TestGraphVisitor::CreateTrueSuccessor() const { |
| 968 return CreateSuccessorFor(true_successor_addresses_); | 979 return CreateSuccessorFor(true_successor_addresses_); |
| 969 } | 980 } |
| 970 | 981 |
| 971 | 982 |
| 972 BlockEntryInstr* TestGraphVisitor::CreateFalseSuccessor() const { | 983 BlockEntryInstr* TestGraphVisitor::CreateFalseSuccessor() const { |
| 973 return CreateSuccessorFor(false_successor_addresses_); | 984 return CreateSuccessorFor(false_successor_addresses_); |
| 974 } | 985 } |
| 975 | 986 |
| 976 | 987 |
| 977 void TestGraphVisitor::ReturnValue(Value* value) { | 988 void TestGraphVisitor::ReturnValue(Value* value) { |
| 978 Isolate* isolate = Isolate::Current(); | 989 Isolate* isolate = Isolate::Current(); |
| 979 if (isolate->type_checks() || isolate->asserts()) { | 990 if (isolate->type_checks() || isolate->asserts()) { |
| 980 value = Bind(new (Z) AssertBooleanInstr(condition_token_pos(), value)); | 991 value = Bind(new (Z) AssertBooleanInstr(condition_token_pos(), value, |
| 992 owner()->GetNextDeoptId())); |
| 981 } | 993 } |
| 982 Value* constant_true = Bind(new (Z) ConstantInstr(Bool::True())); | 994 Value* constant_true = Bind(new (Z) ConstantInstr(Bool::True())); |
| 983 StrictCompareInstr* comp = new (Z) StrictCompareInstr( | 995 StrictCompareInstr* comp = new (Z) StrictCompareInstr( |
| 984 condition_token_pos(), Token::kEQ_STRICT, value, constant_true, | 996 condition_token_pos(), Token::kEQ_STRICT, value, constant_true, false, |
| 985 false); // No number check. | 997 owner()->GetNextDeoptId()); // No number check. |
| 986 BranchInstr* branch = new (Z) BranchInstr(comp); | 998 BranchInstr* branch = new (Z) BranchInstr(comp, owner()->GetNextDeoptId()); |
| 987 AddInstruction(branch); | 999 AddInstruction(branch); |
| 988 CloseFragment(); | 1000 CloseFragment(); |
| 989 | 1001 |
| 990 true_successor_addresses_.Add(branch->true_successor_address()); | 1002 true_successor_addresses_.Add(branch->true_successor_address()); |
| 991 false_successor_addresses_.Add(branch->false_successor_address()); | 1003 false_successor_addresses_.Add(branch->false_successor_address()); |
| 992 } | 1004 } |
| 993 | 1005 |
| 994 | 1006 |
| 995 void TestGraphVisitor::MergeBranchWithStrictCompare(StrictCompareInstr* comp) { | 1007 void TestGraphVisitor::MergeBranchWithStrictCompare(StrictCompareInstr* comp) { |
| 996 BranchInstr* branch = new (Z) BranchInstr(comp); | 1008 BranchInstr* branch = new (Z) BranchInstr(comp, owner()->GetNextDeoptId()); |
| 997 AddInstruction(branch); | 1009 AddInstruction(branch); |
| 998 CloseFragment(); | 1010 CloseFragment(); |
| 999 true_successor_addresses_.Add(branch->true_successor_address()); | 1011 true_successor_addresses_.Add(branch->true_successor_address()); |
| 1000 false_successor_addresses_.Add(branch->false_successor_address()); | 1012 false_successor_addresses_.Add(branch->false_successor_address()); |
| 1001 } | 1013 } |
| 1002 | 1014 |
| 1003 | 1015 |
| 1004 void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateInstr* neg) { | 1016 void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateInstr* neg) { |
| 1005 ASSERT(!Isolate::Current()->type_checks()); | 1017 ASSERT(!Isolate::Current()->type_checks()); |
| 1006 Value* constant_true = Bind(new (Z) ConstantInstr(Bool::True())); | 1018 Value* constant_true = Bind(new (Z) ConstantInstr(Bool::True())); |
| 1007 StrictCompareInstr* comp = new (Z) StrictCompareInstr( | 1019 StrictCompareInstr* comp = new (Z) StrictCompareInstr( |
| 1008 condition_token_pos(), Token::kNE_STRICT, neg->value(), constant_true, | 1020 condition_token_pos(), Token::kNE_STRICT, neg->value(), constant_true, |
| 1009 false); // No number check. | 1021 false, owner()->GetNextDeoptId()); // No number check. |
| 1010 BranchInstr* branch = new (Z) BranchInstr(comp); | 1022 BranchInstr* branch = new (Z) BranchInstr(comp, owner()->GetNextDeoptId()); |
| 1011 AddInstruction(branch); | 1023 AddInstruction(branch); |
| 1012 CloseFragment(); | 1024 CloseFragment(); |
| 1013 true_successor_addresses_.Add(branch->true_successor_address()); | 1025 true_successor_addresses_.Add(branch->true_successor_address()); |
| 1014 false_successor_addresses_.Add(branch->false_successor_address()); | 1026 false_successor_addresses_.Add(branch->false_successor_address()); |
| 1015 } | 1027 } |
| 1016 | 1028 |
| 1017 | 1029 |
| 1018 void TestGraphVisitor::ReturnDefinition(Definition* definition) { | 1030 void TestGraphVisitor::ReturnDefinition(Definition* definition) { |
| 1019 StrictCompareInstr* comp = definition->AsStrictCompare(); | 1031 StrictCompareInstr* comp = definition->AsStrictCompare(); |
| 1020 if (comp != NULL) { | 1032 if (comp != NULL) { |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1134 | 1146 |
| 1135 if (FLAG_causal_async_stacks && | 1147 if (FLAG_causal_async_stacks && |
| 1136 (function.IsAsyncClosure() || function.IsAsyncGenClosure())) { | 1148 (function.IsAsyncClosure() || function.IsAsyncGenClosure())) { |
| 1137 // We are returning from an asynchronous closure. Before we do that, be | 1149 // We are returning from an asynchronous closure. Before we do that, be |
| 1138 // sure to clear the thread's asynchronous stack trace. | 1150 // sure to clear the thread's asynchronous stack trace. |
| 1139 const Function& async_clear_thread_stack_trace = Function::ZoneHandle( | 1151 const Function& async_clear_thread_stack_trace = Function::ZoneHandle( |
| 1140 Z, isolate()->object_store()->async_clear_thread_stack_trace()); | 1152 Z, isolate()->object_store()->async_clear_thread_stack_trace()); |
| 1141 ZoneGrowableArray<PushArgumentInstr*>* no_arguments = | 1153 ZoneGrowableArray<PushArgumentInstr*>* no_arguments = |
| 1142 new (Z) ZoneGrowableArray<PushArgumentInstr*>(0); | 1154 new (Z) ZoneGrowableArray<PushArgumentInstr*>(0); |
| 1143 const int kTypeArgsLen = 0; | 1155 const int kTypeArgsLen = 0; |
| 1144 StaticCallInstr* call_async_clear_thread_stack_trace = | 1156 StaticCallInstr* call_async_clear_thread_stack_trace = new (Z) |
| 1145 new (Z) StaticCallInstr(node->token_pos().ToSynthetic(), | 1157 StaticCallInstr(node->token_pos().ToSynthetic(), |
| 1146 async_clear_thread_stack_trace, kTypeArgsLen, | 1158 async_clear_thread_stack_trace, kTypeArgsLen, |
| 1147 Object::null_array(), no_arguments, | 1159 Object::null_array(), no_arguments, |
| 1148 owner()->ic_data_array()); | 1160 owner()->ic_data_array(), owner()->GetNextDeoptId()); |
| 1149 Do(call_async_clear_thread_stack_trace); | 1161 Do(call_async_clear_thread_stack_trace); |
| 1150 } | 1162 } |
| 1151 | 1163 |
| 1152 // Async functions contain two types of return statements: | 1164 // Async functions contain two types of return statements: |
| 1153 // 1) Returns that should complete the completer once all finally blocks have | 1165 // 1) Returns that should complete the completer once all finally blocks have |
| 1154 // been inlined (call: :async_completer.complete(return_value)). These | 1166 // been inlined (call: :async_completer.complete(return_value)). These |
| 1155 // returns end up returning null in the end. | 1167 // returns end up returning null in the end. |
| 1156 // 2) "Continuation" returns that should not complete the completer but return | 1168 // 2) "Continuation" returns that should not complete the completer but return |
| 1157 // the value. | 1169 // the value. |
| 1158 // | 1170 // |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1173 Value* returned_value = Bind(BuildLoadExprTemp(node->token_pos())); | 1185 Value* returned_value = Bind(BuildLoadExprTemp(node->token_pos())); |
| 1174 arguments->Add(PushArgument(returned_value)); | 1186 arguments->Add(PushArgument(returned_value)); |
| 1175 // Call a helper function to complete the completer. The debugger | 1187 // Call a helper function to complete the completer. The debugger |
| 1176 // uses the helper function to know when to step-out. | 1188 // uses the helper function to know when to step-out. |
| 1177 const Function& complete_on_async_return = Function::ZoneHandle( | 1189 const Function& complete_on_async_return = Function::ZoneHandle( |
| 1178 Z, isolate()->object_store()->complete_on_async_return()); | 1190 Z, isolate()->object_store()->complete_on_async_return()); |
| 1179 ASSERT(!complete_on_async_return.IsNull()); | 1191 ASSERT(!complete_on_async_return.IsNull()); |
| 1180 const int kTypeArgsLen = 0; | 1192 const int kTypeArgsLen = 0; |
| 1181 StaticCallInstr* call = new (Z) StaticCallInstr( | 1193 StaticCallInstr* call = new (Z) StaticCallInstr( |
| 1182 node->token_pos().ToSynthetic(), complete_on_async_return, kTypeArgsLen, | 1194 node->token_pos().ToSynthetic(), complete_on_async_return, kTypeArgsLen, |
| 1183 Object::null_array(), arguments, owner()->ic_data_array()); | 1195 Object::null_array(), arguments, owner()->ic_data_array(), |
| 1196 owner()->GetNextDeoptId()); |
| 1184 Do(call); | 1197 Do(call); |
| 1185 | 1198 |
| 1186 // Rebind the return value for the actual return call to be null. | 1199 // Rebind the return value for the actual return call to be null. |
| 1187 return_value = BuildNullValue(node->token_pos()); | 1200 return_value = BuildNullValue(node->token_pos()); |
| 1188 } | 1201 } |
| 1189 | 1202 |
| 1190 intptr_t current_context_level = owner()->context_level(); | 1203 intptr_t current_context_level = owner()->context_level(); |
| 1191 ASSERT(current_context_level >= 0); | 1204 ASSERT(current_context_level >= 0); |
| 1192 if (HasContextScope()) { | 1205 if (HasContextScope()) { |
| 1193 UnchainContexts(current_context_level); | 1206 UnchainContexts(current_context_level); |
| 1194 } | 1207 } |
| 1195 | 1208 |
| 1196 AddReturnExit(node->token_pos(), return_value); | 1209 AddReturnExit(node->token_pos(), return_value); |
| 1197 | 1210 |
| 1198 if ((function.IsAsyncClosure() || function.IsSyncGenClosure() || | 1211 if ((function.IsAsyncClosure() || function.IsSyncGenClosure() || |
| 1199 function.IsAsyncGenClosure()) && | 1212 function.IsAsyncGenClosure()) && |
| 1200 (node->return_type() == ReturnNode::kContinuationTarget)) { | 1213 (node->return_type() == ReturnNode::kContinuationTarget)) { |
| 1201 JoinEntryInstr* const join = new (Z) | 1214 JoinEntryInstr* const join = |
| 1202 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 1215 new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(), |
| 1216 owner()->GetNextDeoptId()); |
| 1203 owner()->await_joins()->Add(join); | 1217 owner()->await_joins()->Add(join); |
| 1204 exit_ = join; | 1218 exit_ = join; |
| 1205 } | 1219 } |
| 1206 } | 1220 } |
| 1207 | 1221 |
| 1208 | 1222 |
| 1209 // <Expression> ::= Literal { literal: Instance } | 1223 // <Expression> ::= Literal { literal: Instance } |
| 1210 void EffectGraphVisitor::VisitLiteralNode(LiteralNode* node) { | 1224 void EffectGraphVisitor::VisitLiteralNode(LiteralNode* node) { |
| 1211 ReturnDefinition(new (Z) ConstantInstr(node->literal(), node->token_pos())); | 1225 ReturnDefinition(new (Z) ConstantInstr(node->literal(), node->token_pos())); |
| 1212 } | 1226 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1235 } else { | 1249 } else { |
| 1236 instantiator_type_arguments = BuildInstantiatorTypeArguments(token_pos); | 1250 instantiator_type_arguments = BuildInstantiatorTypeArguments(token_pos); |
| 1237 } | 1251 } |
| 1238 Value* function_type_arguments = NULL; | 1252 Value* function_type_arguments = NULL; |
| 1239 if (type.IsInstantiated(kFunctions)) { | 1253 if (type.IsInstantiated(kFunctions)) { |
| 1240 function_type_arguments = BuildNullValue(token_pos); | 1254 function_type_arguments = BuildNullValue(token_pos); |
| 1241 } else { | 1255 } else { |
| 1242 function_type_arguments = BuildFunctionTypeArguments(token_pos); | 1256 function_type_arguments = BuildFunctionTypeArguments(token_pos); |
| 1243 } | 1257 } |
| 1244 ReturnDefinition(new (Z) InstantiateTypeInstr( | 1258 ReturnDefinition(new (Z) InstantiateTypeInstr( |
| 1245 token_pos, type, instantiator_type_arguments, function_type_arguments)); | 1259 token_pos, type, instantiator_type_arguments, function_type_arguments, |
| 1260 owner()->GetNextDeoptId())); |
| 1246 } | 1261 } |
| 1247 | 1262 |
| 1248 | 1263 |
| 1249 // Returns true if the type check can be skipped, for example, if the | 1264 // Returns true if the type check can be skipped, for example, if the |
| 1250 // destination type is dynamic or if the compile type of the value is a subtype | 1265 // destination type is dynamic or if the compile type of the value is a subtype |
| 1251 // of the destination type. | 1266 // of the destination type. |
| 1252 bool EffectGraphVisitor::CanSkipTypeCheck(TokenPosition token_pos, | 1267 bool EffectGraphVisitor::CanSkipTypeCheck(TokenPosition token_pos, |
| 1253 Value* value, | 1268 Value* value, |
| 1254 const AbstractType& dst_type, | 1269 const AbstractType& dst_type, |
| 1255 const String& dst_name) { | 1270 const String& dst_name) { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1325 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { | 1340 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { |
| 1326 // See ValueGraphVisitor::VisitBinaryOpNode. | 1341 // See ValueGraphVisitor::VisitBinaryOpNode. |
| 1327 TestGraphVisitor for_left(owner(), node->left()->token_pos()); | 1342 TestGraphVisitor for_left(owner(), node->left()->token_pos()); |
| 1328 node->left()->Visit(&for_left); | 1343 node->left()->Visit(&for_left); |
| 1329 EffectGraphVisitor empty(owner()); | 1344 EffectGraphVisitor empty(owner()); |
| 1330 Isolate* isolate = Isolate::Current(); | 1345 Isolate* isolate = Isolate::Current(); |
| 1331 if (isolate->type_checks() || isolate->asserts()) { | 1346 if (isolate->type_checks() || isolate->asserts()) { |
| 1332 ValueGraphVisitor for_right(owner()); | 1347 ValueGraphVisitor for_right(owner()); |
| 1333 node->right()->Visit(&for_right); | 1348 node->right()->Visit(&for_right); |
| 1334 Value* right_value = for_right.value(); | 1349 Value* right_value = for_right.value(); |
| 1335 for_right.Do( | 1350 for_right.Do(new (Z) AssertBooleanInstr( |
| 1336 new (Z) AssertBooleanInstr(node->right()->token_pos(), right_value)); | 1351 node->right()->token_pos(), right_value, owner()->GetNextDeoptId())); |
| 1337 if (node->kind() == Token::kAND) { | 1352 if (node->kind() == Token::kAND) { |
| 1338 Join(for_left, for_right, empty); | 1353 Join(for_left, for_right, empty); |
| 1339 } else { | 1354 } else { |
| 1340 Join(for_left, empty, for_right); | 1355 Join(for_left, empty, for_right); |
| 1341 } | 1356 } |
| 1342 } else { | 1357 } else { |
| 1343 EffectGraphVisitor for_right(owner()); | 1358 EffectGraphVisitor for_right(owner()); |
| 1344 node->right()->Visit(&for_right); | 1359 node->right()->Visit(&for_right); |
| 1345 if (node->kind() == Token::kAND) { | 1360 if (node->kind() == Token::kAND) { |
| 1346 Join(for_left, for_right, empty); | 1361 Join(for_left, for_right, empty); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1361 Append(for_right_value); | 1376 Append(for_right_value); |
| 1362 PushArgumentInstr* push_right = PushArgument(for_right_value.value()); | 1377 PushArgumentInstr* push_right = PushArgument(for_right_value.value()); |
| 1363 | 1378 |
| 1364 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1379 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 1365 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); | 1380 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
| 1366 arguments->Add(push_left); | 1381 arguments->Add(push_left); |
| 1367 arguments->Add(push_right); | 1382 arguments->Add(push_right); |
| 1368 const String& name = Symbols::Token(node->kind()); | 1383 const String& name = Symbols::Token(node->kind()); |
| 1369 const intptr_t kTypeArgsLen = 0; | 1384 const intptr_t kTypeArgsLen = 0; |
| 1370 const intptr_t kNumArgsChecked = 2; | 1385 const intptr_t kNumArgsChecked = 2; |
| 1371 InstanceCallInstr* call = new (Z) InstanceCallInstr( | 1386 InstanceCallInstr* call = new (Z) |
| 1372 node->token_pos(), name, node->kind(), arguments, kTypeArgsLen, | 1387 InstanceCallInstr(node->token_pos(), name, node->kind(), arguments, |
| 1373 Object::null_array(), kNumArgsChecked, owner()->ic_data_array()); | 1388 kTypeArgsLen, Object::null_array(), kNumArgsChecked, |
| 1389 owner()->ic_data_array(), owner()->GetNextDeoptId()); |
| 1374 ReturnDefinition(call); | 1390 ReturnDefinition(call); |
| 1375 } | 1391 } |
| 1376 | 1392 |
| 1377 | 1393 |
| 1378 // Special handling for AND/OR. | 1394 // Special handling for AND/OR. |
| 1379 void ValueGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) { | 1395 void ValueGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) { |
| 1380 // Operators "&&" and "||" cannot be overloaded therefore do not call | 1396 // Operators "&&" and "||" cannot be overloaded therefore do not call |
| 1381 // operator. | 1397 // operator. |
| 1382 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { | 1398 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { |
| 1383 // Implement short-circuit logic: do not evaluate right if evaluation | 1399 // Implement short-circuit logic: do not evaluate right if evaluation |
| 1384 // of left is sufficient. | 1400 // of left is sufficient. |
| 1385 // AND: left ? right === true : false; | 1401 // AND: left ? right === true : false; |
| 1386 // OR: left ? true : right === true; | 1402 // OR: left ? true : right === true; |
| 1387 | 1403 |
| 1388 TestGraphVisitor for_test(owner(), node->left()->token_pos()); | 1404 TestGraphVisitor for_test(owner(), node->left()->token_pos()); |
| 1389 node->left()->Visit(&for_test); | 1405 node->left()->Visit(&for_test); |
| 1390 | 1406 |
| 1391 ValueGraphVisitor for_right(owner()); | 1407 ValueGraphVisitor for_right(owner()); |
| 1392 node->right()->Visit(&for_right); | 1408 node->right()->Visit(&for_right); |
| 1393 Value* right_value = for_right.value(); | 1409 Value* right_value = for_right.value(); |
| 1394 Isolate* isolate = Isolate::Current(); | 1410 Isolate* isolate = Isolate::Current(); |
| 1395 if (isolate->type_checks() || isolate->asserts()) { | 1411 if (isolate->type_checks() || isolate->asserts()) { |
| 1396 right_value = for_right.Bind( | 1412 right_value = for_right.Bind(new (Z) AssertBooleanInstr( |
| 1397 new (Z) AssertBooleanInstr(node->right()->token_pos(), right_value)); | 1413 node->right()->token_pos(), right_value, owner()->GetNextDeoptId())); |
| 1398 } | 1414 } |
| 1399 Value* constant_true = for_right.Bind(new (Z) ConstantInstr(Bool::True())); | 1415 Value* constant_true = for_right.Bind(new (Z) ConstantInstr(Bool::True())); |
| 1400 Value* compare = for_right.Bind(new (Z) StrictCompareInstr( | 1416 Value* compare = for_right.Bind(new (Z) StrictCompareInstr( |
| 1401 node->token_pos(), Token::kEQ_STRICT, right_value, constant_true, | 1417 node->token_pos(), Token::kEQ_STRICT, right_value, constant_true, false, |
| 1402 false)); // No number check. | 1418 owner()->GetNextDeoptId())); // No number check. |
| 1403 for_right.Do(BuildStoreExprTemp(compare, node->token_pos())); | 1419 for_right.Do(BuildStoreExprTemp(compare, node->token_pos())); |
| 1404 | 1420 |
| 1405 if (node->kind() == Token::kAND) { | 1421 if (node->kind() == Token::kAND) { |
| 1406 ValueGraphVisitor for_false(owner()); | 1422 ValueGraphVisitor for_false(owner()); |
| 1407 Value* constant_false = | 1423 Value* constant_false = |
| 1408 for_false.Bind(new (Z) ConstantInstr(Bool::False())); | 1424 for_false.Bind(new (Z) ConstantInstr(Bool::False())); |
| 1409 for_false.Do(BuildStoreExprTemp(constant_false, node->token_pos())); | 1425 for_false.Do(BuildStoreExprTemp(constant_false, node->token_pos())); |
| 1410 Join(for_test, for_right, for_false); | 1426 Join(for_test, for_right, for_false); |
| 1411 } else { | 1427 } else { |
| 1412 ASSERT(node->kind() == Token::kOR); | 1428 ASSERT(node->kind() == Token::kOR); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1528 arguments->Add(push_left); | 1544 arguments->Add(push_left); |
| 1529 Value* type_const = Bind(new (Z) ConstantInstr(type)); | 1545 Value* type_const = Bind(new (Z) ConstantInstr(type)); |
| 1530 arguments->Add(PushArgument(type_const)); | 1546 arguments->Add(PushArgument(type_const)); |
| 1531 const intptr_t kTypeArgsLen = 0; | 1547 const intptr_t kTypeArgsLen = 0; |
| 1532 const intptr_t kNumArgsChecked = 2; | 1548 const intptr_t kNumArgsChecked = 2; |
| 1533 Definition* result = new (Z) InstanceCallInstr( | 1549 Definition* result = new (Z) InstanceCallInstr( |
| 1534 node->token_pos(), | 1550 node->token_pos(), |
| 1535 Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()), node->kind(), | 1551 Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()), node->kind(), |
| 1536 arguments, kTypeArgsLen, | 1552 arguments, kTypeArgsLen, |
| 1537 Object::null_array(), // No argument names. | 1553 Object::null_array(), // No argument names. |
| 1538 kNumArgsChecked, owner()->ic_data_array()); | 1554 kNumArgsChecked, owner()->ic_data_array(), owner()->GetNextDeoptId()); |
| 1539 if (negate_result) { | 1555 if (negate_result) { |
| 1540 result = new (Z) BooleanNegateInstr(Bind(result)); | 1556 result = new (Z) BooleanNegateInstr(Bind(result)); |
| 1541 } | 1557 } |
| 1542 ReturnDefinition(result); | 1558 ReturnDefinition(result); |
| 1543 return; | 1559 return; |
| 1544 } | 1560 } |
| 1545 | 1561 |
| 1546 PushArgumentInstr* push_instantiator_type_args = | 1562 PushArgumentInstr* push_instantiator_type_args = |
| 1547 PushInstantiatorTypeArguments(type, node->token_pos()); | 1563 PushInstantiatorTypeArguments(type, node->token_pos()); |
| 1548 PushArgumentInstr* push_function_type_args = | 1564 PushArgumentInstr* push_function_type_args = |
| 1549 PushFunctionTypeArguments(type, node->token_pos()); | 1565 PushFunctionTypeArguments(type, node->token_pos()); |
| 1550 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1566 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 1551 new (Z) ZoneGrowableArray<PushArgumentInstr*>(4); | 1567 new (Z) ZoneGrowableArray<PushArgumentInstr*>(4); |
| 1552 arguments->Add(push_left); | 1568 arguments->Add(push_left); |
| 1553 arguments->Add(push_instantiator_type_args); | 1569 arguments->Add(push_instantiator_type_args); |
| 1554 arguments->Add(push_function_type_args); | 1570 arguments->Add(push_function_type_args); |
| 1555 Value* type_const = Bind(new (Z) ConstantInstr(type)); | 1571 Value* type_const = Bind(new (Z) ConstantInstr(type)); |
| 1556 arguments->Add(PushArgument(type_const)); | 1572 arguments->Add(PushArgument(type_const)); |
| 1557 const intptr_t kTypeArgsLen = 0; | 1573 const intptr_t kTypeArgsLen = 0; |
| 1558 const intptr_t kNumArgsChecked = 1; | 1574 const intptr_t kNumArgsChecked = 1; |
| 1559 Definition* result = new (Z) InstanceCallInstr( | 1575 Definition* result = new (Z) InstanceCallInstr( |
| 1560 node->token_pos(), Library::PrivateCoreLibName(Symbols::_instanceOf()), | 1576 node->token_pos(), Library::PrivateCoreLibName(Symbols::_instanceOf()), |
| 1561 node->kind(), arguments, kTypeArgsLen, | 1577 node->kind(), arguments, kTypeArgsLen, |
| 1562 Object::null_array(), // No argument names. | 1578 Object::null_array(), // No argument names. |
| 1563 kNumArgsChecked, owner()->ic_data_array()); | 1579 kNumArgsChecked, owner()->ic_data_array(), owner()->GetNextDeoptId()); |
| 1564 if (negate_result) { | 1580 if (negate_result) { |
| 1565 result = new (Z) BooleanNegateInstr(Bind(result)); | 1581 result = new (Z) BooleanNegateInstr(Bind(result)); |
| 1566 } | 1582 } |
| 1567 ReturnDefinition(result); | 1583 ReturnDefinition(result); |
| 1568 } | 1584 } |
| 1569 | 1585 |
| 1570 | 1586 |
| 1571 void EffectGraphVisitor::BuildTypeCast(ComparisonNode* node) { | 1587 void EffectGraphVisitor::BuildTypeCast(ComparisonNode* node) { |
| 1572 ASSERT(Token::IsTypeCastOperator(node->kind())); | 1588 ASSERT(Token::IsTypeCastOperator(node->kind())); |
| 1573 ASSERT(!node->right()->AsTypeNode()->type().IsNull()); | 1589 ASSERT(!node->right()->AsTypeNode()->type().IsNull()); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1592 arguments->Add(push_instantiator_type_args); | 1608 arguments->Add(push_instantiator_type_args); |
| 1593 arguments->Add(push_function_type_args); | 1609 arguments->Add(push_function_type_args); |
| 1594 Value* type_arg = Bind(new (Z) ConstantInstr(type)); | 1610 Value* type_arg = Bind(new (Z) ConstantInstr(type)); |
| 1595 arguments->Add(PushArgument(type_arg)); | 1611 arguments->Add(PushArgument(type_arg)); |
| 1596 const int kTypeArgsLen = 0; | 1612 const int kTypeArgsLen = 0; |
| 1597 const intptr_t kNumArgsChecked = 1; | 1613 const intptr_t kNumArgsChecked = 1; |
| 1598 InstanceCallInstr* call = new (Z) InstanceCallInstr( | 1614 InstanceCallInstr* call = new (Z) InstanceCallInstr( |
| 1599 node->token_pos(), Library::PrivateCoreLibName(Symbols::_as()), | 1615 node->token_pos(), Library::PrivateCoreLibName(Symbols::_as()), |
| 1600 node->kind(), arguments, kTypeArgsLen, | 1616 node->kind(), arguments, kTypeArgsLen, |
| 1601 Object::null_array(), // No argument names. | 1617 Object::null_array(), // No argument names. |
| 1602 kNumArgsChecked, owner()->ic_data_array()); | 1618 kNumArgsChecked, owner()->ic_data_array(), owner()->GetNextDeoptId()); |
| 1603 ReturnDefinition(call); | 1619 ReturnDefinition(call); |
| 1604 } | 1620 } |
| 1605 | 1621 |
| 1606 | 1622 |
| 1607 StrictCompareInstr* EffectGraphVisitor::BuildStrictCompare( | 1623 StrictCompareInstr* EffectGraphVisitor::BuildStrictCompare( |
| 1608 AstNode* left, | 1624 AstNode* left, |
| 1609 AstNode* right, | 1625 AstNode* right, |
| 1610 Token::Kind kind, | 1626 Token::Kind kind, |
| 1611 TokenPosition token_pos) { | 1627 TokenPosition token_pos) { |
| 1612 ValueGraphVisitor for_left_value(owner()); | 1628 ValueGraphVisitor for_left_value(owner()); |
| 1613 left->Visit(&for_left_value); | 1629 left->Visit(&for_left_value); |
| 1614 Append(for_left_value); | 1630 Append(for_left_value); |
| 1615 ValueGraphVisitor for_right_value(owner()); | 1631 ValueGraphVisitor for_right_value(owner()); |
| 1616 right->Visit(&for_right_value); | 1632 right->Visit(&for_right_value); |
| 1617 Append(for_right_value); | 1633 Append(for_right_value); |
| 1618 StrictCompareInstr* comp = new (Z) StrictCompareInstr( | 1634 StrictCompareInstr* comp = new (Z) StrictCompareInstr( |
| 1619 token_pos, kind, for_left_value.value(), for_right_value.value(), | 1635 token_pos, kind, for_left_value.value(), for_right_value.value(), true, |
| 1620 true); // Number check. | 1636 owner()->GetNextDeoptId()); // Number check. |
| 1621 return comp; | 1637 return comp; |
| 1622 } | 1638 } |
| 1623 | 1639 |
| 1624 | 1640 |
| 1625 // <Expression> :: Comparison { kind: Token::Kind | 1641 // <Expression> :: Comparison { kind: Token::Kind |
| 1626 // left: <Expression> | 1642 // left: <Expression> |
| 1627 // right: <Expression> } | 1643 // right: <Expression> } |
| 1628 void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) { | 1644 void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) { |
| 1629 if (Token::IsTypeTestOperator(node->kind())) { | 1645 if (Token::IsTypeTestOperator(node->kind())) { |
| 1630 BuildTypeTest(node); | 1646 BuildTypeTest(node); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1666 arguments->Add(push_left); | 1682 arguments->Add(push_left); |
| 1667 | 1683 |
| 1668 ValueGraphVisitor for_right_value(owner()); | 1684 ValueGraphVisitor for_right_value(owner()); |
| 1669 node->right()->Visit(&for_right_value); | 1685 node->right()->Visit(&for_right_value); |
| 1670 Append(for_right_value); | 1686 Append(for_right_value); |
| 1671 PushArgumentInstr* push_right = PushArgument(for_right_value.value()); | 1687 PushArgumentInstr* push_right = PushArgument(for_right_value.value()); |
| 1672 arguments->Add(push_right); | 1688 arguments->Add(push_right); |
| 1673 | 1689 |
| 1674 const intptr_t kTypeArgsLen = 0; | 1690 const intptr_t kTypeArgsLen = 0; |
| 1675 const intptr_t kNumArgsChecked = 2; | 1691 const intptr_t kNumArgsChecked = 2; |
| 1676 Definition* result = new (Z) | 1692 Definition* result = new (Z) InstanceCallInstr( |
| 1677 InstanceCallInstr(node->token_pos(), Symbols::EqualOperator(), | 1693 node->token_pos(), Symbols::EqualOperator(), |
| 1678 Token::kEQ, // Result is negated later for kNE. | 1694 Token::kEQ, // Result is negated later for kNE. |
| 1679 arguments, kTypeArgsLen, Object::null_array(), | 1695 arguments, kTypeArgsLen, Object::null_array(), kNumArgsChecked, |
| 1680 kNumArgsChecked, owner()->ic_data_array()); | 1696 owner()->ic_data_array(), owner()->GetNextDeoptId()); |
| 1681 if (node->kind() == Token::kNE) { | 1697 if (node->kind() == Token::kNE) { |
| 1682 Isolate* isolate = Isolate::Current(); | 1698 Isolate* isolate = Isolate::Current(); |
| 1683 if (isolate->type_checks() || isolate->asserts()) { | 1699 if (isolate->type_checks() || isolate->asserts()) { |
| 1684 Value* value = Bind(result); | 1700 Value* value = Bind(result); |
| 1685 result = new (Z) AssertBooleanInstr(node->token_pos(), value); | 1701 result = new (Z) AssertBooleanInstr(node->token_pos(), value, |
| 1702 owner()->GetNextDeoptId()); |
| 1686 } | 1703 } |
| 1687 Value* value = Bind(result); | 1704 Value* value = Bind(result); |
| 1688 result = new (Z) BooleanNegateInstr(value); | 1705 result = new (Z) BooleanNegateInstr(value); |
| 1689 } | 1706 } |
| 1690 ReturnDefinition(result); | 1707 ReturnDefinition(result); |
| 1691 return; | 1708 return; |
| 1692 } | 1709 } |
| 1693 | 1710 |
| 1694 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1711 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 1695 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); | 1712 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
| 1696 | 1713 |
| 1697 ValueGraphVisitor for_left_value(owner()); | 1714 ValueGraphVisitor for_left_value(owner()); |
| 1698 node->left()->Visit(&for_left_value); | 1715 node->left()->Visit(&for_left_value); |
| 1699 Append(for_left_value); | 1716 Append(for_left_value); |
| 1700 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); | 1717 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); |
| 1701 arguments->Add(push_left); | 1718 arguments->Add(push_left); |
| 1702 | 1719 |
| 1703 ValueGraphVisitor for_right_value(owner()); | 1720 ValueGraphVisitor for_right_value(owner()); |
| 1704 node->right()->Visit(&for_right_value); | 1721 node->right()->Visit(&for_right_value); |
| 1705 Append(for_right_value); | 1722 Append(for_right_value); |
| 1706 PushArgumentInstr* push_right = PushArgument(for_right_value.value()); | 1723 PushArgumentInstr* push_right = PushArgument(for_right_value.value()); |
| 1707 arguments->Add(push_right); | 1724 arguments->Add(push_right); |
| 1708 | 1725 |
| 1709 ASSERT(Token::IsRelationalOperator(node->kind())); | 1726 ASSERT(Token::IsRelationalOperator(node->kind())); |
| 1710 const intptr_t kTypeArgsLen = 0; | 1727 const intptr_t kTypeArgsLen = 0; |
| 1711 InstanceCallInstr* comp = new (Z) InstanceCallInstr( | 1728 InstanceCallInstr* comp = new (Z) InstanceCallInstr( |
| 1712 node->token_pos(), Symbols::Token(node->kind()), node->kind(), arguments, | 1729 node->token_pos(), Symbols::Token(node->kind()), node->kind(), arguments, |
| 1713 kTypeArgsLen, Object::null_array(), 2, owner()->ic_data_array()); | 1730 kTypeArgsLen, Object::null_array(), 2, owner()->ic_data_array(), |
| 1731 owner()->GetNextDeoptId()); |
| 1714 ReturnDefinition(comp); | 1732 ReturnDefinition(comp); |
| 1715 } | 1733 } |
| 1716 | 1734 |
| 1717 | 1735 |
| 1718 void EffectGraphVisitor::VisitUnaryOpNode(UnaryOpNode* node) { | 1736 void EffectGraphVisitor::VisitUnaryOpNode(UnaryOpNode* node) { |
| 1719 // "!" cannot be overloaded, therefore do not call operator. | 1737 // "!" cannot be overloaded, therefore do not call operator. |
| 1720 if (node->kind() == Token::kNOT) { | 1738 if (node->kind() == Token::kNOT) { |
| 1721 ValueGraphVisitor for_value(owner()); | 1739 ValueGraphVisitor for_value(owner()); |
| 1722 node->operand()->Visit(&for_value); | 1740 node->operand()->Visit(&for_value); |
| 1723 Append(for_value); | 1741 Append(for_value); |
| 1724 Value* value = for_value.value(); | 1742 Value* value = for_value.value(); |
| 1725 Isolate* isolate = Isolate::Current(); | 1743 Isolate* isolate = Isolate::Current(); |
| 1726 if (isolate->type_checks() || isolate->asserts()) { | 1744 if (isolate->type_checks() || isolate->asserts()) { |
| 1727 value = | 1745 value = Bind(new (Z) AssertBooleanInstr( |
| 1728 Bind(new (Z) AssertBooleanInstr(node->operand()->token_pos(), value)); | 1746 node->operand()->token_pos(), value, owner()->GetNextDeoptId())); |
| 1729 } | 1747 } |
| 1730 BooleanNegateInstr* negate = new (Z) BooleanNegateInstr(value); | 1748 BooleanNegateInstr* negate = new (Z) BooleanNegateInstr(value); |
| 1731 ReturnDefinition(negate); | 1749 ReturnDefinition(negate); |
| 1732 return; | 1750 return; |
| 1733 } | 1751 } |
| 1734 | 1752 |
| 1735 ValueGraphVisitor for_value(owner()); | 1753 ValueGraphVisitor for_value(owner()); |
| 1736 node->operand()->Visit(&for_value); | 1754 node->operand()->Visit(&for_value); |
| 1737 Append(for_value); | 1755 Append(for_value); |
| 1738 PushArgumentInstr* push_value = PushArgument(for_value.value()); | 1756 PushArgumentInstr* push_value = PushArgument(for_value.value()); |
| 1739 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1757 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 1740 new (Z) ZoneGrowableArray<PushArgumentInstr*>(1); | 1758 new (Z) ZoneGrowableArray<PushArgumentInstr*>(1); |
| 1741 arguments->Add(push_value); | 1759 arguments->Add(push_value); |
| 1742 const intptr_t kTypeArgsLen = 0; | 1760 const intptr_t kTypeArgsLen = 0; |
| 1743 InstanceCallInstr* call = new (Z) InstanceCallInstr( | 1761 InstanceCallInstr* call = new (Z) InstanceCallInstr( |
| 1744 node->token_pos(), Symbols::Token(node->kind()), node->kind(), arguments, | 1762 node->token_pos(), Symbols::Token(node->kind()), node->kind(), arguments, |
| 1745 kTypeArgsLen, Object::null_array(), 1, owner()->ic_data_array()); | 1763 kTypeArgsLen, Object::null_array(), 1, owner()->ic_data_array(), |
| 1764 owner()->GetNextDeoptId()); |
| 1746 ReturnDefinition(call); | 1765 ReturnDefinition(call); |
| 1747 } | 1766 } |
| 1748 | 1767 |
| 1749 | 1768 |
| 1750 void EffectGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) { | 1769 void EffectGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) { |
| 1751 TestGraphVisitor for_test(owner(), node->condition()->token_pos()); | 1770 TestGraphVisitor for_test(owner(), node->condition()->token_pos()); |
| 1752 node->condition()->Visit(&for_test); | 1771 node->condition()->Visit(&for_test); |
| 1753 | 1772 |
| 1754 // Translate the subexpressions for their effects. | 1773 // Translate the subexpressions for their effects. |
| 1755 EffectGraphVisitor for_true(owner()); | 1774 EffectGraphVisitor for_true(owner()); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1833 // | 1852 // |
| 1834 // Note: The specification of switch/case is under discussion and may change | 1853 // Note: The specification of switch/case is under discussion and may change |
| 1835 // drastically. | 1854 // drastically. |
| 1836 void EffectGraphVisitor::VisitCaseNode(CaseNode* node) { | 1855 void EffectGraphVisitor::VisitCaseNode(CaseNode* node) { |
| 1837 const intptr_t len = node->case_expressions()->length(); | 1856 const intptr_t len = node->case_expressions()->length(); |
| 1838 // Create case statements instructions. | 1857 // Create case statements instructions. |
| 1839 EffectGraphVisitor for_case_statements(owner()); | 1858 EffectGraphVisitor for_case_statements(owner()); |
| 1840 // Compute the start of the statements fragment. | 1859 // Compute the start of the statements fragment. |
| 1841 JoinEntryInstr* statement_start = NULL; | 1860 JoinEntryInstr* statement_start = NULL; |
| 1842 if (node->label() == NULL) { | 1861 if (node->label() == NULL) { |
| 1843 statement_start = new (Z) | 1862 statement_start = |
| 1844 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 1863 new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(), |
| 1864 owner()->GetNextDeoptId()); |
| 1845 } else { | 1865 } else { |
| 1846 // The case nodes are nested inside a SequenceNode that is the body of a | 1866 // The case nodes are nested inside a SequenceNode that is the body of a |
| 1847 // SwitchNode. The SwitchNode on the nesting stack contains the | 1867 // SwitchNode. The SwitchNode on the nesting stack contains the |
| 1848 // continue labels for all the case clauses. | 1868 // continue labels for all the case clauses. |
| 1849 statement_start = | 1869 statement_start = |
| 1850 owner()->nesting_stack()->outer()->ContinueTargetFor(node->label()); | 1870 owner()->nesting_stack()->outer()->ContinueTargetFor(node->label()); |
| 1851 } | 1871 } |
| 1852 ASSERT(statement_start != NULL); | 1872 ASSERT(statement_start != NULL); |
| 1853 node->statements()->Visit(&for_case_statements); | 1873 node->statements()->Visit(&for_case_statements); |
| 1854 Instruction* statement_exit = | 1874 Instruction* statement_exit = |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1886 // node contains default. | 1906 // node contains default. |
| 1887 if (len > 0) { | 1907 if (len > 0) { |
| 1888 ASSERT(next_target != NULL); | 1908 ASSERT(next_target != NULL); |
| 1889 if (node->contains_default()) { | 1909 if (node->contains_default()) { |
| 1890 // True and false go to statement start. | 1910 // True and false go to statement start. |
| 1891 next_target->Goto(statement_start); | 1911 next_target->Goto(statement_start); |
| 1892 exit_instruction = statement_exit; | 1912 exit_instruction = statement_exit; |
| 1893 } else { | 1913 } else { |
| 1894 if (statement_exit != NULL) { | 1914 if (statement_exit != NULL) { |
| 1895 JoinEntryInstr* join = new (Z) | 1915 JoinEntryInstr* join = new (Z) |
| 1896 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 1916 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(), |
| 1917 owner()->GetNextDeoptId()); |
| 1897 statement_exit->Goto(join); | 1918 statement_exit->Goto(join); |
| 1898 next_target->Goto(join); | 1919 next_target->Goto(join); |
| 1899 exit_instruction = join; | 1920 exit_instruction = join; |
| 1900 } else { | 1921 } else { |
| 1901 exit_instruction = next_target; | 1922 exit_instruction = next_target; |
| 1902 } | 1923 } |
| 1903 } | 1924 } |
| 1904 } else { | 1925 } else { |
| 1905 // A CaseNode without case expressions must contain default. | 1926 // A CaseNode without case expressions must contain default. |
| 1906 ASSERT(node->contains_default()); | 1927 ASSERT(node->contains_default()); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1969 // Traverse the body first in order to generate continue and break labels. | 1990 // Traverse the body first in order to generate continue and break labels. |
| 1970 EffectGraphVisitor for_body(owner()); | 1991 EffectGraphVisitor for_body(owner()); |
| 1971 node->body()->Visit(&for_body); | 1992 node->body()->Visit(&for_body); |
| 1972 | 1993 |
| 1973 TestGraphVisitor for_test(owner(), node->condition()->token_pos()); | 1994 TestGraphVisitor for_test(owner(), node->condition()->token_pos()); |
| 1974 node->condition()->Visit(&for_test); | 1995 node->condition()->Visit(&for_test); |
| 1975 ASSERT(is_open()); | 1996 ASSERT(is_open()); |
| 1976 | 1997 |
| 1977 // Tie do-while loop (test is after the body). | 1998 // Tie do-while loop (test is after the body). |
| 1978 JoinEntryInstr* body_entry_join = | 1999 JoinEntryInstr* body_entry_join = |
| 1979 new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 2000 new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(), |
| 2001 owner()->GetNextDeoptId()); |
| 1980 Goto(body_entry_join); | 2002 Goto(body_entry_join); |
| 1981 Instruction* body_exit = AppendFragment(body_entry_join, for_body); | 2003 Instruction* body_exit = AppendFragment(body_entry_join, for_body); |
| 1982 | 2004 |
| 1983 JoinEntryInstr* join = nested_loop.continue_target(); | 2005 JoinEntryInstr* join = nested_loop.continue_target(); |
| 1984 if ((body_exit != NULL) || (join != NULL)) { | 2006 if ((body_exit != NULL) || (join != NULL)) { |
| 1985 if (join == NULL) { | 2007 if (join == NULL) { |
| 1986 join = new (Z) | 2008 join = new (Z) |
| 1987 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 2009 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(), |
| 2010 owner()->GetNextDeoptId()); |
| 1988 } | 2011 } |
| 1989 CheckStackOverflowInstr* check = new (Z) | 2012 CheckStackOverflowInstr* check = new (Z) CheckStackOverflowInstr( |
| 1990 CheckStackOverflowInstr(node->token_pos(), owner()->loop_depth()); | 2013 node->token_pos(), owner()->loop_depth(), owner()->GetNextDeoptId()); |
| 1991 join->LinkTo(check); | 2014 join->LinkTo(check); |
| 1992 check->LinkTo(for_test.entry()); | 2015 check->LinkTo(for_test.entry()); |
| 1993 if (body_exit != NULL) { | 2016 if (body_exit != NULL) { |
| 1994 body_exit->Goto(join); | 2017 body_exit->Goto(join); |
| 1995 } | 2018 } |
| 1996 } | 2019 } |
| 1997 | 2020 |
| 1998 for_test.IfTrueGoto(body_entry_join); | 2021 for_test.IfTrueGoto(body_entry_join); |
| 1999 join = nested_loop.break_target(); | 2022 join = nested_loop.break_target(); |
| 2000 if (join == NULL) { | 2023 if (join == NULL) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2028 // Compose body to set any jump labels. | 2051 // Compose body to set any jump labels. |
| 2029 EffectGraphVisitor for_body(owner()); | 2052 EffectGraphVisitor for_body(owner()); |
| 2030 node->body()->Visit(&for_body); | 2053 node->body()->Visit(&for_body); |
| 2031 | 2054 |
| 2032 EffectGraphVisitor for_increment(owner()); | 2055 EffectGraphVisitor for_increment(owner()); |
| 2033 node->increment()->Visit(&for_increment); | 2056 node->increment()->Visit(&for_increment); |
| 2034 | 2057 |
| 2035 // Join the loop body and increment and then tie the loop. | 2058 // Join the loop body and increment and then tie the loop. |
| 2036 JoinEntryInstr* continue_join = nested_loop.continue_target(); | 2059 JoinEntryInstr* continue_join = nested_loop.continue_target(); |
| 2037 if ((continue_join != NULL) || for_body.is_open()) { | 2060 if ((continue_join != NULL) || for_body.is_open()) { |
| 2038 JoinEntryInstr* loop_entry = new (Z) | 2061 JoinEntryInstr* loop_entry = |
| 2039 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 2062 new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(), |
| 2063 owner()->GetNextDeoptId()); |
| 2040 if (continue_join != NULL) { | 2064 if (continue_join != NULL) { |
| 2041 if (for_body.is_open()) for_body.Goto(continue_join); | 2065 if (for_body.is_open()) for_body.Goto(continue_join); |
| 2042 Instruction* current = AppendFragment(continue_join, for_increment); | 2066 Instruction* current = AppendFragment(continue_join, for_increment); |
| 2043 current->Goto(loop_entry); | 2067 current->Goto(loop_entry); |
| 2044 } else { | 2068 } else { |
| 2045 for_body.Append(for_increment); | 2069 for_body.Append(for_increment); |
| 2046 for_body.Goto(loop_entry); | 2070 for_body.Goto(loop_entry); |
| 2047 } | 2071 } |
| 2048 Goto(loop_entry); | 2072 Goto(loop_entry); |
| 2049 exit_ = loop_entry; | 2073 exit_ = loop_entry; |
| 2050 // Note: the stack overflow check happens on the back branch that jumps | 2074 // Note: the stack overflow check happens on the back branch that jumps |
| 2051 // to the increment instruction. The token position for the overflow | 2075 // to the increment instruction. The token position for the overflow |
| 2052 // check must match the position of the increment expression, so that | 2076 // check must match the position of the increment expression, so that |
| 2053 // the context level (if any) matches the that of the increment | 2077 // the context level (if any) matches the that of the increment |
| 2054 // expression. | 2078 // expression. |
| 2055 AddInstruction(new (Z) CheckStackOverflowInstr( | 2079 AddInstruction(new (Z) CheckStackOverflowInstr( |
| 2056 node->increment()->token_pos(), owner()->loop_depth())); | 2080 node->increment()->token_pos(), owner()->loop_depth(), |
| 2081 owner()->GetNextDeoptId())); |
| 2057 } | 2082 } |
| 2058 | 2083 |
| 2059 if (node->condition() == NULL) { | 2084 if (node->condition() == NULL) { |
| 2060 // Endless loop, no test. | 2085 // Endless loop, no test. |
| 2061 Append(for_body); | 2086 Append(for_body); |
| 2062 exit_ = nested_loop.break_target(); // May be NULL. | 2087 exit_ = nested_loop.break_target(); // May be NULL. |
| 2063 } else { | 2088 } else { |
| 2064 EffectGraphVisitor for_test_preamble(owner()); | 2089 EffectGraphVisitor for_test_preamble(owner()); |
| 2065 if (node->condition_preamble() != NULL) { | 2090 if (node->condition_preamble() != NULL) { |
| 2066 node->condition_preamble()->Visit(&for_test_preamble); | 2091 node->condition_preamble()->Visit(&for_test_preamble); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2241 } | 2266 } |
| 2242 | 2267 |
| 2243 | 2268 |
| 2244 void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) { | 2269 void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) { |
| 2245 const TypeArguments& type_args = | 2270 const TypeArguments& type_args = |
| 2246 TypeArguments::ZoneHandle(Z, node->type().arguments()); | 2271 TypeArguments::ZoneHandle(Z, node->type().arguments()); |
| 2247 Value* element_type = | 2272 Value* element_type = |
| 2248 BuildInstantiatedTypeArguments(node->token_pos(), type_args); | 2273 BuildInstantiatedTypeArguments(node->token_pos(), type_args); |
| 2249 Value* num_elements = | 2274 Value* num_elements = |
| 2250 Bind(new (Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(node->length())))); | 2275 Bind(new (Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(node->length())))); |
| 2251 CreateArrayInstr* create = | 2276 CreateArrayInstr* create = new (Z) CreateArrayInstr( |
| 2252 new (Z) CreateArrayInstr(node->token_pos(), element_type, num_elements); | 2277 node->token_pos(), element_type, num_elements, owner()->GetNextDeoptId()); |
| 2253 Value* array_val = Bind(create); | 2278 Value* array_val = Bind(create); |
| 2254 | 2279 |
| 2255 { | 2280 { |
| 2256 LocalVariable* tmp_var = EnterTempLocalScope(array_val); | 2281 LocalVariable* tmp_var = EnterTempLocalScope(array_val); |
| 2257 const intptr_t class_id = kArrayCid; | 2282 const intptr_t class_id = kArrayCid; |
| 2258 const intptr_t deopt_id = Thread::kNoDeoptId; | 2283 const intptr_t deopt_id = Thread::kNoDeoptId; |
| 2259 for (int i = 0; i < node->length(); ++i) { | 2284 for (int i = 0; i < node->length(); ++i) { |
| 2260 Value* array = Bind(new (Z) LoadLocalInstr(*tmp_var, node->token_pos())); | 2285 Value* array = Bind(new (Z) LoadLocalInstr(*tmp_var, node->token_pos())); |
| 2261 Value* index = Bind(new (Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(i)), | 2286 Value* index = Bind(new (Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(i)), |
| 2262 node->token_pos())); | 2287 node->token_pos())); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2292 const int kTypeArgsLen = 0; | 2317 const int kTypeArgsLen = 0; |
| 2293 const int kNumberOfArguments = 1; | 2318 const int kNumberOfArguments = 1; |
| 2294 const Array& kNoArgumentNames = Object::null_array(); | 2319 const Array& kNoArgumentNames = Object::null_array(); |
| 2295 const Class& cls = | 2320 const Class& cls = |
| 2296 Class::Handle(Library::LookupCoreClass(Symbols::StringBase())); | 2321 Class::Handle(Library::LookupCoreClass(Symbols::StringBase())); |
| 2297 ASSERT(!cls.IsNull()); | 2322 ASSERT(!cls.IsNull()); |
| 2298 const Function& function = Function::ZoneHandle( | 2323 const Function& function = Function::ZoneHandle( |
| 2299 Z, Resolver::ResolveStatic( | 2324 Z, Resolver::ResolveStatic( |
| 2300 cls, Library::PrivateCoreLibName(Symbols::InterpolateSingle()), | 2325 cls, Library::PrivateCoreLibName(Symbols::InterpolateSingle()), |
| 2301 kTypeArgsLen, kNumberOfArguments, kNoArgumentNames)); | 2326 kTypeArgsLen, kNumberOfArguments, kNoArgumentNames)); |
| 2302 StaticCallInstr* call = new (Z) | 2327 StaticCallInstr* call = new (Z) StaticCallInstr( |
| 2303 StaticCallInstr(node->token_pos(), function, kTypeArgsLen, | 2328 node->token_pos(), function, kTypeArgsLen, kNoArgumentNames, values, |
| 2304 kNoArgumentNames, values, owner()->ic_data_array()); | 2329 owner()->ic_data_array(), owner()->GetNextDeoptId()); |
| 2305 ReturnDefinition(call); | 2330 ReturnDefinition(call); |
| 2306 return; | 2331 return; |
| 2307 } | 2332 } |
| 2308 arguments->Visit(&for_argument); | 2333 arguments->Visit(&for_argument); |
| 2309 Append(for_argument); | 2334 Append(for_argument); |
| 2310 StringInterpolateInstr* instr = | 2335 StringInterpolateInstr* instr = new (Z) StringInterpolateInstr( |
| 2311 new (Z) StringInterpolateInstr(for_argument.value(), node->token_pos()); | 2336 for_argument.value(), node->token_pos(), owner()->GetNextDeoptId()); |
| 2312 ReturnDefinition(instr); | 2337 ReturnDefinition(instr); |
| 2313 } | 2338 } |
| 2314 | 2339 |
| 2315 | 2340 |
| 2316 void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) { | 2341 void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) { |
| 2317 const Function& function = node->function(); | 2342 const Function& function = node->function(); |
| 2318 if (function.IsImplicitStaticClosureFunction()) { | 2343 if (function.IsImplicitStaticClosureFunction()) { |
| 2319 const Instance& closure = | 2344 const Instance& closure = |
| 2320 Instance::ZoneHandle(Z, function.ImplicitStaticClosure()); | 2345 Instance::ZoneHandle(Z, function.ImplicitStaticClosure()); |
| 2321 ReturnDefinition(new (Z) ConstantInstr(closure)); | 2346 ReturnDefinition(new (Z) ConstantInstr(closure)); |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2523 BuildPushTypeArguments(*node->arguments(), arguments); | 2548 BuildPushTypeArguments(*node->arguments(), arguments); |
| 2524 ValueGraphVisitor for_receiver(owner()); | 2549 ValueGraphVisitor for_receiver(owner()); |
| 2525 node->receiver()->Visit(&for_receiver); | 2550 node->receiver()->Visit(&for_receiver); |
| 2526 Append(for_receiver); | 2551 Append(for_receiver); |
| 2527 PushArgumentInstr* push_receiver = PushArgument(for_receiver.value()); | 2552 PushArgumentInstr* push_receiver = PushArgument(for_receiver.value()); |
| 2528 arguments->Add(push_receiver); | 2553 arguments->Add(push_receiver); |
| 2529 BuildPushArguments(*node->arguments(), arguments); | 2554 BuildPushArguments(*node->arguments(), arguments); |
| 2530 InstanceCallInstr* call = new (Z) InstanceCallInstr( | 2555 InstanceCallInstr* call = new (Z) InstanceCallInstr( |
| 2531 node->token_pos(), node->function_name(), Token::kILLEGAL, arguments, | 2556 node->token_pos(), node->function_name(), Token::kILLEGAL, arguments, |
| 2532 node->arguments()->type_args_len(), node->arguments()->names(), 1, | 2557 node->arguments()->type_args_len(), node->arguments()->names(), 1, |
| 2533 owner()->ic_data_array()); | 2558 owner()->ic_data_array(), owner()->GetNextDeoptId()); |
| 2534 ReturnDefinition(call); | 2559 ReturnDefinition(call); |
| 2535 } | 2560 } |
| 2536 } | 2561 } |
| 2537 | 2562 |
| 2538 | 2563 |
| 2539 // <Expression> ::= StaticCall { function: Function | 2564 // <Expression> ::= StaticCall { function: Function |
| 2540 // arguments: <ArgumentList> } | 2565 // arguments: <ArgumentList> } |
| 2541 void EffectGraphVisitor::VisitStaticCallNode(StaticCallNode* node) { | 2566 void EffectGraphVisitor::VisitStaticCallNode(StaticCallNode* node) { |
| 2542 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 2567 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 2543 new (Z) ZoneGrowableArray<PushArgumentInstr*>( | 2568 new (Z) ZoneGrowableArray<PushArgumentInstr*>( |
| 2544 node->arguments()->LengthWithTypeArgs()); | 2569 node->arguments()->LengthWithTypeArgs()); |
| 2545 BuildPushTypeArguments(*node->arguments(), arguments); | 2570 BuildPushTypeArguments(*node->arguments(), arguments); |
| 2546 BuildPushArguments(*node->arguments(), arguments); | 2571 BuildPushArguments(*node->arguments(), arguments); |
| 2547 StaticCallInstr* call = new (Z) StaticCallInstr( | 2572 StaticCallInstr* call = new (Z) StaticCallInstr( |
| 2548 node->token_pos(), node->function(), node->arguments()->type_args_len(), | 2573 node->token_pos(), node->function(), node->arguments()->type_args_len(), |
| 2549 node->arguments()->names(), arguments, owner()->ic_data_array()); | 2574 node->arguments()->names(), arguments, owner()->ic_data_array(), |
| 2575 owner()->GetNextDeoptId()); |
| 2550 if (node->function().recognized_kind() != MethodRecognizer::kUnknown) { | 2576 if (node->function().recognized_kind() != MethodRecognizer::kUnknown) { |
| 2551 call->set_result_cid(MethodRecognizer::ResultCid(node->function())); | 2577 call->set_result_cid(MethodRecognizer::ResultCid(node->function())); |
| 2552 } | 2578 } |
| 2553 ReturnDefinition(call); | 2579 ReturnDefinition(call); |
| 2554 } | 2580 } |
| 2555 | 2581 |
| 2556 | 2582 |
| 2557 void EffectGraphVisitor::BuildClosureCall(ClosureCallNode* node, | 2583 void EffectGraphVisitor::BuildClosureCall(ClosureCallNode* node, |
| 2558 bool result_needed) { | 2584 bool result_needed) { |
| 2559 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 2585 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2573 arguments->Add(push_closure); | 2599 arguments->Add(push_closure); |
| 2574 BuildPushArguments(*node->arguments(), arguments); | 2600 BuildPushArguments(*node->arguments(), arguments); |
| 2575 | 2601 |
| 2576 closure_val = Bind(new (Z) LoadLocalInstr(*tmp_var, node->token_pos())); | 2602 closure_val = Bind(new (Z) LoadLocalInstr(*tmp_var, node->token_pos())); |
| 2577 LoadFieldInstr* function_load = new (Z) LoadFieldInstr( | 2603 LoadFieldInstr* function_load = new (Z) LoadFieldInstr( |
| 2578 closure_val, Closure::function_offset(), | 2604 closure_val, Closure::function_offset(), |
| 2579 AbstractType::ZoneHandle(Z, AbstractType::null()), node->token_pos()); | 2605 AbstractType::ZoneHandle(Z, AbstractType::null()), node->token_pos()); |
| 2580 function_load->set_is_immutable(true); | 2606 function_load->set_is_immutable(true); |
| 2581 Value* function_val = Bind(function_load); | 2607 Value* function_val = Bind(function_load); |
| 2582 | 2608 |
| 2583 Definition* closure_call = | 2609 Definition* closure_call = new (Z) ClosureCallInstr( |
| 2584 new (Z) ClosureCallInstr(function_val, node, arguments); | 2610 function_val, node, arguments, owner()->GetNextDeoptId()); |
| 2585 if (result_needed) { | 2611 if (result_needed) { |
| 2586 Value* result = Bind(closure_call); | 2612 Value* result = Bind(closure_call); |
| 2587 Do(new (Z) StoreLocalInstr(*tmp_var, result, ST(node->token_pos()))); | 2613 Do(new (Z) StoreLocalInstr(*tmp_var, result, ST(node->token_pos()))); |
| 2588 } else { | 2614 } else { |
| 2589 Do(closure_call); | 2615 Do(closure_call); |
| 2590 } | 2616 } |
| 2591 ReturnDefinition(ExitTempLocalScope(closure_value)); | 2617 ReturnDefinition(ExitTempLocalScope(closure_value)); |
| 2592 } | 2618 } |
| 2593 | 2619 |
| 2594 | 2620 |
| 2595 void EffectGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { | 2621 void EffectGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { |
| 2596 BuildClosureCall(node, false); | 2622 BuildClosureCall(node, false); |
| 2597 } | 2623 } |
| 2598 | 2624 |
| 2599 | 2625 |
| 2600 void ValueGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { | 2626 void ValueGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { |
| 2601 BuildClosureCall(node, true); | 2627 BuildClosureCall(node, true); |
| 2602 } | 2628 } |
| 2603 | 2629 |
| 2604 | 2630 |
| 2605 void EffectGraphVisitor::VisitInitStaticFieldNode(InitStaticFieldNode* node) { | 2631 void EffectGraphVisitor::VisitInitStaticFieldNode(InitStaticFieldNode* node) { |
| 2606 Value* field = Bind( | 2632 Value* field = Bind( |
| 2607 new (Z) ConstantInstr(Field::ZoneHandle(Z, node->field().Original()))); | 2633 new (Z) ConstantInstr(Field::ZoneHandle(Z, node->field().Original()))); |
| 2608 AddInstruction(new (Z) InitStaticFieldInstr(field, node->field())); | 2634 AddInstruction(new (Z) InitStaticFieldInstr(field, node->field(), |
| 2635 owner()->GetNextDeoptId())); |
| 2609 } | 2636 } |
| 2610 | 2637 |
| 2611 | 2638 |
| 2612 void EffectGraphVisitor::VisitCloneContextNode(CloneContextNode* node) { | 2639 void EffectGraphVisitor::VisitCloneContextNode(CloneContextNode* node) { |
| 2613 Value* context = Bind(BuildCurrentContext(node->token_pos())); | 2640 Value* context = Bind(BuildCurrentContext(node->token_pos())); |
| 2614 Value* clone = Bind(new (Z) CloneContextInstr(node->token_pos(), context)); | 2641 Value* clone = Bind(new (Z) CloneContextInstr(node->token_pos(), context, |
| 2642 owner()->GetNextDeoptId())); |
| 2615 Do(BuildStoreContext(clone, node->token_pos())); | 2643 Do(BuildStoreContext(clone, node->token_pos())); |
| 2616 } | 2644 } |
| 2617 | 2645 |
| 2618 | 2646 |
| 2619 Value* EffectGraphVisitor::BuildObjectAllocation(ConstructorCallNode* node) { | 2647 Value* EffectGraphVisitor::BuildObjectAllocation(ConstructorCallNode* node) { |
| 2620 const Class& cls = Class::ZoneHandle(Z, node->constructor().Owner()); | 2648 const Class& cls = Class::ZoneHandle(Z, node->constructor().Owner()); |
| 2621 const bool cls_is_parameterized = cls.NumTypeArguments() > 0; | 2649 const bool cls_is_parameterized = cls.NumTypeArguments() > 0; |
| 2622 | 2650 |
| 2623 ZoneGrowableArray<PushArgumentInstr*>* allocate_arguments = new (Z) | 2651 ZoneGrowableArray<PushArgumentInstr*>* allocate_arguments = new (Z) |
| 2624 ZoneGrowableArray<PushArgumentInstr*>(cls_is_parameterized ? 1 : 0); | 2652 ZoneGrowableArray<PushArgumentInstr*>(cls_is_parameterized ? 1 : 0); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2638 | 2666 |
| 2639 void EffectGraphVisitor::BuildConstructorCall( | 2667 void EffectGraphVisitor::BuildConstructorCall( |
| 2640 ConstructorCallNode* node, | 2668 ConstructorCallNode* node, |
| 2641 PushArgumentInstr* push_alloc_value) { | 2669 PushArgumentInstr* push_alloc_value) { |
| 2642 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 2670 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 2643 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); | 2671 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
| 2644 arguments->Add(push_alloc_value); | 2672 arguments->Add(push_alloc_value); |
| 2645 | 2673 |
| 2646 BuildPushArguments(*node->arguments(), arguments); | 2674 BuildPushArguments(*node->arguments(), arguments); |
| 2647 const intptr_t kTypeArgsLen = 0; | 2675 const intptr_t kTypeArgsLen = 0; |
| 2648 Do(new (Z) StaticCallInstr(node->token_pos(), node->constructor(), | 2676 Do(new (Z) |
| 2649 kTypeArgsLen, node->arguments()->names(), | 2677 StaticCallInstr(node->token_pos(), node->constructor(), kTypeArgsLen, |
| 2650 arguments, owner()->ic_data_array())); | 2678 node->arguments()->names(), arguments, |
| 2679 owner()->ic_data_array(), owner()->GetNextDeoptId())); |
| 2651 } | 2680 } |
| 2652 | 2681 |
| 2653 | 2682 |
| 2654 static intptr_t GetResultCidOfListFactory(ConstructorCallNode* node) { | 2683 static intptr_t GetResultCidOfListFactory(ConstructorCallNode* node) { |
| 2655 const Function& function = node->constructor(); | 2684 const Function& function = node->constructor(); |
| 2656 const Class& function_class = Class::Handle(function.Owner()); | 2685 const Class& function_class = Class::Handle(function.Owner()); |
| 2657 | 2686 |
| 2658 if ((function_class.library() != Library::CoreLibrary()) && | 2687 if ((function_class.library() != Library::CoreLibrary()) && |
| 2659 (function_class.library() != Library::TypedDataLibrary())) { | 2688 (function_class.library() != Library::TypedDataLibrary())) { |
| 2660 return kDynamicCid; | 2689 return kDynamicCid; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2679 if (node->constructor().IsFactory()) { | 2708 if (node->constructor().IsFactory()) { |
| 2680 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 2709 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 2681 new (Z) ZoneGrowableArray<PushArgumentInstr*>(); | 2710 new (Z) ZoneGrowableArray<PushArgumentInstr*>(); |
| 2682 PushArgumentInstr* push_type_arguments = | 2711 PushArgumentInstr* push_type_arguments = |
| 2683 PushArgument(BuildInstantiatedTypeArguments(node->token_pos(), | 2712 PushArgument(BuildInstantiatedTypeArguments(node->token_pos(), |
| 2684 node->type_arguments())); | 2713 node->type_arguments())); |
| 2685 arguments->Add(push_type_arguments); | 2714 arguments->Add(push_type_arguments); |
| 2686 ASSERT(arguments->length() == 1); | 2715 ASSERT(arguments->length() == 1); |
| 2687 BuildPushArguments(*node->arguments(), arguments); | 2716 BuildPushArguments(*node->arguments(), arguments); |
| 2688 const int kTypeArgsLen = 0; | 2717 const int kTypeArgsLen = 0; |
| 2689 StaticCallInstr* call = new (Z) StaticCallInstr( | 2718 StaticCallInstr* call = new (Z) |
| 2690 node->token_pos(), node->constructor(), kTypeArgsLen, | 2719 StaticCallInstr(node->token_pos(), node->constructor(), kTypeArgsLen, |
| 2691 node->arguments()->names(), arguments, owner()->ic_data_array()); | 2720 node->arguments()->names(), arguments, |
| 2721 owner()->ic_data_array(), owner()->GetNextDeoptId()); |
| 2692 const intptr_t result_cid = GetResultCidOfListFactory(node); | 2722 const intptr_t result_cid = GetResultCidOfListFactory(node); |
| 2693 if (result_cid != kDynamicCid) { | 2723 if (result_cid != kDynamicCid) { |
| 2694 call->set_result_cid(result_cid); | 2724 call->set_result_cid(result_cid); |
| 2695 call->set_is_known_list_constructor(true); | 2725 call->set_is_known_list_constructor(true); |
| 2696 // Recognized fixed length array factory must have two arguments: | 2726 // Recognized fixed length array factory must have two arguments: |
| 2697 // (0) type-arguments, (1) length. | 2727 // (0) type-arguments, (1) length. |
| 2698 ASSERT(!LoadFieldInstr::IsFixedLengthArrayCid(result_cid) || | 2728 ASSERT(!LoadFieldInstr::IsFixedLengthArrayCid(result_cid) || |
| 2699 arguments->length() == 2); | 2729 arguments->length() == 2); |
| 2700 } else if (node->constructor().recognized_kind() != | 2730 } else if (node->constructor().recognized_kind() != |
| 2701 MethodRecognizer::kUnknown) { | 2731 MethodRecognizer::kUnknown) { |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2823 } | 2853 } |
| 2824 } | 2854 } |
| 2825 Value* function_type_args = NULL; | 2855 Value* function_type_args = NULL; |
| 2826 if (type_arguments.IsInstantiated(kFunctions)) { | 2856 if (type_arguments.IsInstantiated(kFunctions)) { |
| 2827 function_type_args = BuildNullValue(token_pos); | 2857 function_type_args = BuildNullValue(token_pos); |
| 2828 } else { | 2858 } else { |
| 2829 function_type_args = BuildFunctionTypeArguments(token_pos); | 2859 function_type_args = BuildFunctionTypeArguments(token_pos); |
| 2830 } | 2860 } |
| 2831 return Bind(new (Z) InstantiateTypeArgumentsInstr( | 2861 return Bind(new (Z) InstantiateTypeArgumentsInstr( |
| 2832 token_pos, type_arguments, instantiator_class, instantiator_type_args, | 2862 token_pos, type_arguments, instantiator_class, instantiator_type_args, |
| 2833 function_type_args)); | 2863 function_type_args, owner()->GetNextDeoptId())); |
| 2834 } | 2864 } |
| 2835 | 2865 |
| 2836 | 2866 |
| 2837 void ValueGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) { | 2867 void ValueGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) { |
| 2838 if (node->constructor().IsFactory()) { | 2868 if (node->constructor().IsFactory()) { |
| 2839 EffectGraphVisitor::VisitConstructorCallNode(node); | 2869 EffectGraphVisitor::VisitConstructorCallNode(node); |
| 2840 return; | 2870 return; |
| 2841 } | 2871 } |
| 2842 | 2872 |
| 2843 // t_n contains the allocated and initialized object. | 2873 // t_n contains the allocated and initialized object. |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2912 Do(BuildStoreExprTemp(for_receiver.value(), node->token_pos())); | 2942 Do(BuildStoreExprTemp(for_receiver.value(), node->token_pos())); |
| 2913 BuildInstanceGetterConditional(node); | 2943 BuildInstanceGetterConditional(node); |
| 2914 } else { | 2944 } else { |
| 2915 PushArgumentInstr* push_receiver = PushArgument(for_receiver.value()); | 2945 PushArgumentInstr* push_receiver = PushArgument(for_receiver.value()); |
| 2916 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 2946 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 2917 new (Z) ZoneGrowableArray<PushArgumentInstr*>(1); | 2947 new (Z) ZoneGrowableArray<PushArgumentInstr*>(1); |
| 2918 arguments->Add(push_receiver); | 2948 arguments->Add(push_receiver); |
| 2919 const String& name = | 2949 const String& name = |
| 2920 String::ZoneHandle(Z, Field::GetterSymbol(node->field_name())); | 2950 String::ZoneHandle(Z, Field::GetterSymbol(node->field_name())); |
| 2921 const intptr_t kTypeArgsLen = 0; | 2951 const intptr_t kTypeArgsLen = 0; |
| 2922 InstanceCallInstr* call = new (Z) InstanceCallInstr( | 2952 InstanceCallInstr* call = new (Z) |
| 2923 node->token_pos(), name, Token::kGET, arguments, kTypeArgsLen, | 2953 InstanceCallInstr(node->token_pos(), name, Token::kGET, arguments, |
| 2924 Object::null_array(), 1, owner()->ic_data_array()); | 2954 kTypeArgsLen, Object::null_array(), 1, |
| 2955 owner()->ic_data_array(), owner()->GetNextDeoptId()); |
| 2925 ReturnDefinition(call); | 2956 ReturnDefinition(call); |
| 2926 } | 2957 } |
| 2927 } | 2958 } |
| 2928 | 2959 |
| 2929 | 2960 |
| 2930 void EffectGraphVisitor::BuildInstanceSetterArguments( | 2961 void EffectGraphVisitor::BuildInstanceSetterArguments( |
| 2931 InstanceSetterNode* node, | 2962 InstanceSetterNode* node, |
| 2932 ZoneGrowableArray<PushArgumentInstr*>* arguments, | 2963 ZoneGrowableArray<PushArgumentInstr*>* arguments, |
| 2933 bool result_is_needed) { | 2964 bool result_is_needed) { |
| 2934 ValueGraphVisitor for_receiver(owner()); | 2965 ValueGraphVisitor for_receiver(owner()); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2976 Join(for_test, for_true, for_false); | 3007 Join(for_test, for_true, for_false); |
| 2977 return; | 3008 return; |
| 2978 } | 3009 } |
| 2979 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 3010 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 2980 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); | 3011 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
| 2981 BuildInstanceSetterArguments(node, arguments, kResultNotNeeded); | 3012 BuildInstanceSetterArguments(node, arguments, kResultNotNeeded); |
| 2982 const String& name = | 3013 const String& name = |
| 2983 String::ZoneHandle(Z, Field::SetterSymbol(node->field_name())); | 3014 String::ZoneHandle(Z, Field::SetterSymbol(node->field_name())); |
| 2984 const int kTypeArgsLen = 0; | 3015 const int kTypeArgsLen = 0; |
| 2985 const intptr_t kNumArgsChecked = 1; // Do not check value type. | 3016 const intptr_t kNumArgsChecked = 1; // Do not check value type. |
| 2986 InstanceCallInstr* call = new (Z) InstanceCallInstr( | 3017 InstanceCallInstr* call = new (Z) |
| 2987 token_pos, name, Token::kSET, arguments, kTypeArgsLen, | 3018 InstanceCallInstr(token_pos, name, Token::kSET, arguments, kTypeArgsLen, |
| 2988 Object::null_array(), kNumArgsChecked, owner()->ic_data_array()); | 3019 Object::null_array(), kNumArgsChecked, |
| 3020 owner()->ic_data_array(), owner()->GetNextDeoptId()); |
| 2989 ReturnDefinition(call); | 3021 ReturnDefinition(call); |
| 2990 } | 3022 } |
| 2991 | 3023 |
| 2992 | 3024 |
| 2993 void ValueGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) { | 3025 void ValueGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) { |
| 2994 const TokenPosition token_pos = node->token_pos(); | 3026 const TokenPosition token_pos = node->token_pos(); |
| 2995 if (node->is_conditional()) { | 3027 if (node->is_conditional()) { |
| 2996 ValueGraphVisitor for_receiver(owner()); | 3028 ValueGraphVisitor for_receiver(owner()); |
| 2997 node->receiver()->Visit(&for_receiver); | 3029 node->receiver()->Visit(&for_receiver); |
| 2998 Append(for_receiver); | 3030 Append(for_receiver); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3023 } | 3055 } |
| 3024 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 3056 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 3025 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); | 3057 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
| 3026 BuildInstanceSetterArguments(node, arguments, kResultNeeded); | 3058 BuildInstanceSetterArguments(node, arguments, kResultNeeded); |
| 3027 const String& name = | 3059 const String& name = |
| 3028 String::ZoneHandle(Z, Field::SetterSymbol(node->field_name())); | 3060 String::ZoneHandle(Z, Field::SetterSymbol(node->field_name())); |
| 3029 const intptr_t kTypeArgsLen = 0; | 3061 const intptr_t kTypeArgsLen = 0; |
| 3030 const intptr_t kNumArgsChecked = 1; // Do not check value type. | 3062 const intptr_t kNumArgsChecked = 1; // Do not check value type. |
| 3031 Do(new (Z) InstanceCallInstr(token_pos, name, Token::kSET, arguments, | 3063 Do(new (Z) InstanceCallInstr(token_pos, name, Token::kSET, arguments, |
| 3032 kTypeArgsLen, Object::null_array(), | 3064 kTypeArgsLen, Object::null_array(), |
| 3033 kNumArgsChecked, owner()->ic_data_array())); | 3065 kNumArgsChecked, owner()->ic_data_array(), |
| 3066 owner()->GetNextDeoptId())); |
| 3034 ReturnDefinition(BuildLoadExprTemp(token_pos)); | 3067 ReturnDefinition(BuildLoadExprTemp(token_pos)); |
| 3035 } | 3068 } |
| 3036 | 3069 |
| 3037 | 3070 |
| 3038 void EffectGraphVisitor::VisitStaticGetterNode(StaticGetterNode* node) { | 3071 void EffectGraphVisitor::VisitStaticGetterNode(StaticGetterNode* node) { |
| 3039 const String& getter_name = | 3072 const String& getter_name = |
| 3040 String::ZoneHandle(Z, Field::GetterSymbol(node->field_name())); | 3073 String::ZoneHandle(Z, Field::GetterSymbol(node->field_name())); |
| 3041 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 3074 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 3042 new (Z) ZoneGrowableArray<PushArgumentInstr*>(); | 3075 new (Z) ZoneGrowableArray<PushArgumentInstr*>(); |
| 3043 Function& getter_function = Function::ZoneHandle(Z, Function::null()); | 3076 Function& getter_function = Function::ZoneHandle(Z, Function::null()); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3086 InvocationMirror::EncodeType(node->cls().IsTopLevel() | 3119 InvocationMirror::EncodeType(node->cls().IsTopLevel() |
| 3087 ? InvocationMirror::kTopLevel | 3120 ? InvocationMirror::kTopLevel |
| 3088 : InvocationMirror::kStatic, | 3121 : InvocationMirror::kStatic, |
| 3089 InvocationMirror::kGetter)); | 3122 InvocationMirror::kGetter)); |
| 3090 ReturnDefinition(call); | 3123 ReturnDefinition(call); |
| 3091 return; | 3124 return; |
| 3092 } | 3125 } |
| 3093 } | 3126 } |
| 3094 ASSERT(!getter_function.IsNull()); | 3127 ASSERT(!getter_function.IsNull()); |
| 3095 const intptr_t kTypeArgsLen = 0; | 3128 const intptr_t kTypeArgsLen = 0; |
| 3096 StaticCallInstr* call = | 3129 StaticCallInstr* call = new (Z) StaticCallInstr( |
| 3097 new (Z) StaticCallInstr(node->token_pos(), getter_function, kTypeArgsLen, | 3130 node->token_pos(), getter_function, kTypeArgsLen, |
| 3098 Object::null_array(), // No names | 3131 Object::null_array(), // No names |
| 3099 arguments, owner()->ic_data_array()); | 3132 arguments, owner()->ic_data_array(), owner()->GetNextDeoptId()); |
| 3100 ReturnDefinition(call); | 3133 ReturnDefinition(call); |
| 3101 } | 3134 } |
| 3102 | 3135 |
| 3103 | 3136 |
| 3104 void EffectGraphVisitor::BuildStaticSetter(StaticSetterNode* node, | 3137 void EffectGraphVisitor::BuildStaticSetter(StaticSetterNode* node, |
| 3105 bool result_is_needed) { | 3138 bool result_is_needed) { |
| 3106 const String& setter_name = | 3139 const String& setter_name = |
| 3107 String::ZoneHandle(Z, Field::SetterSymbol(node->field_name())); | 3140 String::ZoneHandle(Z, Field::SetterSymbol(node->field_name())); |
| 3108 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 3141 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 3109 new (Z) ZoneGrowableArray<PushArgumentInstr*>(1); | 3142 new (Z) ZoneGrowableArray<PushArgumentInstr*>(1); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3151 Value* value = NULL; | 3184 Value* value = NULL; |
| 3152 if (result_is_needed) { | 3185 if (result_is_needed) { |
| 3153 value = Bind(BuildStoreExprTemp(for_value.value(), token_pos)); | 3186 value = Bind(BuildStoreExprTemp(for_value.value(), token_pos)); |
| 3154 } else { | 3187 } else { |
| 3155 value = for_value.value(); | 3188 value = for_value.value(); |
| 3156 } | 3189 } |
| 3157 arguments->Add(PushArgument(value)); | 3190 arguments->Add(PushArgument(value)); |
| 3158 const intptr_t kTypeArgsLen = 0; | 3191 const intptr_t kTypeArgsLen = 0; |
| 3159 call = new (Z) StaticCallInstr(token_pos, setter_function, kTypeArgsLen, | 3192 call = new (Z) StaticCallInstr(token_pos, setter_function, kTypeArgsLen, |
| 3160 Object::null_array(), // No names. | 3193 Object::null_array(), // No names. |
| 3161 arguments, owner()->ic_data_array()); | 3194 arguments, owner()->ic_data_array(), |
| 3195 owner()->GetNextDeoptId()); |
| 3162 } | 3196 } |
| 3163 if (result_is_needed) { | 3197 if (result_is_needed) { |
| 3164 Do(call); | 3198 Do(call); |
| 3165 ReturnDefinition(BuildLoadExprTemp(token_pos)); | 3199 ReturnDefinition(BuildLoadExprTemp(token_pos)); |
| 3166 } else { | 3200 } else { |
| 3167 ReturnDefinition(call); | 3201 ReturnDefinition(call); |
| 3168 } | 3202 } |
| 3169 } | 3203 } |
| 3170 | 3204 |
| 3171 | 3205 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3243 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function); | 3277 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function); |
| 3244 switch (kind) { | 3278 switch (kind) { |
| 3245 case MethodRecognizer::kObjectEquals: { | 3279 case MethodRecognizer::kObjectEquals: { |
| 3246 Value* receiver = Bind(BuildLoadThisVar(node->scope(), token_pos)); | 3280 Value* receiver = Bind(BuildLoadThisVar(node->scope(), token_pos)); |
| 3247 LocalVariable* other_var = | 3281 LocalVariable* other_var = |
| 3248 node->scope()->LookupVariable(Symbols::Other(), | 3282 node->scope()->LookupVariable(Symbols::Other(), |
| 3249 true); // Test only. | 3283 true); // Test only. |
| 3250 Value* other = Bind(new (Z) LoadLocalInstr(*other_var, token_pos)); | 3284 Value* other = Bind(new (Z) LoadLocalInstr(*other_var, token_pos)); |
| 3251 // Receiver is not a number because numbers override equality. | 3285 // Receiver is not a number because numbers override equality. |
| 3252 const bool kNoNumberCheck = false; | 3286 const bool kNoNumberCheck = false; |
| 3253 StrictCompareInstr* compare = new (Z) StrictCompareInstr( | 3287 StrictCompareInstr* compare = new (Z) |
| 3254 token_pos, Token::kEQ_STRICT, receiver, other, kNoNumberCheck); | 3288 StrictCompareInstr(token_pos, Token::kEQ_STRICT, receiver, other, |
| 3289 kNoNumberCheck, owner()->GetNextDeoptId()); |
| 3255 return ReturnDefinition(compare); | 3290 return ReturnDefinition(compare); |
| 3256 } | 3291 } |
| 3257 case MethodRecognizer::kStringBaseLength: | 3292 case MethodRecognizer::kStringBaseLength: |
| 3258 case MethodRecognizer::kStringBaseIsEmpty: { | 3293 case MethodRecognizer::kStringBaseIsEmpty: { |
| 3259 // Treat length loads as mutable (i.e. affected by side effects) to | 3294 // Treat length loads as mutable (i.e. affected by side effects) to |
| 3260 // avoid hoisting them since we can't hoist the preceding class-check. | 3295 // avoid hoisting them since we can't hoist the preceding class-check. |
| 3261 // This is because of externalization of strings that affects their | 3296 // This is because of externalization of strings that affects their |
| 3262 // class-id. | 3297 // class-id. |
| 3263 LoadFieldInstr* load = BuildNativeGetter( | 3298 LoadFieldInstr* load = BuildNativeGetter( |
| 3264 node, MethodRecognizer::kStringBaseLength, String::length_offset(), | 3299 node, MethodRecognizer::kStringBaseLength, String::length_offset(), |
| 3265 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid); | 3300 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid); |
| 3266 load->set_is_immutable(!FLAG_support_externalizable_strings); | 3301 load->set_is_immutable(!FLAG_support_externalizable_strings); |
| 3267 if (kind == MethodRecognizer::kStringBaseLength) { | 3302 if (kind == MethodRecognizer::kStringBaseLength) { |
| 3268 return ReturnDefinition(load); | 3303 return ReturnDefinition(load); |
| 3269 } | 3304 } |
| 3270 ASSERT(kind == MethodRecognizer::kStringBaseIsEmpty); | 3305 ASSERT(kind == MethodRecognizer::kStringBaseIsEmpty); |
| 3271 Value* zero_val = | 3306 Value* zero_val = |
| 3272 Bind(new (Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(0)))); | 3307 Bind(new (Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(0)))); |
| 3273 Value* load_val = Bind(load); | 3308 Value* load_val = Bind(load); |
| 3274 StrictCompareInstr* compare = new (Z) | 3309 StrictCompareInstr* compare = new (Z) StrictCompareInstr( |
| 3275 StrictCompareInstr(token_pos, Token::kEQ_STRICT, load_val, zero_val, | 3310 token_pos, Token::kEQ_STRICT, load_val, zero_val, false, |
| 3276 false); // No number check. | 3311 owner()->GetNextDeoptId()); // No number check. |
| 3277 return ReturnDefinition(compare); | 3312 return ReturnDefinition(compare); |
| 3278 } | 3313 } |
| 3279 case MethodRecognizer::kGrowableArrayLength: | 3314 case MethodRecognizer::kGrowableArrayLength: |
| 3280 case MethodRecognizer::kObjectArrayLength: | 3315 case MethodRecognizer::kObjectArrayLength: |
| 3281 case MethodRecognizer::kImmutableArrayLength: | 3316 case MethodRecognizer::kImmutableArrayLength: |
| 3282 case MethodRecognizer::kTypedDataLength: { | 3317 case MethodRecognizer::kTypedDataLength: { |
| 3283 LoadFieldInstr* load = | 3318 LoadFieldInstr* load = |
| 3284 BuildNativeGetter(node, kind, OffsetForLengthGetter(kind), | 3319 BuildNativeGetter(node, kind, OffsetForLengthGetter(kind), |
| 3285 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid); | 3320 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid); |
| 3286 load->set_is_immutable(kind != MethodRecognizer::kGrowableArrayLength); | 3321 load->set_is_immutable(kind != MethodRecognizer::kGrowableArrayLength); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 3309 } | 3344 } |
| 3310 case MethodRecognizer::kObjectArrayAllocate: { | 3345 case MethodRecognizer::kObjectArrayAllocate: { |
| 3311 LocalVariable* type_args_parameter = node->scope()->LookupVariable( | 3346 LocalVariable* type_args_parameter = node->scope()->LookupVariable( |
| 3312 Symbols::TypeArgumentsParameter(), true); | 3347 Symbols::TypeArgumentsParameter(), true); |
| 3313 Value* element_type = | 3348 Value* element_type = |
| 3314 Bind(new (Z) LoadLocalInstr(*type_args_parameter, token_pos)); | 3349 Bind(new (Z) LoadLocalInstr(*type_args_parameter, token_pos)); |
| 3315 LocalVariable* length_parameter = | 3350 LocalVariable* length_parameter = |
| 3316 node->scope()->LookupVariable(Symbols::Length(), true); | 3351 node->scope()->LookupVariable(Symbols::Length(), true); |
| 3317 Value* length = | 3352 Value* length = |
| 3318 Bind(new (Z) LoadLocalInstr(*length_parameter, token_pos)); | 3353 Bind(new (Z) LoadLocalInstr(*length_parameter, token_pos)); |
| 3319 CreateArrayInstr* create_array = | 3354 CreateArrayInstr* create_array = new CreateArrayInstr( |
| 3320 new CreateArrayInstr(token_pos, element_type, length); | 3355 token_pos, element_type, length, owner()->GetNextDeoptId()); |
| 3321 return ReturnDefinition(create_array); | 3356 return ReturnDefinition(create_array); |
| 3322 } | 3357 } |
| 3323 case MethodRecognizer::kBigint_getDigits: { | 3358 case MethodRecognizer::kBigint_getDigits: { |
| 3324 return ReturnDefinition(BuildNativeGetter( | 3359 return ReturnDefinition(BuildNativeGetter( |
| 3325 node, kind, Bigint::digits_offset(), Object::dynamic_type(), | 3360 node, kind, Bigint::digits_offset(), Object::dynamic_type(), |
| 3326 kTypedDataUint32ArrayCid)); | 3361 kTypedDataUint32ArrayCid)); |
| 3327 } | 3362 } |
| 3328 case MethodRecognizer::kBigint_getUsed: { | 3363 case MethodRecognizer::kBigint_getUsed: { |
| 3329 return ReturnDefinition( | 3364 return ReturnDefinition( |
| 3330 BuildNativeGetter(node, kind, Bigint::used_offset(), | 3365 BuildNativeGetter(node, kind, Bigint::used_offset(), |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3600 ValueGraphVisitor for_index(owner()); | 3635 ValueGraphVisitor for_index(owner()); |
| 3601 node->index_expr()->Visit(&for_index); | 3636 node->index_expr()->Visit(&for_index); |
| 3602 Append(for_index); | 3637 Append(for_index); |
| 3603 arguments->Add(PushArgument(for_index.value())); | 3638 arguments->Add(PushArgument(for_index.value())); |
| 3604 | 3639 |
| 3605 const intptr_t kTypeArgsLen = 0; | 3640 const intptr_t kTypeArgsLen = 0; |
| 3606 if (super_function != NULL) { | 3641 if (super_function != NULL) { |
| 3607 // Generate static call to super operator. | 3642 // Generate static call to super operator. |
| 3608 StaticCallInstr* load = new (Z) StaticCallInstr( | 3643 StaticCallInstr* load = new (Z) StaticCallInstr( |
| 3609 node->token_pos(), *super_function, kTypeArgsLen, Object::null_array(), | 3644 node->token_pos(), *super_function, kTypeArgsLen, Object::null_array(), |
| 3610 arguments, owner()->ic_data_array()); | 3645 arguments, owner()->ic_data_array(), owner()->GetNextDeoptId()); |
| 3611 ReturnDefinition(load); | 3646 ReturnDefinition(load); |
| 3612 } else { | 3647 } else { |
| 3613 // Generate dynamic call to index operator. | 3648 // Generate dynamic call to index operator. |
| 3614 const intptr_t checked_argument_count = 1; | 3649 const intptr_t checked_argument_count = 1; |
| 3615 InstanceCallInstr* load = new (Z) InstanceCallInstr( | 3650 InstanceCallInstr* load = new (Z) InstanceCallInstr( |
| 3616 node->token_pos(), Symbols::IndexToken(), Token::kINDEX, arguments, | 3651 node->token_pos(), Symbols::IndexToken(), Token::kINDEX, arguments, |
| 3617 kTypeArgsLen, Object::null_array(), checked_argument_count, | 3652 kTypeArgsLen, Object::null_array(), checked_argument_count, |
| 3618 owner()->ic_data_array()); | 3653 owner()->ic_data_array(), owner()->GetNextDeoptId()); |
| 3619 ReturnDefinition(load); | 3654 ReturnDefinition(load); |
| 3620 } | 3655 } |
| 3621 } | 3656 } |
| 3622 | 3657 |
| 3623 | 3658 |
| 3624 Definition* EffectGraphVisitor::BuildStoreIndexedValues(StoreIndexedNode* node, | 3659 Definition* EffectGraphVisitor::BuildStoreIndexedValues(StoreIndexedNode* node, |
| 3625 bool result_is_needed) { | 3660 bool result_is_needed) { |
| 3626 Function* super_function = NULL; | 3661 Function* super_function = NULL; |
| 3627 const TokenPosition token_pos = node->token_pos(); | 3662 const TokenPosition token_pos = node->token_pos(); |
| 3628 if (node->IsSuperStore()) { | 3663 if (node->IsSuperStore()) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3674 value = for_value.value(); | 3709 value = for_value.value(); |
| 3675 } | 3710 } |
| 3676 arguments->Add(PushArgument(value)); | 3711 arguments->Add(PushArgument(value)); |
| 3677 | 3712 |
| 3678 const intptr_t kTypeArgsLen = 0; | 3713 const intptr_t kTypeArgsLen = 0; |
| 3679 if (super_function != NULL) { | 3714 if (super_function != NULL) { |
| 3680 // Generate static call to super operator []=. | 3715 // Generate static call to super operator []=. |
| 3681 | 3716 |
| 3682 StaticCallInstr* store = new (Z) StaticCallInstr( | 3717 StaticCallInstr* store = new (Z) StaticCallInstr( |
| 3683 token_pos, *super_function, kTypeArgsLen, Object::null_array(), | 3718 token_pos, *super_function, kTypeArgsLen, Object::null_array(), |
| 3684 arguments, owner()->ic_data_array()); | 3719 arguments, owner()->ic_data_array(), owner()->GetNextDeoptId()); |
| 3685 if (result_is_needed) { | 3720 if (result_is_needed) { |
| 3686 Do(store); | 3721 Do(store); |
| 3687 return BuildLoadExprTemp(token_pos); | 3722 return BuildLoadExprTemp(token_pos); |
| 3688 } else { | 3723 } else { |
| 3689 return store; | 3724 return store; |
| 3690 } | 3725 } |
| 3691 } else { | 3726 } else { |
| 3692 // Generate dynamic call to operator []=. | 3727 // Generate dynamic call to operator []=. |
| 3693 const intptr_t checked_argument_count = 2; // Do not check for value type. | 3728 const intptr_t checked_argument_count = 2; // Do not check for value type. |
| 3694 InstanceCallInstr* store = new (Z) InstanceCallInstr( | 3729 InstanceCallInstr* store = new (Z) InstanceCallInstr( |
| 3695 token_pos, Symbols::AssignIndexToken(), Token::kASSIGN_INDEX, arguments, | 3730 token_pos, Symbols::AssignIndexToken(), Token::kASSIGN_INDEX, arguments, |
| 3696 kTypeArgsLen, Object::null_array(), checked_argument_count, | 3731 kTypeArgsLen, Object::null_array(), checked_argument_count, |
| 3697 owner()->ic_data_array()); | 3732 owner()->ic_data_array(), owner()->GetNextDeoptId()); |
| 3698 if (result_is_needed) { | 3733 if (result_is_needed) { |
| 3699 Do(store); | 3734 Do(store); |
| 3700 return BuildLoadExprTemp(token_pos); | 3735 return BuildLoadExprTemp(token_pos); |
| 3701 } else { | 3736 } else { |
| 3702 return store; | 3737 return store; |
| 3703 } | 3738 } |
| 3704 } | 3739 } |
| 3705 } | 3740 } |
| 3706 | 3741 |
| 3707 | 3742 |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3858 // Setup arguments for _asyncSetThreadStackTrace. | 3893 // Setup arguments for _asyncSetThreadStackTrace. |
| 3859 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 3894 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 3860 new (Z) ZoneGrowableArray<PushArgumentInstr*>(1); | 3895 new (Z) ZoneGrowableArray<PushArgumentInstr*>(1); |
| 3861 arguments->Add(PushArgument(async_stack_trace_value)); | 3896 arguments->Add(PushArgument(async_stack_trace_value)); |
| 3862 | 3897 |
| 3863 const Function& async_set_thread_stack_trace = Function::ZoneHandle( | 3898 const Function& async_set_thread_stack_trace = Function::ZoneHandle( |
| 3864 Z, isolate()->object_store()->async_set_thread_stack_trace()); | 3899 Z, isolate()->object_store()->async_set_thread_stack_trace()); |
| 3865 ASSERT(!async_set_thread_stack_trace.IsNull()); | 3900 ASSERT(!async_set_thread_stack_trace.IsNull()); |
| 3866 // Call _asyncSetThreadStackTrace | 3901 // Call _asyncSetThreadStackTrace |
| 3867 const intptr_t kTypeArgsLen = 0; | 3902 const intptr_t kTypeArgsLen = 0; |
| 3868 StaticCallInstr* call_async_set_thread_stack_trace = | 3903 StaticCallInstr* call_async_set_thread_stack_trace = new (Z) |
| 3869 new (Z) StaticCallInstr(node->token_pos().ToSynthetic(), | 3904 StaticCallInstr(node->token_pos().ToSynthetic(), |
| 3870 async_set_thread_stack_trace, kTypeArgsLen, | 3905 async_set_thread_stack_trace, kTypeArgsLen, |
| 3871 Object::null_array(), arguments, | 3906 Object::null_array(), arguments, |
| 3872 owner()->ic_data_array()); | 3907 owner()->ic_data_array(), owner()->GetNextDeoptId()); |
| 3873 Do(call_async_set_thread_stack_trace); | 3908 Do(call_async_set_thread_stack_trace); |
| 3874 } | 3909 } |
| 3875 | 3910 |
| 3876 | 3911 |
| 3877 if (FLAG_support_debugger && is_top_level_sequence && | 3912 if (FLAG_support_debugger && is_top_level_sequence && |
| 3878 function.is_debuggable()) { | 3913 function.is_debuggable()) { |
| 3879 // Place a debug check at method entry to ensure breaking on a method always | 3914 // Place a debug check at method entry to ensure breaking on a method always |
| 3880 // happens, even if there are no assignments/calls/runtimecalls in the first | 3915 // happens, even if there are no assignments/calls/runtimecalls in the first |
| 3881 // basic block. Place this check at the last parameter to ensure parameters | 3916 // basic block. Place this check at the last parameter to ensure parameters |
| 3882 // are in scope in the debugger at method entry. | 3917 // are in scope in the debugger at method entry. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3896 new (Z) DebugStepCheckInstr(check_pos, RawPcDescriptors::kRuntimeCall)); | 3931 new (Z) DebugStepCheckInstr(check_pos, RawPcDescriptors::kRuntimeCall)); |
| 3897 } | 3932 } |
| 3898 | 3933 |
| 3899 // This check may be deleted if the generated code is leaf. | 3934 // This check may be deleted if the generated code is leaf. |
| 3900 // Native functions don't need a stack check at entry. | 3935 // Native functions don't need a stack check at entry. |
| 3901 if (is_top_level_sequence && !function.is_native()) { | 3936 if (is_top_level_sequence && !function.is_native()) { |
| 3902 // Always allocate CheckOverflowInstr so that deopt-ids match regardless | 3937 // Always allocate CheckOverflowInstr so that deopt-ids match regardless |
| 3903 // if we inline or not. | 3938 // if we inline or not. |
| 3904 if (!function.IsImplicitGetterFunction() && | 3939 if (!function.IsImplicitGetterFunction() && |
| 3905 !function.IsImplicitSetterFunction()) { | 3940 !function.IsImplicitSetterFunction()) { |
| 3906 CheckStackOverflowInstr* check = | 3941 CheckStackOverflowInstr* check = new (Z) CheckStackOverflowInstr( |
| 3907 new (Z) CheckStackOverflowInstr(node->token_pos(), 0); | 3942 node->token_pos(), 0, owner()->GetNextDeoptId()); |
| 3908 // If we are inlining don't actually attach the stack check. We must still | 3943 // If we are inlining don't actually attach the stack check. We must still |
| 3909 // create the stack check in order to allocate a deopt id. | 3944 // create the stack check in order to allocate a deopt id. |
| 3910 if (!owner()->IsInlining()) { | 3945 if (!owner()->IsInlining()) { |
| 3911 AddInstruction(check); | 3946 AddInstruction(check); |
| 3912 } | 3947 } |
| 3913 } | 3948 } |
| 3914 } | 3949 } |
| 3915 | 3950 |
| 3916 if (Isolate::Current()->type_checks() && is_top_level_sequence) { | 3951 if (Isolate::Current()->type_checks() && is_top_level_sequence) { |
| 3917 const int num_params = function.NumParameters(); | 3952 const int num_params = function.NumParameters(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3937 } | 3972 } |
| 3938 | 3973 |
| 3939 // Continuation part: | 3974 // Continuation part: |
| 3940 // If this node sequence is the body of a function with continuations, | 3975 // If this node sequence is the body of a function with continuations, |
| 3941 // leave room for a preamble. | 3976 // leave room for a preamble. |
| 3942 // The preamble is generated after visiting the body. | 3977 // The preamble is generated after visiting the body. |
| 3943 GotoInstr* preamble_start = NULL; | 3978 GotoInstr* preamble_start = NULL; |
| 3944 if (is_top_level_sequence && | 3979 if (is_top_level_sequence && |
| 3945 (function.IsAsyncClosure() || function.IsSyncGenClosure() || | 3980 (function.IsAsyncClosure() || function.IsSyncGenClosure() || |
| 3946 function.IsAsyncGenClosure())) { | 3981 function.IsAsyncGenClosure())) { |
| 3947 JoinEntryInstr* preamble_end = new (Z) | 3982 JoinEntryInstr* preamble_end = |
| 3948 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 3983 new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(), |
| 3984 owner()->GetNextDeoptId()); |
| 3949 ASSERT(exit() != NULL); | 3985 ASSERT(exit() != NULL); |
| 3950 exit()->Goto(preamble_end); | 3986 exit()->Goto(preamble_end); |
| 3951 ASSERT(exit()->next()->IsGoto()); | 3987 ASSERT(exit()->next()->IsGoto()); |
| 3952 preamble_start = exit()->next()->AsGoto(); | 3988 preamble_start = exit()->next()->AsGoto(); |
| 3953 ASSERT(preamble_start->IsGoto()); | 3989 ASSERT(preamble_start->IsGoto()); |
| 3954 exit_ = preamble_end; | 3990 exit_ = preamble_end; |
| 3955 } | 3991 } |
| 3956 | 3992 |
| 3957 intptr_t i = 0; | 3993 intptr_t i = 0; |
| 3958 while (is_open() && (i < node->length())) { | 3994 while (is_open() && (i < node->length())) { |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4080 owner()->set_try_index(try_handler_index); | 4116 owner()->set_try_index(try_handler_index); |
| 4081 | 4117 |
| 4082 // Preserve current context into local variable ':saved_try_context_var'. | 4118 // Preserve current context into local variable ':saved_try_context_var'. |
| 4083 BuildSaveContext(node->context_var(), ST(node->token_pos())); | 4119 BuildSaveContext(node->context_var(), ST(node->token_pos())); |
| 4084 | 4120 |
| 4085 EffectGraphVisitor for_try(owner()); | 4121 EffectGraphVisitor for_try(owner()); |
| 4086 node->try_block()->Visit(&for_try); | 4122 node->try_block()->Visit(&for_try); |
| 4087 | 4123 |
| 4088 if (for_try.is_open()) { | 4124 if (for_try.is_open()) { |
| 4089 JoinEntryInstr* after_try = new (Z) | 4125 JoinEntryInstr* after_try = new (Z) |
| 4090 JoinEntryInstr(owner()->AllocateBlockId(), original_handler_index); | 4126 JoinEntryInstr(owner()->AllocateBlockId(), original_handler_index, |
| 4127 owner()->GetNextDeoptId()); |
| 4091 for_try.Goto(after_try); | 4128 for_try.Goto(after_try); |
| 4092 for_try.exit_ = after_try; | 4129 for_try.exit_ = after_try; |
| 4093 } | 4130 } |
| 4094 | 4131 |
| 4095 JoinEntryInstr* try_entry = | 4132 JoinEntryInstr* try_entry = new (Z) JoinEntryInstr( |
| 4096 new (Z) JoinEntryInstr(owner()->AllocateBlockId(), try_handler_index); | 4133 owner()->AllocateBlockId(), try_handler_index, owner()->GetNextDeoptId()); |
| 4097 | 4134 |
| 4098 Goto(try_entry); | 4135 Goto(try_entry); |
| 4099 AppendFragment(try_entry, for_try); | 4136 AppendFragment(try_entry, for_try); |
| 4100 exit_ = for_try.exit_; | 4137 exit_ = for_try.exit_; |
| 4101 | 4138 |
| 4102 // We are done generating code for the try block. | 4139 // We are done generating code for the try block. |
| 4103 owner()->set_try_index(original_handler_index); | 4140 owner()->set_try_index(original_handler_index); |
| 4104 | 4141 |
| 4105 // If there is a finally block, it is the handler for code in the catch | 4142 // If there is a finally block, it is the handler for code in the catch |
| 4106 // block. | 4143 // block. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 4126 catch_block->token_pos(), (node->token_pos() == TokenPosition::kNoSource), | 4163 catch_block->token_pos(), (node->token_pos() == TokenPosition::kNoSource), |
| 4127 owner()->AllocateBlockId(), catch_handler_index, owner()->graph_entry(), | 4164 owner()->AllocateBlockId(), catch_handler_index, owner()->graph_entry(), |
| 4128 catch_block->handler_types(), try_handler_index, | 4165 catch_block->handler_types(), try_handler_index, |
| 4129 catch_block->exception_var(), catch_block->stacktrace_var(), | 4166 catch_block->exception_var(), catch_block->stacktrace_var(), |
| 4130 catch_block->needs_stacktrace(), Thread::Current()->GetNextDeoptId()); | 4167 catch_block->needs_stacktrace(), Thread::Current()->GetNextDeoptId()); |
| 4131 owner()->AddCatchEntry(catch_entry); | 4168 owner()->AddCatchEntry(catch_entry); |
| 4132 AppendFragment(catch_entry, for_catch); | 4169 AppendFragment(catch_entry, for_catch); |
| 4133 | 4170 |
| 4134 if (for_catch.is_open()) { | 4171 if (for_catch.is_open()) { |
| 4135 JoinEntryInstr* join = new (Z) | 4172 JoinEntryInstr* join = new (Z) |
| 4136 JoinEntryInstr(owner()->AllocateBlockId(), original_handler_index); | 4173 JoinEntryInstr(owner()->AllocateBlockId(), original_handler_index, |
| 4174 owner()->GetNextDeoptId()); |
| 4137 for_catch.Goto(join); | 4175 for_catch.Goto(join); |
| 4138 if (is_open()) Goto(join); | 4176 if (is_open()) Goto(join); |
| 4139 exit_ = join; | 4177 exit_ = join; |
| 4140 } | 4178 } |
| 4141 | 4179 |
| 4142 if (finally_block != NULL) { | 4180 if (finally_block != NULL) { |
| 4143 ASSERT(node->rethrow_clause() != NULL); | 4181 ASSERT(node->rethrow_clause() != NULL); |
| 4144 // Create a handler for the code in the catch block, containing the | 4182 // Create a handler for the code in the catch block, containing the |
| 4145 // code in the finally block. | 4183 // code in the finally block. |
| 4146 owner()->set_try_index(original_handler_index); | 4184 owner()->set_try_index(original_handler_index); |
| 4147 EffectGraphVisitor for_finally(owner()); | 4185 EffectGraphVisitor for_finally(owner()); |
| 4148 for_finally.BuildRestoreContext(catch_block->context_var(), | 4186 for_finally.BuildRestoreContext(catch_block->context_var(), |
| 4149 finally_block->token_pos()); | 4187 finally_block->token_pos()); |
| 4150 | 4188 |
| 4151 node->rethrow_clause()->Visit(&for_finally); | 4189 node->rethrow_clause()->Visit(&for_finally); |
| 4152 if (for_finally.is_open()) { | 4190 if (for_finally.is_open()) { |
| 4153 // Rethrow the exception. Manually build the graph for rethrow. | 4191 // Rethrow the exception. Manually build the graph for rethrow. |
| 4154 Value* exception = for_finally.Bind(for_finally.BuildLoadLocal( | 4192 Value* exception = for_finally.Bind(for_finally.BuildLoadLocal( |
| 4155 catch_block->rethrow_exception_var(), finally_block->token_pos())); | 4193 catch_block->rethrow_exception_var(), finally_block->token_pos())); |
| 4156 for_finally.PushArgument(exception); | 4194 for_finally.PushArgument(exception); |
| 4157 Value* stacktrace = for_finally.Bind(for_finally.BuildLoadLocal( | 4195 Value* stacktrace = for_finally.Bind(for_finally.BuildLoadLocal( |
| 4158 catch_block->rethrow_stacktrace_var(), finally_block->token_pos())); | 4196 catch_block->rethrow_stacktrace_var(), finally_block->token_pos())); |
| 4159 for_finally.PushArgument(stacktrace); | 4197 for_finally.PushArgument(stacktrace); |
| 4160 for_finally.AddInstruction( | 4198 for_finally.AddInstruction( |
| 4161 new (Z) ReThrowInstr(catch_block->token_pos(), catch_handler_index)); | 4199 new (Z) ReThrowInstr(catch_block->token_pos(), catch_handler_index, |
| 4200 owner()->GetNextDeoptId())); |
| 4162 for_finally.CloseFragment(); | 4201 for_finally.CloseFragment(); |
| 4163 } | 4202 } |
| 4164 ASSERT(!for_finally.is_open()); | 4203 ASSERT(!for_finally.is_open()); |
| 4165 | 4204 |
| 4166 const Array& types = Array::ZoneHandle(Z, Array::New(1, Heap::kOld)); | 4205 const Array& types = Array::ZoneHandle(Z, Array::New(1, Heap::kOld)); |
| 4167 types.SetAt(0, Object::dynamic_type()); | 4206 types.SetAt(0, Object::dynamic_type()); |
| 4168 CatchBlockEntryInstr* finally_entry = new (Z) CatchBlockEntryInstr( | 4207 CatchBlockEntryInstr* finally_entry = new (Z) CatchBlockEntryInstr( |
| 4169 finally_block->token_pos(), | 4208 finally_block->token_pos(), |
| 4170 true, // this is not a catch block from user code. | 4209 true, // this is not a catch block from user code. |
| 4171 owner()->AllocateBlockId(), original_handler_index, | 4210 owner()->AllocateBlockId(), original_handler_index, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4214 const Class& object_class = | 4253 const Class& object_class = |
| 4215 Class::ZoneHandle(Z, isolate()->object_store()->object_class()); | 4254 Class::ZoneHandle(Z, isolate()->object_store()->object_class()); |
| 4216 no_such_method_func = Resolver::ResolveDynamicForReceiverClass( | 4255 no_such_method_func = Resolver::ResolveDynamicForReceiverClass( |
| 4217 object_class, Symbols::NoSuchMethod(), args_desc); | 4256 object_class, Symbols::NoSuchMethod(), args_desc); |
| 4218 } | 4257 } |
| 4219 // We are guaranteed to find noSuchMethod of class Object. | 4258 // We are guaranteed to find noSuchMethod of class Object. |
| 4220 ASSERT(!no_such_method_func.IsNull()); | 4259 ASSERT(!no_such_method_func.IsNull()); |
| 4221 ZoneGrowableArray<PushArgumentInstr*>* push_arguments = | 4260 ZoneGrowableArray<PushArgumentInstr*>* push_arguments = |
| 4222 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); | 4261 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
| 4223 BuildPushArguments(*args, push_arguments); | 4262 BuildPushArguments(*args, push_arguments); |
| 4224 return new (Z) StaticCallInstr(args_pos, no_such_method_func, kTypeArgsLen, | 4263 return new (Z) StaticCallInstr( |
| 4225 Object::null_array(), push_arguments, | 4264 args_pos, no_such_method_func, kTypeArgsLen, Object::null_array(), |
| 4226 owner()->ic_data_array()); | 4265 push_arguments, owner()->ic_data_array(), owner()->GetNextDeoptId()); |
| 4227 } | 4266 } |
| 4228 | 4267 |
| 4229 | 4268 |
| 4230 StaticCallInstr* EffectGraphVisitor::BuildThrowNoSuchMethodError( | 4269 StaticCallInstr* EffectGraphVisitor::BuildThrowNoSuchMethodError( |
| 4231 TokenPosition token_pos, | 4270 TokenPosition token_pos, |
| 4232 const Class& function_class, | 4271 const Class& function_class, |
| 4233 const String& function_name, | 4272 const String& function_name, |
| 4234 ArgumentListNode* function_arguments, | 4273 ArgumentListNode* function_arguments, |
| 4235 int invocation_type) { | 4274 int invocation_type) { |
| 4236 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 4275 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4282 Class::Handle(Z, core_lib.LookupClass(Symbols::NoSuchMethodError())); | 4321 Class::Handle(Z, core_lib.LookupClass(Symbols::NoSuchMethodError())); |
| 4283 ASSERT(!cls.IsNull()); | 4322 ASSERT(!cls.IsNull()); |
| 4284 const intptr_t kTypeArgsLen = 0; | 4323 const intptr_t kTypeArgsLen = 0; |
| 4285 const Function& func = Function::ZoneHandle( | 4324 const Function& func = Function::ZoneHandle( |
| 4286 Z, Resolver::ResolveStatic( | 4325 Z, Resolver::ResolveStatic( |
| 4287 cls, Library::PrivateCoreLibName(Symbols::ThrowNew()), | 4326 cls, Library::PrivateCoreLibName(Symbols::ThrowNew()), |
| 4288 kTypeArgsLen, arguments->length(), Object::null_array())); | 4327 kTypeArgsLen, arguments->length(), Object::null_array())); |
| 4289 ASSERT(!func.IsNull()); | 4328 ASSERT(!func.IsNull()); |
| 4290 return new (Z) StaticCallInstr(token_pos, func, kTypeArgsLen, | 4329 return new (Z) StaticCallInstr(token_pos, func, kTypeArgsLen, |
| 4291 Object::null_array(), // No names. | 4330 Object::null_array(), // No names. |
| 4292 arguments, owner()->ic_data_array()); | 4331 arguments, owner()->ic_data_array(), |
| 4332 owner()->GetNextDeoptId()); |
| 4293 } | 4333 } |
| 4294 | 4334 |
| 4295 | 4335 |
| 4296 void EffectGraphVisitor::BuildThrowNode(ThrowNode* node) { | 4336 void EffectGraphVisitor::BuildThrowNode(ThrowNode* node) { |
| 4297 if (FLAG_support_debugger) { | 4337 if (FLAG_support_debugger) { |
| 4298 if (node->exception()->IsLiteralNode() || | 4338 if (node->exception()->IsLiteralNode() || |
| 4299 node->exception()->IsLoadLocalNode() || | 4339 node->exception()->IsLoadLocalNode() || |
| 4300 node->exception()->IsLoadStaticFieldNode() || | 4340 node->exception()->IsLoadStaticFieldNode() || |
| 4301 node->exception()->IsClosureNode()) { | 4341 node->exception()->IsClosureNode()) { |
| 4302 AddInstruction(new (Z) DebugStepCheckInstr( | 4342 AddInstruction(new (Z) DebugStepCheckInstr( |
| 4303 node->token_pos(), RawPcDescriptors::kRuntimeCall)); | 4343 node->token_pos(), RawPcDescriptors::kRuntimeCall)); |
| 4304 } | 4344 } |
| 4305 } | 4345 } |
| 4306 ValueGraphVisitor for_exception(owner()); | 4346 ValueGraphVisitor for_exception(owner()); |
| 4307 node->exception()->Visit(&for_exception); | 4347 node->exception()->Visit(&for_exception); |
| 4308 Append(for_exception); | 4348 Append(for_exception); |
| 4309 PushArgument(for_exception.value()); | 4349 PushArgument(for_exception.value()); |
| 4310 Instruction* instr = NULL; | 4350 Instruction* instr = NULL; |
| 4311 if (node->stacktrace() == NULL) { | 4351 if (node->stacktrace() == NULL) { |
| 4312 instr = new (Z) ThrowInstr(node->token_pos()); | 4352 instr = new (Z) ThrowInstr(node->token_pos(), owner()->GetNextDeoptId()); |
| 4313 } else { | 4353 } else { |
| 4314 ValueGraphVisitor for_stack_trace(owner()); | 4354 ValueGraphVisitor for_stack_trace(owner()); |
| 4315 node->stacktrace()->Visit(&for_stack_trace); | 4355 node->stacktrace()->Visit(&for_stack_trace); |
| 4316 Append(for_stack_trace); | 4356 Append(for_stack_trace); |
| 4317 PushArgument(for_stack_trace.value()); | 4357 PushArgument(for_stack_trace.value()); |
| 4318 instr = new (Z) ReThrowInstr(node->token_pos(), owner()->catch_try_index()); | 4358 instr = new (Z) ReThrowInstr(node->token_pos(), owner()->catch_try_index(), |
| 4359 owner()->GetNextDeoptId()); |
| 4319 } | 4360 } |
| 4320 AddInstruction(instr); | 4361 AddInstruction(instr); |
| 4321 } | 4362 } |
| 4322 | 4363 |
| 4323 | 4364 |
| 4324 void EffectGraphVisitor::VisitThrowNode(ThrowNode* node) { | 4365 void EffectGraphVisitor::VisitThrowNode(ThrowNode* node) { |
| 4325 BuildThrowNode(node); | 4366 BuildThrowNode(node); |
| 4326 CloseFragment(); | 4367 CloseFragment(); |
| 4327 } | 4368 } |
| 4328 | 4369 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 4348 owner()->set_try_index(outer_try_index); | 4389 owner()->set_try_index(outer_try_index); |
| 4349 } | 4390 } |
| 4350 | 4391 |
| 4351 // Note: do not restore the saved_try_context here since the inlined | 4392 // Note: do not restore the saved_try_context here since the inlined |
| 4352 // code is not reached via an exception handler, therefore the context is | 4393 // code is not reached via an exception handler, therefore the context is |
| 4353 // always properly set on entry. In other words, the inlined finally clause is | 4394 // always properly set on entry. In other words, the inlined finally clause is |
| 4354 // never the target of a long jump that would find an uninitialized current | 4395 // never the target of a long jump that would find an uninitialized current |
| 4355 // context variable. | 4396 // context variable. |
| 4356 | 4397 |
| 4357 JoinEntryInstr* finally_entry = | 4398 JoinEntryInstr* finally_entry = |
| 4358 new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 4399 new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(), |
| 4400 owner()->GetNextDeoptId()); |
| 4359 EffectGraphVisitor for_finally_block(owner()); | 4401 EffectGraphVisitor for_finally_block(owner()); |
| 4360 for_finally_block.AdjustContextLevel(node->finally_block()->scope()); | 4402 for_finally_block.AdjustContextLevel(node->finally_block()->scope()); |
| 4361 node->finally_block()->Visit(&for_finally_block); | 4403 node->finally_block()->Visit(&for_finally_block); |
| 4362 | 4404 |
| 4363 if (try_index >= 0) { | 4405 if (try_index >= 0) { |
| 4364 owner()->set_try_index(try_index); | 4406 owner()->set_try_index(try_index); |
| 4365 } | 4407 } |
| 4366 | 4408 |
| 4367 if (for_finally_block.is_open()) { | 4409 if (for_finally_block.is_open()) { |
| 4368 JoinEntryInstr* after_finally = new (Z) | 4410 JoinEntryInstr* after_finally = |
| 4369 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 4411 new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(), |
| 4412 owner()->GetNextDeoptId()); |
| 4370 for_finally_block.Goto(after_finally); | 4413 for_finally_block.Goto(after_finally); |
| 4371 for_finally_block.exit_ = after_finally; | 4414 for_finally_block.exit_ = after_finally; |
| 4372 } | 4415 } |
| 4373 | 4416 |
| 4374 Goto(finally_entry); | 4417 Goto(finally_entry); |
| 4375 AppendFragment(finally_entry, for_finally_block); | 4418 AppendFragment(finally_entry, for_finally_block); |
| 4376 exit_ = for_finally_block.exit_; | 4419 exit_ = for_finally_block.exit_; |
| 4377 } | 4420 } |
| 4378 | 4421 |
| 4379 | 4422 |
| 4380 void EffectGraphVisitor::VisitStopNode(StopNode* node) { | 4423 void EffectGraphVisitor::VisitStopNode(StopNode* node) { |
| 4381 AddInstruction(new (Z) StopInstr(node->message())); | 4424 AddInstruction(new (Z) StopInstr(node->message())); |
| 4382 } | 4425 } |
| 4383 | 4426 |
| 4384 | 4427 |
| 4385 FlowGraph* FlowGraphBuilder::BuildGraph() { | 4428 FlowGraph* FlowGraphBuilder::BuildGraph() { |
| 4386 VMTagScope tagScope(thread(), VMTag::kCompileFlowGraphBuilderTagId, | 4429 VMTagScope tagScope(thread(), VMTag::kCompileFlowGraphBuilderTagId, |
| 4387 FLAG_profile_vm); | 4430 FLAG_profile_vm); |
| 4388 if (FLAG_support_ast_printer && FLAG_print_ast && | 4431 if (FLAG_support_ast_printer && FLAG_print_ast && |
| 4389 FlowGraphPrinter::ShouldPrint(parsed_function().function())) { | 4432 FlowGraphPrinter::ShouldPrint(parsed_function().function())) { |
| 4390 // Print the function ast before IL generation. | 4433 // Print the function ast before IL generation. |
| 4391 AstPrinter ast_printer; | 4434 AstPrinter ast_printer; |
| 4392 ast_printer.PrintFunctionNodes(parsed_function()); | 4435 ast_printer.PrintFunctionNodes(parsed_function()); |
| 4393 } | 4436 } |
| 4394 if (FLAG_support_ast_printer && FLAG_print_scopes && | 4437 if (FLAG_support_ast_printer && FLAG_print_scopes && |
| 4395 FlowGraphPrinter::ShouldPrint(parsed_function().function())) { | 4438 FlowGraphPrinter::ShouldPrint(parsed_function().function())) { |
| 4396 AstPrinter ast_printer; | 4439 AstPrinter ast_printer; |
| 4397 ast_printer.PrintFunctionScope(parsed_function()); | 4440 ast_printer.PrintFunctionScope(parsed_function()); |
| 4398 } | 4441 } |
| 4399 TargetEntryInstr* normal_entry = new (Z) | 4442 TargetEntryInstr* normal_entry = new (Z) TargetEntryInstr( |
| 4400 TargetEntryInstr(AllocateBlockId(), CatchClauseNode::kInvalidTryIndex); | 4443 AllocateBlockId(), CatchClauseNode::kInvalidTryIndex, GetNextDeoptId()); |
| 4401 graph_entry_ = | 4444 graph_entry_ = |
| 4402 new (Z) GraphEntryInstr(parsed_function(), normal_entry, osr_id_); | 4445 new (Z) GraphEntryInstr(parsed_function(), normal_entry, osr_id_); |
| 4403 EffectGraphVisitor for_effect(this); | 4446 EffectGraphVisitor for_effect(this); |
| 4404 parsed_function().node_sequence()->Visit(&for_effect); | 4447 parsed_function().node_sequence()->Visit(&for_effect); |
| 4405 AppendFragment(normal_entry, for_effect); | 4448 AppendFragment(normal_entry, for_effect); |
| 4406 // Check that the graph is properly terminated. | 4449 // Check that the graph is properly terminated. |
| 4407 ASSERT(!for_effect.is_open()); | 4450 ASSERT(!for_effect.is_open()); |
| 4408 | 4451 |
| 4409 // When compiling for OSR, use a depth first search to prune instructions | 4452 // When compiling for OSR, use a depth first search to prune instructions |
| 4410 // unreachable from the OSR entry. Catch entries are always considered | 4453 // unreachable from the OSR entry. Catch entries are always considered |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4449 ASSERT(type.HasResolvedTypeClass()); | 4492 ASSERT(type.HasResolvedTypeClass()); |
| 4450 const Class& type_class = Class::Handle(type.type_class()); | 4493 const Class& type_class = Class::Handle(type.type_class()); |
| 4451 // Bail if the type has any type parameters. | 4494 // Bail if the type has any type parameters. |
| 4452 if (type_class.IsGeneric()) return false; | 4495 if (type_class.IsGeneric()) return false; |
| 4453 | 4496 |
| 4454 // Finally a simple class for instance of checking. | 4497 // Finally a simple class for instance of checking. |
| 4455 return true; | 4498 return true; |
| 4456 } | 4499 } |
| 4457 | 4500 |
| 4458 } // namespace dart | 4501 } // namespace dart |
| OLD | NEW |