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