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 "vm/ast_printer.h" | 7 #include "vm/ast_printer.h" |
8 #include "vm/code_descriptors.h" | 8 #include "vm/code_descriptors.h" |
9 #include "vm/dart_entry.h" | 9 #include "vm/dart_entry.h" |
10 #include "vm/flags.h" | 10 #include "vm/flags.h" |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 // and a pair of effect graph fragments with zero or one available exits. | 142 // and a pair of effect graph fragments with zero or one available exits. |
143 // We want to append the branch and (if necessary) a join node to this | 143 // We want to append the branch and (if necessary) a join node to this |
144 // graph fragment. | 144 // graph fragment. |
145 ASSERT(is_open()); | 145 ASSERT(is_open()); |
146 | 146 |
147 // 1. Connect the test to this graph. | 147 // 1. Connect the test to this graph. |
148 Append(test_fragment); | 148 Append(test_fragment); |
149 | 149 |
150 // 2. Connect the true and false bodies to the test and record their exits | 150 // 2. Connect the true and false bodies to the test and record their exits |
151 // (if any). | 151 // (if any). |
152 TargetEntryInstr* true_entry = new TargetEntryInstr(); | 152 TargetEntryInstr* true_entry = new TargetEntryInstr(owner()->try_index()); |
153 *test_fragment.true_successor_address() = true_entry; | 153 *test_fragment.true_successor_address() = true_entry; |
154 Instruction* true_exit = AppendFragment(true_entry, true_fragment); | 154 Instruction* true_exit = AppendFragment(true_entry, true_fragment); |
155 | 155 |
156 TargetEntryInstr* false_entry = new TargetEntryInstr(); | 156 TargetEntryInstr* false_entry = new TargetEntryInstr(owner()->try_index()); |
157 *test_fragment.false_successor_address() = false_entry; | 157 *test_fragment.false_successor_address() = false_entry; |
158 Instruction* false_exit = AppendFragment(false_entry, false_fragment); | 158 Instruction* false_exit = AppendFragment(false_entry, false_fragment); |
159 | 159 |
160 // 3. Add a join or select one (or neither) of the arms as exit. | 160 // 3. Add a join or select one (or neither) of the arms as exit. |
161 if (true_exit == NULL) { | 161 if (true_exit == NULL) { |
162 exit_ = false_exit; // May be NULL. | 162 exit_ = false_exit; // May be NULL. |
163 if (false_exit != NULL) temp_index_ = false_fragment.temp_index(); | 163 if (false_exit != NULL) temp_index_ = false_fragment.temp_index(); |
164 } else if (false_exit == NULL) { | 164 } else if (false_exit == NULL) { |
165 exit_ = true_exit; | 165 exit_ = true_exit; |
166 temp_index_ = true_fragment.temp_index(); | 166 temp_index_ = true_fragment.temp_index(); |
167 } else { | 167 } else { |
168 JoinEntryInstr* join = new JoinEntryInstr(); | 168 JoinEntryInstr* join = new JoinEntryInstr(owner()->try_index()); |
169 true_exit->Goto(join); | 169 true_exit->Goto(join); |
170 false_exit->Goto(join); | 170 false_exit->Goto(join); |
171 exit_ = join; | 171 exit_ = join; |
172 ASSERT(true_fragment.temp_index() == false_fragment.temp_index()); | 172 ASSERT(true_fragment.temp_index() == false_fragment.temp_index()); |
173 temp_index_ = true_fragment.temp_index(); | 173 temp_index_ = true_fragment.temp_index(); |
174 } | 174 } |
175 } | 175 } |
176 | 176 |
177 | 177 |
178 void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment, | 178 void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment, |
179 const EffectGraphVisitor& body_fragment) { | 179 const EffectGraphVisitor& body_fragment) { |
180 // We have: a test graph fragment with zero, one, or two available exits; | 180 // We have: a test graph fragment with zero, one, or two available exits; |
181 // and an effect graph fragment with zero or one available exits. We want | 181 // and an effect graph fragment with zero or one available exits. We want |
182 // to append the 'while loop' consisting of the test graph fragment as | 182 // to append the 'while loop' consisting of the test graph fragment as |
183 // condition and the effect graph fragment as body. | 183 // condition and the effect graph fragment as body. |
184 ASSERT(is_open()); | 184 ASSERT(is_open()); |
185 | 185 |
186 // 1. Connect the body to the test if it is reachable, and if so record | 186 // 1. Connect the body to the test if it is reachable, and if so record |
187 // its exit (if any). | 187 // its exit (if any). |
188 TargetEntryInstr* body_entry = new TargetEntryInstr(); | 188 TargetEntryInstr* body_entry = new TargetEntryInstr(owner()->try_index()); |
189 *test_fragment.true_successor_address() = body_entry; | 189 *test_fragment.true_successor_address() = body_entry; |
190 Instruction* body_exit = AppendFragment(body_entry, body_fragment); | 190 Instruction* body_exit = AppendFragment(body_entry, body_fragment); |
191 | 191 |
192 // 2. Connect the test to this graph, including the body if reachable and | 192 // 2. Connect the test to this graph, including the body if reachable and |
193 // using a fresh join node if the body is reachable and has an open exit. | 193 // using a fresh join node if the body is reachable and has an open exit. |
194 if (body_exit == NULL) { | 194 if (body_exit == NULL) { |
195 Append(test_fragment); | 195 Append(test_fragment); |
196 } else { | 196 } else { |
197 JoinEntryInstr* join = new JoinEntryInstr(); | 197 JoinEntryInstr* join = new JoinEntryInstr(owner()->try_index()); |
198 join->set_next(test_fragment.entry()); | 198 join->set_next(test_fragment.entry()); |
199 Goto(join); | 199 Goto(join); |
200 body_exit->Goto(join); | 200 body_exit->Goto(join); |
201 } | 201 } |
202 | 202 |
203 // 3. Set the exit to the graph to be the false successor of the test, a | 203 // 3. Set the exit to the graph to be the false successor of the test, a |
204 // fresh target node | 204 // fresh target node |
205 exit_ = *test_fragment.false_successor_address() = new TargetEntryInstr(); | 205 exit_ = *test_fragment.false_successor_address() = |
| 206 new TargetEntryInstr(owner()->try_index()); |
206 } | 207 } |
207 | 208 |
208 | 209 |
209 PushArgumentInstr* EffectGraphVisitor::PushArgument(Value* value) { | 210 PushArgumentInstr* EffectGraphVisitor::PushArgument(Value* value) { |
210 PushArgumentInstr* result = new PushArgumentInstr(value); | 211 PushArgumentInstr* result = new PushArgumentInstr(value); |
211 AddInstruction(result); | 212 AddInstruction(result); |
212 return result; | 213 return result; |
213 } | 214 } |
214 | 215 |
215 | 216 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 | 264 |
264 // Loads context saved in 'context_variable' into the current context. | 265 // Loads context saved in 'context_variable' into the current context. |
265 void EffectGraphVisitor::BuildLoadContext(const LocalVariable& variable) { | 266 void EffectGraphVisitor::BuildLoadContext(const LocalVariable& variable) { |
266 Value* load_saved_context = Bind(BuildLoadLocal(variable)); | 267 Value* load_saved_context = Bind(BuildLoadLocal(variable)); |
267 Do(new StoreContextComp(load_saved_context)); | 268 Do(new StoreContextComp(load_saved_context)); |
268 } | 269 } |
269 | 270 |
270 | 271 |
271 void TestGraphVisitor::ReturnValue(Value* value) { | 272 void TestGraphVisitor::ReturnValue(Value* value) { |
272 if (FLAG_enable_type_checks) { | 273 if (FLAG_enable_type_checks) { |
273 value = Bind(new AssertBooleanComp(condition_token_pos(), | 274 value = Bind(new AssertBooleanComp(condition_token_pos(), value)); |
274 owner()->try_index(), | |
275 value)); | |
276 } | 275 } |
277 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 276 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
278 Value* constant_true = Bind(Constant(bool_true)); | 277 Value* constant_true = Bind(Constant(bool_true)); |
279 StrictCompareComp* comp = | 278 StrictCompareComp* comp = |
280 new StrictCompareComp(Token::kEQ_STRICT, value, constant_true); | 279 new StrictCompareComp(Token::kEQ_STRICT, value, constant_true); |
281 BranchInstr* branch = new BranchInstr(comp); | 280 BranchInstr* branch = new BranchInstr(comp); |
282 AddInstruction(branch); | 281 AddInstruction(branch); |
283 CloseFragment(); | 282 CloseFragment(); |
284 true_successor_address_ = branch->true_successor_address(); | 283 true_successor_address_ = branch->true_successor_address(); |
285 false_successor_address_ = branch->false_successor_address(); | 284 false_successor_address_ = branch->false_successor_address(); |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 node->right()->Visit(&for_right_value); | 515 node->right()->Visit(&for_right_value); |
517 Append(for_right_value); | 516 Append(for_right_value); |
518 PushArgumentInstr* push_right = PushArgument(for_right_value.value()); | 517 PushArgumentInstr* push_right = PushArgument(for_right_value.value()); |
519 | 518 |
520 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 519 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
521 new ZoneGrowableArray<PushArgumentInstr*>(2); | 520 new ZoneGrowableArray<PushArgumentInstr*>(2); |
522 arguments->Add(push_left); | 521 arguments->Add(push_left); |
523 arguments->Add(push_right); | 522 arguments->Add(push_right); |
524 const String& name = String::ZoneHandle(Symbols::New(node->Name())); | 523 const String& name = String::ZoneHandle(Symbols::New(node->Name())); |
525 InstanceCallComp* call = new InstanceCallComp(node->token_pos(), | 524 InstanceCallComp* call = new InstanceCallComp(node->token_pos(), |
526 owner()->try_index(), | |
527 name, | 525 name, |
528 node->kind(), | 526 node->kind(), |
529 arguments, | 527 arguments, |
530 Array::ZoneHandle(), | 528 Array::ZoneHandle(), |
531 2); | 529 2); |
532 ReturnComputation(call); | 530 ReturnComputation(call); |
533 } | 531 } |
534 | 532 |
535 | 533 |
536 // Special handling for AND/OR. | 534 // Special handling for AND/OR. |
(...skipping 12 matching lines...) Expand all Loading... |
549 temp_index(), | 547 temp_index(), |
550 node->left()->token_pos()); | 548 node->left()->token_pos()); |
551 node->left()->Visit(&for_test); | 549 node->left()->Visit(&for_test); |
552 | 550 |
553 ValueGraphVisitor for_right(owner(), temp_index()); | 551 ValueGraphVisitor for_right(owner(), temp_index()); |
554 node->right()->Visit(&for_right); | 552 node->right()->Visit(&for_right); |
555 Value* right_value = for_right.value(); | 553 Value* right_value = for_right.value(); |
556 if (FLAG_enable_type_checks) { | 554 if (FLAG_enable_type_checks) { |
557 right_value = | 555 right_value = |
558 for_right.Bind(new AssertBooleanComp(node->right()->token_pos(), | 556 for_right.Bind(new AssertBooleanComp(node->right()->token_pos(), |
559 owner()->try_index(), | |
560 right_value)); | 557 right_value)); |
561 } | 558 } |
562 Value* constant_true = for_right.Bind(Constant(bool_true)); | 559 Value* constant_true = for_right.Bind(Constant(bool_true)); |
563 Value* compare = | 560 Value* compare = |
564 for_right.Bind(new StrictCompareComp(Token::kEQ_STRICT, | 561 for_right.Bind(new StrictCompareComp(Token::kEQ_STRICT, |
565 right_value, | 562 right_value, |
566 constant_true)); | 563 constant_true)); |
567 for_right.Do(BuildStoreLocal( | 564 for_right.Do(BuildStoreLocal( |
568 *owner()->parsed_function().expression_temp_var(), | 565 *owner()->parsed_function().expression_temp_var(), |
569 compare)); | 566 compare)); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
638 Value* instantiator_type_arguments = NULL; | 635 Value* instantiator_type_arguments = NULL; |
639 if (dst_type.IsInstantiated()) { | 636 if (dst_type.IsInstantiated()) { |
640 instantiator = BuildNullValue(); | 637 instantiator = BuildNullValue(); |
641 instantiator_type_arguments = BuildNullValue(); | 638 instantiator_type_arguments = BuildNullValue(); |
642 } else { | 639 } else { |
643 BuildTypecheckArguments(token_pos, | 640 BuildTypecheckArguments(token_pos, |
644 &instantiator, | 641 &instantiator, |
645 &instantiator_type_arguments); | 642 &instantiator_type_arguments); |
646 } | 643 } |
647 return new AssertAssignableComp(token_pos, | 644 return new AssertAssignableComp(token_pos, |
648 owner()->try_index(), | |
649 value, | 645 value, |
650 instantiator, | 646 instantiator, |
651 instantiator_type_arguments, | 647 instantiator_type_arguments, |
652 dst_type, | 648 dst_type, |
653 dst_name); | 649 dst_name); |
654 } | 650 } |
655 | 651 |
656 | 652 |
657 // Used for type casts and to test assignments. | 653 // Used for type casts and to test assignments. |
658 Value* EffectGraphVisitor::BuildAssignableValue(intptr_t token_pos, | 654 Value* EffectGraphVisitor::BuildAssignableValue(intptr_t token_pos, |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
740 if (type.IsInstantiated()) { | 736 if (type.IsInstantiated()) { |
741 instantiator = BuildNullValue(); | 737 instantiator = BuildNullValue(); |
742 instantiator_type_arguments = BuildNullValue(); | 738 instantiator_type_arguments = BuildNullValue(); |
743 } else { | 739 } else { |
744 BuildTypecheckArguments(node->token_pos(), | 740 BuildTypecheckArguments(node->token_pos(), |
745 &instantiator, | 741 &instantiator, |
746 &instantiator_type_arguments); | 742 &instantiator_type_arguments); |
747 } | 743 } |
748 InstanceOfComp* instance_of = | 744 InstanceOfComp* instance_of = |
749 new InstanceOfComp(node->token_pos(), | 745 new InstanceOfComp(node->token_pos(), |
750 owner()->try_index(), | |
751 for_left_value.value(), | 746 for_left_value.value(), |
752 instantiator, | 747 instantiator, |
753 instantiator_type_arguments, | 748 instantiator_type_arguments, |
754 node->right()->AsTypeNode()->type(), | 749 node->right()->AsTypeNode()->type(), |
755 (node->kind() == Token::kISNOT)); | 750 (node->kind() == Token::kISNOT)); |
756 ReturnComputation(instance_of); | 751 ReturnComputation(instance_of); |
757 } | 752 } |
758 | 753 |
759 | 754 |
760 void ValueGraphVisitor::BuildTypeCast(ComparisonNode* node) { | 755 void ValueGraphVisitor::BuildTypeCast(ComparisonNode* node) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
802 | 797 |
803 if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) { | 798 if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) { |
804 ValueGraphVisitor for_left_value(owner(), temp_index()); | 799 ValueGraphVisitor for_left_value(owner(), temp_index()); |
805 node->left()->Visit(&for_left_value); | 800 node->left()->Visit(&for_left_value); |
806 Append(for_left_value); | 801 Append(for_left_value); |
807 ValueGraphVisitor for_right_value(owner(), temp_index()); | 802 ValueGraphVisitor for_right_value(owner(), temp_index()); |
808 node->right()->Visit(&for_right_value); | 803 node->right()->Visit(&for_right_value); |
809 Append(for_right_value); | 804 Append(for_right_value); |
810 if (FLAG_enable_type_checks) { | 805 if (FLAG_enable_type_checks) { |
811 EqualityCompareComp* comp = new EqualityCompareComp( | 806 EqualityCompareComp* comp = new EqualityCompareComp( |
812 node->token_pos(), owner()->try_index(), | 807 node->token_pos(), |
813 Token::kEQ, for_left_value.value(), for_right_value.value()); | 808 Token::kEQ, |
| 809 for_left_value.value(), |
| 810 for_right_value.value()); |
814 if (node->kind() == Token::kEQ) { | 811 if (node->kind() == Token::kEQ) { |
815 ReturnComputation(comp); | 812 ReturnComputation(comp); |
816 } else { | 813 } else { |
817 Value* eq_result = Bind(comp); | 814 Value* eq_result = Bind(comp); |
818 eq_result = Bind(new AssertBooleanComp(node->token_pos(), | 815 eq_result = Bind(new AssertBooleanComp(node->token_pos(), eq_result)); |
819 owner()->try_index(), | |
820 eq_result)); | |
821 ReturnComputation(new BooleanNegateComp(eq_result)); | 816 ReturnComputation(new BooleanNegateComp(eq_result)); |
822 } | 817 } |
823 } else { | 818 } else { |
824 EqualityCompareComp* comp = new EqualityCompareComp( | 819 EqualityCompareComp* comp = new EqualityCompareComp( |
825 node->token_pos(), owner()->try_index(), | 820 node->token_pos(), |
826 node->kind(), for_left_value.value(), for_right_value.value()); | 821 node->kind(), |
| 822 for_left_value.value(), |
| 823 for_right_value.value()); |
827 ReturnComputation(comp); | 824 ReturnComputation(comp); |
828 } | 825 } |
829 return; | 826 return; |
830 } | 827 } |
831 | 828 |
832 ValueGraphVisitor for_left_value(owner(), temp_index()); | 829 ValueGraphVisitor for_left_value(owner(), temp_index()); |
833 node->left()->Visit(&for_left_value); | 830 node->left()->Visit(&for_left_value); |
834 Append(for_left_value); | 831 Append(for_left_value); |
835 ValueGraphVisitor for_right_value(owner(), temp_index()); | 832 ValueGraphVisitor for_right_value(owner(), temp_index()); |
836 node->right()->Visit(&for_right_value); | 833 node->right()->Visit(&for_right_value); |
837 Append(for_right_value); | 834 Append(for_right_value); |
838 RelationalOpComp* comp = new RelationalOpComp(node->token_pos(), | 835 RelationalOpComp* comp = new RelationalOpComp(node->token_pos(), |
839 owner()->try_index(), | |
840 node->kind(), | 836 node->kind(), |
841 for_left_value.value(), | 837 for_left_value.value(), |
842 for_right_value.value()); | 838 for_right_value.value()); |
843 ReturnComputation(comp); | 839 ReturnComputation(comp); |
844 } | 840 } |
845 | 841 |
846 | 842 |
847 void EffectGraphVisitor::VisitUnaryOpNode(UnaryOpNode* node) { | 843 void EffectGraphVisitor::VisitUnaryOpNode(UnaryOpNode* node) { |
848 // "!" cannot be overloaded, therefore do not call operator. | 844 // "!" cannot be overloaded, therefore do not call operator. |
849 if (node->kind() == Token::kNOT) { | 845 if (node->kind() == Token::kNOT) { |
850 ValueGraphVisitor for_value(owner(), temp_index()); | 846 ValueGraphVisitor for_value(owner(), temp_index()); |
851 node->operand()->Visit(&for_value); | 847 node->operand()->Visit(&for_value); |
852 Append(for_value); | 848 Append(for_value); |
853 Value* value = for_value.value(); | 849 Value* value = for_value.value(); |
854 if (FLAG_enable_type_checks) { | 850 if (FLAG_enable_type_checks) { |
855 value = | 851 value = |
856 Bind(new AssertBooleanComp(node->operand()->token_pos(), | 852 Bind(new AssertBooleanComp(node->operand()->token_pos(), value)); |
857 owner()->try_index(), | |
858 value)); | |
859 } | 853 } |
860 BooleanNegateComp* negate = new BooleanNegateComp(value); | 854 BooleanNegateComp* negate = new BooleanNegateComp(value); |
861 ReturnComputation(negate); | 855 ReturnComputation(negate); |
862 return; | 856 return; |
863 } | 857 } |
864 ValueGraphVisitor for_value(owner(), temp_index()); | 858 ValueGraphVisitor for_value(owner(), temp_index()); |
865 node->operand()->Visit(&for_value); | 859 node->operand()->Visit(&for_value); |
866 Append(for_value); | 860 Append(for_value); |
867 PushArgumentInstr* push_value = PushArgument(for_value.value()); | 861 PushArgumentInstr* push_value = PushArgument(for_value.value()); |
868 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 862 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
869 new ZoneGrowableArray<PushArgumentInstr*>(1); | 863 new ZoneGrowableArray<PushArgumentInstr*>(1); |
870 arguments->Add(push_value); | 864 arguments->Add(push_value); |
871 String& name = String::ZoneHandle(); | 865 String& name = String::ZoneHandle(); |
872 if (node->kind() == Token::kSUB) { | 866 if (node->kind() == Token::kSUB) { |
873 name = Symbols::New("unary-"); | 867 name = Symbols::New("unary-"); |
874 } else { | 868 } else { |
875 name = Symbols::New(Token::Str(node->kind())); | 869 name = Symbols::New(Token::Str(node->kind())); |
876 } | 870 } |
877 InstanceCallComp* call = new InstanceCallComp( | 871 InstanceCallComp* call = new InstanceCallComp( |
878 node->token_pos(), owner()->try_index(), name, node->kind(), | 872 node->token_pos(), name, node->kind(), |
879 arguments, Array::ZoneHandle(), 1); | 873 arguments, Array::ZoneHandle(), 1); |
880 ReturnComputation(call); | 874 ReturnComputation(call); |
881 } | 875 } |
882 | 876 |
883 | 877 |
884 void EffectGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) { | 878 void EffectGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) { |
885 TestGraphVisitor for_test(owner(), | 879 TestGraphVisitor for_test(owner(), |
886 temp_index(), | 880 temp_index(), |
887 node->condition()->token_pos()); | 881 node->condition()->token_pos()); |
888 node->condition()->Visit(&for_test); | 882 node->condition()->Visit(&for_test); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
980 const intptr_t len = node->case_expressions()->length(); | 974 const intptr_t len = node->case_expressions()->length(); |
981 // Create case statements instructions. | 975 // Create case statements instructions. |
982 EffectGraphVisitor for_case_statements(owner(), temp_index()); | 976 EffectGraphVisitor for_case_statements(owner(), temp_index()); |
983 // Compute start of statements fragment. | 977 // Compute start of statements fragment. |
984 JoinEntryInstr* statement_start = NULL; | 978 JoinEntryInstr* statement_start = NULL; |
985 if ((node->label() != NULL) && node->label()->is_continue_target()) { | 979 if ((node->label() != NULL) && node->label()->is_continue_target()) { |
986 // Since a labeled jump continue statement occur in a different case node, | 980 // Since a labeled jump continue statement occur in a different case node, |
987 // allocate JoinNode here and use it as statement start. | 981 // allocate JoinNode here and use it as statement start. |
988 statement_start = node->label()->join_for_continue(); | 982 statement_start = node->label()->join_for_continue(); |
989 if (statement_start == NULL) { | 983 if (statement_start == NULL) { |
990 statement_start = new JoinEntryInstr(); | 984 statement_start = new JoinEntryInstr(owner()->try_index()); |
991 node->label()->set_join_for_continue(statement_start); | 985 node->label()->set_join_for_continue(statement_start); |
992 } | 986 } |
993 } else { | 987 } else { |
994 statement_start = new JoinEntryInstr(); | 988 statement_start = new JoinEntryInstr(owner()->try_index()); |
995 } | 989 } |
996 node->statements()->Visit(&for_case_statements); | 990 node->statements()->Visit(&for_case_statements); |
997 Instruction* statement_exit = | 991 Instruction* statement_exit = |
998 AppendFragment(statement_start, for_case_statements); | 992 AppendFragment(statement_start, for_case_statements); |
999 if (is_open() && (len == 0)) { | 993 if (is_open() && (len == 0)) { |
1000 ASSERT(node->contains_default()); | 994 ASSERT(node->contains_default()); |
1001 // Default only case node. | 995 // Default only case node. |
1002 Goto(statement_start); | 996 Goto(statement_start); |
1003 exit_ = statement_exit; | 997 exit_ = statement_exit; |
1004 return; | 998 return; |
1005 } | 999 } |
1006 | 1000 |
1007 // Generate instructions for all case expressions. | 1001 // Generate instructions for all case expressions. |
1008 TargetEntryInstr** previous_false_address = NULL; | 1002 TargetEntryInstr** previous_false_address = NULL; |
1009 for (intptr_t i = 0; i < len; i++) { | 1003 for (intptr_t i = 0; i < len; i++) { |
1010 AstNode* case_expr = node->case_expressions()->NodeAt(i); | 1004 AstNode* case_expr = node->case_expressions()->NodeAt(i); |
1011 TestGraphVisitor for_case_expression(owner(), | 1005 TestGraphVisitor for_case_expression(owner(), |
1012 temp_index(), | 1006 temp_index(), |
1013 case_expr->token_pos()); | 1007 case_expr->token_pos()); |
1014 case_expr->Visit(&for_case_expression); | 1008 case_expr->Visit(&for_case_expression); |
1015 if (i == 0) { | 1009 if (i == 0) { |
1016 // Append only the first one, everything else is connected from it. | 1010 // Append only the first one, everything else is connected from it. |
1017 Append(for_case_expression); | 1011 Append(for_case_expression); |
1018 } else { | 1012 } else { |
1019 TargetEntryInstr* case_entry_target = new TargetEntryInstr(); | 1013 TargetEntryInstr* case_entry_target = |
| 1014 new TargetEntryInstr(owner()->try_index()); |
1020 AppendFragment(case_entry_target, for_case_expression); | 1015 AppendFragment(case_entry_target, for_case_expression); |
1021 *previous_false_address = case_entry_target; | 1016 *previous_false_address = case_entry_target; |
1022 } | 1017 } |
1023 TargetEntryInstr* true_target = new TargetEntryInstr(); | 1018 TargetEntryInstr* true_target = |
| 1019 new TargetEntryInstr(owner()->try_index()); |
1024 *for_case_expression.true_successor_address() = true_target; | 1020 *for_case_expression.true_successor_address() = true_target; |
1025 true_target->Goto(statement_start); | 1021 true_target->Goto(statement_start); |
1026 previous_false_address = for_case_expression.false_successor_address(); | 1022 previous_false_address = for_case_expression.false_successor_address(); |
1027 } | 1023 } |
1028 | 1024 |
1029 // Once a test fragment has been added, this fragment is closed. | 1025 // Once a test fragment has been added, this fragment is closed. |
1030 ASSERT(!is_open()); | 1026 ASSERT(!is_open()); |
1031 | 1027 |
1032 Instruction* exit_instruction = NULL; | 1028 Instruction* exit_instruction = NULL; |
1033 // Handle last (or only) case: false goes to exit or to statement if this | 1029 // Handle last (or only) case: false goes to exit or to statement if this |
1034 // node contains default. | 1030 // node contains default. |
1035 if (len > 0) { | 1031 if (len > 0) { |
1036 TargetEntryInstr* false_target = new TargetEntryInstr(); | 1032 TargetEntryInstr* false_target = |
| 1033 new TargetEntryInstr(owner()->try_index()); |
1037 *previous_false_address = false_target; | 1034 *previous_false_address = false_target; |
1038 if (node->contains_default()) { | 1035 if (node->contains_default()) { |
1039 // True and false go to statement start. | 1036 // True and false go to statement start. |
1040 false_target->Goto(statement_start); | 1037 false_target->Goto(statement_start); |
1041 exit_instruction = statement_exit; | 1038 exit_instruction = statement_exit; |
1042 } else { | 1039 } else { |
1043 if (statement_exit != NULL) { | 1040 if (statement_exit != NULL) { |
1044 JoinEntryInstr* join = new JoinEntryInstr(); | 1041 JoinEntryInstr* join = new JoinEntryInstr(owner()->try_index()); |
1045 statement_exit->Goto(join); | 1042 statement_exit->Goto(join); |
1046 false_target->Goto(join); | 1043 false_target->Goto(join); |
1047 exit_instruction = join; | 1044 exit_instruction = join; |
1048 } else { | 1045 } else { |
1049 exit_instruction = false_target; | 1046 exit_instruction = false_target; |
1050 } | 1047 } |
1051 } | 1048 } |
1052 } else { | 1049 } else { |
1053 // A CaseNode without case expressions must contain default. | 1050 // A CaseNode without case expressions must contain default. |
1054 ASSERT(node->contains_default()); | 1051 ASSERT(node->contains_default()); |
(...skipping 19 matching lines...) Expand all Loading... |
1074 // g) break-join (optional) | 1071 // g) break-join (optional) |
1075 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) { | 1072 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) { |
1076 TestGraphVisitor for_test(owner(), | 1073 TestGraphVisitor for_test(owner(), |
1077 temp_index(), | 1074 temp_index(), |
1078 node->condition()->token_pos()); | 1075 node->condition()->token_pos()); |
1079 node->condition()->Visit(&for_test); | 1076 node->condition()->Visit(&for_test); |
1080 ASSERT(!for_test.is_empty()); // Language spec. | 1077 ASSERT(!for_test.is_empty()); // Language spec. |
1081 | 1078 |
1082 EffectGraphVisitor for_body(owner(), temp_index()); | 1079 EffectGraphVisitor for_body(owner(), temp_index()); |
1083 for_body.Do( | 1080 for_body.Do( |
1084 new CheckStackOverflowComp(node->token_pos(), owner()->try_index())); | 1081 new CheckStackOverflowComp(node->token_pos())); |
1085 node->body()->Visit(&for_body); | 1082 node->body()->Visit(&for_body); |
1086 | 1083 |
1087 // Labels are set after body traversal. | 1084 // Labels are set after body traversal. |
1088 SourceLabel* lbl = node->label(); | 1085 SourceLabel* lbl = node->label(); |
1089 ASSERT(lbl != NULL); | 1086 ASSERT(lbl != NULL); |
1090 JoinEntryInstr* join = lbl->join_for_continue(); | 1087 JoinEntryInstr* join = lbl->join_for_continue(); |
1091 if (join != NULL) { | 1088 if (join != NULL) { |
1092 if (for_body.is_open()) for_body.Goto(join); | 1089 if (for_body.is_open()) for_body.Goto(join); |
1093 for_body.exit_ = join; | 1090 for_body.exit_ = join; |
1094 } | 1091 } |
(...skipping 11 matching lines...) Expand all Loading... |
1106 // b) [ body ] | 1103 // b) [ body ] |
1107 // c) test-entry (continue-join or body-exit-target) | 1104 // c) test-entry (continue-join or body-exit-target) |
1108 // d) [ test-entry ] -> (back-target, loop-exit-target) | 1105 // d) [ test-entry ] -> (back-target, loop-exit-target) |
1109 // e) back-target -> (body-entry-join) | 1106 // e) back-target -> (body-entry-join) |
1110 // f) loop-exit-target | 1107 // f) loop-exit-target |
1111 // g) break-join | 1108 // g) break-join |
1112 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { | 1109 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { |
1113 // Traverse body first in order to generate continue and break labels. | 1110 // Traverse body first in order to generate continue and break labels. |
1114 EffectGraphVisitor for_body(owner(), temp_index()); | 1111 EffectGraphVisitor for_body(owner(), temp_index()); |
1115 for_body.Do( | 1112 for_body.Do( |
1116 new CheckStackOverflowComp(node->token_pos(), owner()->try_index())); | 1113 new CheckStackOverflowComp(node->token_pos())); |
1117 node->body()->Visit(&for_body); | 1114 node->body()->Visit(&for_body); |
1118 | 1115 |
1119 TestGraphVisitor for_test(owner(), | 1116 TestGraphVisitor for_test(owner(), |
1120 temp_index(), | 1117 temp_index(), |
1121 node->condition()->token_pos()); | 1118 node->condition()->token_pos()); |
1122 node->condition()->Visit(&for_test); | 1119 node->condition()->Visit(&for_test); |
1123 ASSERT(is_open()); | 1120 ASSERT(is_open()); |
1124 | 1121 |
1125 // Tie do-while loop (test is after the body). | 1122 // Tie do-while loop (test is after the body). |
1126 JoinEntryInstr* body_entry_join = new JoinEntryInstr(); | 1123 JoinEntryInstr* body_entry_join = new JoinEntryInstr(owner()->try_index()); |
1127 Goto(body_entry_join); | 1124 Goto(body_entry_join); |
1128 Instruction* body_exit = AppendFragment(body_entry_join, for_body); | 1125 Instruction* body_exit = AppendFragment(body_entry_join, for_body); |
1129 | 1126 |
1130 JoinEntryInstr* join = node->label()->join_for_continue(); | 1127 JoinEntryInstr* join = node->label()->join_for_continue(); |
1131 if ((body_exit != NULL) || (join != NULL)) { | 1128 if ((body_exit != NULL) || (join != NULL)) { |
1132 if (join == NULL) join = new JoinEntryInstr(); | 1129 if (join == NULL) join = new JoinEntryInstr(owner()->try_index()); |
1133 join->set_next(for_test.entry()); | 1130 join->set_next(for_test.entry()); |
1134 if (body_exit != NULL) { | 1131 if (body_exit != NULL) { |
1135 body_exit->Goto(join); | 1132 body_exit->Goto(join); |
1136 } | 1133 } |
1137 } | 1134 } |
1138 | 1135 |
1139 TargetEntryInstr* back_target_entry = new TargetEntryInstr(); | 1136 TargetEntryInstr* back_target_entry = |
| 1137 new TargetEntryInstr(owner()->try_index()); |
1140 *for_test.true_successor_address() = back_target_entry; | 1138 *for_test.true_successor_address() = back_target_entry; |
1141 back_target_entry->Goto(body_entry_join); | 1139 back_target_entry->Goto(body_entry_join); |
1142 TargetEntryInstr* loop_exit_target = new TargetEntryInstr(); | 1140 TargetEntryInstr* loop_exit_target = |
| 1141 new TargetEntryInstr(owner()->try_index()); |
1143 *for_test.false_successor_address() = loop_exit_target; | 1142 *for_test.false_successor_address() = loop_exit_target; |
1144 if (node->label()->join_for_break() == NULL) { | 1143 if (node->label()->join_for_break() == NULL) { |
1145 exit_ = loop_exit_target; | 1144 exit_ = loop_exit_target; |
1146 } else { | 1145 } else { |
1147 loop_exit_target->Goto(node->label()->join_for_break()); | 1146 loop_exit_target->Goto(node->label()->join_for_break()); |
1148 exit_ = node->label()->join_for_break(); | 1147 exit_ = node->label()->join_for_break(); |
1149 } | 1148 } |
1150 } | 1149 } |
1151 | 1150 |
1152 | 1151 |
(...skipping 11 matching lines...) Expand all Loading... |
1164 // i) break-join | 1163 // i) break-join |
1165 void EffectGraphVisitor::VisitForNode(ForNode* node) { | 1164 void EffectGraphVisitor::VisitForNode(ForNode* node) { |
1166 EffectGraphVisitor for_initializer(owner(), temp_index()); | 1165 EffectGraphVisitor for_initializer(owner(), temp_index()); |
1167 node->initializer()->Visit(&for_initializer); | 1166 node->initializer()->Visit(&for_initializer); |
1168 Append(for_initializer); | 1167 Append(for_initializer); |
1169 ASSERT(is_open()); | 1168 ASSERT(is_open()); |
1170 | 1169 |
1171 // Compose body to set any jump labels. | 1170 // Compose body to set any jump labels. |
1172 EffectGraphVisitor for_body(owner(), temp_index()); | 1171 EffectGraphVisitor for_body(owner(), temp_index()); |
1173 for_body.Do( | 1172 for_body.Do( |
1174 new CheckStackOverflowComp(node->token_pos(), owner()->try_index())); | 1173 new CheckStackOverflowComp(node->token_pos())); |
1175 node->body()->Visit(&for_body); | 1174 node->body()->Visit(&for_body); |
1176 | 1175 |
1177 // Join loop body, increment and compute their end instruction. | 1176 // Join loop body, increment and compute their end instruction. |
1178 ASSERT(!for_body.is_empty()); | 1177 ASSERT(!for_body.is_empty()); |
1179 Instruction* loop_increment_end = NULL; | 1178 Instruction* loop_increment_end = NULL; |
1180 EffectGraphVisitor for_increment(owner(), temp_index()); | 1179 EffectGraphVisitor for_increment(owner(), temp_index()); |
1181 node->increment()->Visit(&for_increment); | 1180 node->increment()->Visit(&for_increment); |
1182 JoinEntryInstr* join = node->label()->join_for_continue(); | 1181 JoinEntryInstr* join = node->label()->join_for_continue(); |
1183 if (join != NULL) { | 1182 if (join != NULL) { |
1184 // Insert the join between the body and increment. | 1183 // Insert the join between the body and increment. |
1185 if (for_body.is_open()) for_body.Goto(join); | 1184 if (for_body.is_open()) for_body.Goto(join); |
1186 loop_increment_end = AppendFragment(join, for_increment); | 1185 loop_increment_end = AppendFragment(join, for_increment); |
1187 ASSERT(loop_increment_end != NULL); | 1186 ASSERT(loop_increment_end != NULL); |
1188 } else if (for_body.is_open()) { | 1187 } else if (for_body.is_open()) { |
1189 // Do not insert an extra basic block. | 1188 // Do not insert an extra basic block. |
1190 for_body.Append(for_increment); | 1189 for_body.Append(for_increment); |
1191 loop_increment_end = for_body.exit(); | 1190 loop_increment_end = for_body.exit(); |
1192 // 'for_body' contains at least the stack check. | 1191 // 'for_body' contains at least the stack check. |
1193 ASSERT(loop_increment_end != NULL); | 1192 ASSERT(loop_increment_end != NULL); |
1194 } else { | 1193 } else { |
1195 loop_increment_end = NULL; | 1194 loop_increment_end = NULL; |
1196 } | 1195 } |
1197 | 1196 |
1198 // 'loop_increment_end' is NULL only if there is no join for continue and the | 1197 // 'loop_increment_end' is NULL only if there is no join for continue and the |
1199 // body is not open, i.e., no backward branch exists. | 1198 // body is not open, i.e., no backward branch exists. |
1200 if (loop_increment_end != NULL) { | 1199 if (loop_increment_end != NULL) { |
1201 JoinEntryInstr* loop_start = new JoinEntryInstr(); | 1200 JoinEntryInstr* loop_start = new JoinEntryInstr(owner()->try_index()); |
1202 Goto(loop_start); | 1201 Goto(loop_start); |
1203 loop_increment_end->Goto(loop_start); | 1202 loop_increment_end->Goto(loop_start); |
1204 exit_ = loop_start; | 1203 exit_ = loop_start; |
1205 } | 1204 } |
1206 | 1205 |
1207 if (node->condition() == NULL) { | 1206 if (node->condition() == NULL) { |
1208 // Endless loop, no test. | 1207 // Endless loop, no test. |
1209 JoinEntryInstr* body_entry = new JoinEntryInstr(); | 1208 JoinEntryInstr* body_entry = new JoinEntryInstr(owner()->try_index()); |
1210 AppendFragment(body_entry, for_body); | 1209 AppendFragment(body_entry, for_body); |
1211 Goto(body_entry); | 1210 Goto(body_entry); |
1212 if (node->label()->join_for_break() != NULL) { | 1211 if (node->label()->join_for_break() != NULL) { |
1213 // Control flow of ForLoop continues into join_for_break. | 1212 // Control flow of ForLoop continues into join_for_break. |
1214 exit_ = node->label()->join_for_break(); | 1213 exit_ = node->label()->join_for_break(); |
1215 } | 1214 } |
1216 } else { | 1215 } else { |
1217 TargetEntryInstr* loop_exit = new TargetEntryInstr(); | 1216 TargetEntryInstr* loop_exit = new TargetEntryInstr(owner()->try_index()); |
1218 TestGraphVisitor for_test(owner(), | 1217 TestGraphVisitor for_test(owner(), |
1219 temp_index(), | 1218 temp_index(), |
1220 node->condition()->token_pos()); | 1219 node->condition()->token_pos()); |
1221 node->condition()->Visit(&for_test); | 1220 node->condition()->Visit(&for_test); |
1222 Append(for_test); | 1221 Append(for_test); |
1223 TargetEntryInstr* body_entry = new TargetEntryInstr(); | 1222 TargetEntryInstr* body_entry = new TargetEntryInstr(owner()->try_index()); |
1224 AppendFragment(body_entry, for_body); | 1223 AppendFragment(body_entry, for_body); |
1225 *for_test.true_successor_address() = body_entry; | 1224 *for_test.true_successor_address() = body_entry; |
1226 *for_test.false_successor_address() = loop_exit; | 1225 *for_test.false_successor_address() = loop_exit; |
1227 if (node->label()->join_for_break() == NULL) { | 1226 if (node->label()->join_for_break() == NULL) { |
1228 exit_ = loop_exit; | 1227 exit_ = loop_exit; |
1229 } else { | 1228 } else { |
1230 loop_exit->Goto(node->label()->join_for_break()); | 1229 loop_exit->Goto(node->label()->join_for_break()); |
1231 exit_ = node->label()->join_for_break(); | 1230 exit_ = node->label()->join_for_break(); |
1232 } | 1231 } |
1233 } | 1232 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1266 ASSERT(target_context_level >= 0); | 1265 ASSERT(target_context_level >= 0); |
1267 intptr_t current_context_level = owner()->context_level(); | 1266 intptr_t current_context_level = owner()->context_level(); |
1268 ASSERT(current_context_level >= target_context_level); | 1267 ASSERT(current_context_level >= target_context_level); |
1269 while (current_context_level-- > target_context_level) { | 1268 while (current_context_level-- > target_context_level) { |
1270 UnchainContext(); | 1269 UnchainContext(); |
1271 } | 1270 } |
1272 | 1271 |
1273 JoinEntryInstr* jump_target = NULL; | 1272 JoinEntryInstr* jump_target = NULL; |
1274 if (node->kind() == Token::kBREAK) { | 1273 if (node->kind() == Token::kBREAK) { |
1275 if (node->label()->join_for_break() == NULL) { | 1274 if (node->label()->join_for_break() == NULL) { |
1276 node->label()->set_join_for_break(new JoinEntryInstr()); | 1275 node->label()->set_join_for_break( |
| 1276 new JoinEntryInstr(owner()->try_index())); |
1277 } | 1277 } |
1278 jump_target = node->label()->join_for_break(); | 1278 jump_target = node->label()->join_for_break(); |
1279 } else { | 1279 } else { |
1280 if (node->label()->join_for_continue() == NULL) { | 1280 if (node->label()->join_for_continue() == NULL) { |
1281 node->label()->set_join_for_continue(new JoinEntryInstr()); | 1281 node->label()->set_join_for_continue( |
| 1282 new JoinEntryInstr(owner()->try_index())); |
1282 } | 1283 } |
1283 jump_target = node->label()->join_for_continue(); | 1284 jump_target = node->label()->join_for_continue(); |
1284 } | 1285 } |
1285 Goto(jump_target); | 1286 Goto(jump_target); |
1286 } | 1287 } |
1287 | 1288 |
1288 | 1289 |
1289 void EffectGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) { | 1290 void EffectGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) { |
1290 UNREACHABLE(); | 1291 UNREACHABLE(); |
1291 } | 1292 } |
1292 | 1293 |
1293 | 1294 |
1294 void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) { | 1295 void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) { |
1295 // Translate the array elements and collect their values. | 1296 // Translate the array elements and collect their values. |
1296 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1297 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1297 new ZoneGrowableArray<PushArgumentInstr*>(node->length()); | 1298 new ZoneGrowableArray<PushArgumentInstr*>(node->length()); |
1298 for (int i = 0; i < node->length(); ++i) { | 1299 for (int i = 0; i < node->length(); ++i) { |
1299 ValueGraphVisitor for_value(owner(), temp_index()); | 1300 ValueGraphVisitor for_value(owner(), temp_index()); |
1300 node->ElementAt(i)->Visit(&for_value); | 1301 node->ElementAt(i)->Visit(&for_value); |
1301 Append(for_value); | 1302 Append(for_value); |
1302 arguments->Add(PushArgument(for_value.value())); | 1303 arguments->Add(PushArgument(for_value.value())); |
1303 } | 1304 } |
1304 const AbstractTypeArguments& type_args = | 1305 const AbstractTypeArguments& type_args = |
1305 AbstractTypeArguments::ZoneHandle(node->type().arguments()); | 1306 AbstractTypeArguments::ZoneHandle(node->type().arguments()); |
1306 Value* element_type = BuildInstantiatedTypeArguments(node->token_pos(), | 1307 Value* element_type = BuildInstantiatedTypeArguments(node->token_pos(), |
1307 type_args); | 1308 type_args); |
1308 CreateArrayComp* create = new CreateArrayComp(node->token_pos(), | 1309 CreateArrayComp* create = new CreateArrayComp(node->token_pos(), |
1309 owner()->try_index(), | |
1310 arguments, | 1310 arguments, |
1311 node->type(), | 1311 node->type(), |
1312 element_type); | 1312 element_type); |
1313 ReturnComputation(create); | 1313 ReturnComputation(create); |
1314 } | 1314 } |
1315 | 1315 |
1316 | 1316 |
1317 void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) { | 1317 void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) { |
1318 const Function& function = node->function(); | 1318 const Function& function = node->function(); |
1319 | 1319 |
(...skipping 30 matching lines...) Expand all Loading... |
1350 const bool requires_type_arguments = cls.HasTypeArguments(); | 1350 const bool requires_type_arguments = cls.HasTypeArguments(); |
1351 Value* type_arguments = NULL; | 1351 Value* type_arguments = NULL; |
1352 if (requires_type_arguments) { | 1352 if (requires_type_arguments) { |
1353 ASSERT(!function.IsImplicitStaticClosureFunction()); | 1353 ASSERT(!function.IsImplicitStaticClosureFunction()); |
1354 type_arguments = BuildInstantiatorTypeArguments(node->token_pos(), NULL); | 1354 type_arguments = BuildInstantiatorTypeArguments(node->token_pos(), NULL); |
1355 } else { | 1355 } else { |
1356 type_arguments = BuildNullValue(); | 1356 type_arguments = BuildNullValue(); |
1357 } | 1357 } |
1358 PushArgumentInstr* push_type_arguments = PushArgument(type_arguments); | 1358 PushArgumentInstr* push_type_arguments = PushArgument(type_arguments); |
1359 arguments->Add(push_type_arguments); | 1359 arguments->Add(push_type_arguments); |
1360 ReturnComputation( | 1360 ReturnComputation(new CreateClosureComp(node, arguments)); |
1361 new CreateClosureComp(node, owner()->try_index(), arguments)); | |
1362 } | 1361 } |
1363 | 1362 |
1364 | 1363 |
1365 void EffectGraphVisitor::TranslateArgumentList( | 1364 void EffectGraphVisitor::TranslateArgumentList( |
1366 const ArgumentListNode& node, | 1365 const ArgumentListNode& node, |
1367 ZoneGrowableArray<Value*>* values) { | 1366 ZoneGrowableArray<Value*>* values) { |
1368 for (intptr_t i = 0; i < node.length(); ++i) { | 1367 for (intptr_t i = 0; i < node.length(); ++i) { |
1369 ValueGraphVisitor for_argument(owner(), temp_index()); | 1368 ValueGraphVisitor for_argument(owner(), temp_index()); |
1370 node.NodeAt(i)->Visit(&for_argument); | 1369 node.NodeAt(i)->Visit(&for_argument); |
1371 Append(for_argument); | 1370 Append(for_argument); |
(...skipping 20 matching lines...) Expand all Loading... |
1392 node->receiver()->Visit(&for_receiver); | 1391 node->receiver()->Visit(&for_receiver); |
1393 Append(for_receiver); | 1392 Append(for_receiver); |
1394 PushArgumentInstr* push_receiver = PushArgument(for_receiver.value()); | 1393 PushArgumentInstr* push_receiver = PushArgument(for_receiver.value()); |
1395 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1394 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1396 new ZoneGrowableArray<PushArgumentInstr*>( | 1395 new ZoneGrowableArray<PushArgumentInstr*>( |
1397 node->arguments()->length() + 1); | 1396 node->arguments()->length() + 1); |
1398 arguments->Add(push_receiver); | 1397 arguments->Add(push_receiver); |
1399 | 1398 |
1400 BuildPushArguments(*node->arguments(), arguments); | 1399 BuildPushArguments(*node->arguments(), arguments); |
1401 InstanceCallComp* call = new InstanceCallComp( | 1400 InstanceCallComp* call = new InstanceCallComp( |
1402 node->token_pos(), owner()->try_index(), | 1401 node->token_pos(), |
1403 node->function_name(), Token::kILLEGAL, arguments, | 1402 node->function_name(), Token::kILLEGAL, arguments, |
1404 node->arguments()->names(), 1); | 1403 node->arguments()->names(), 1); |
1405 ReturnComputation(call); | 1404 ReturnComputation(call); |
1406 } | 1405 } |
1407 | 1406 |
1408 | 1407 |
1409 // <Expression> ::= StaticCall { function: Function | 1408 // <Expression> ::= StaticCall { function: Function |
1410 // arguments: <ArgumentList> } | 1409 // arguments: <ArgumentList> } |
1411 void EffectGraphVisitor::VisitStaticCallNode(StaticCallNode* node) { | 1410 void EffectGraphVisitor::VisitStaticCallNode(StaticCallNode* node) { |
1412 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1411 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1413 new ZoneGrowableArray<PushArgumentInstr*>(node->arguments()->length()); | 1412 new ZoneGrowableArray<PushArgumentInstr*>(node->arguments()->length()); |
1414 BuildPushArguments(*node->arguments(), arguments); | 1413 BuildPushArguments(*node->arguments(), arguments); |
1415 StaticCallComp* call = | 1414 StaticCallComp* call = |
1416 new StaticCallComp(node->token_pos(), | 1415 new StaticCallComp(node->token_pos(), |
1417 owner()->try_index(), | |
1418 node->function(), | 1416 node->function(), |
1419 node->arguments()->names(), | 1417 node->arguments()->names(), |
1420 arguments); | 1418 arguments); |
1421 ReturnComputation(call); | 1419 ReturnComputation(call); |
1422 } | 1420 } |
1423 | 1421 |
1424 | 1422 |
1425 ClosureCallComp* EffectGraphVisitor::BuildClosureCall( | 1423 ClosureCallComp* EffectGraphVisitor::BuildClosureCall( |
1426 ClosureCallNode* node) { | 1424 ClosureCallNode* node) { |
1427 ValueGraphVisitor for_closure(owner(), temp_index()); | 1425 ValueGraphVisitor for_closure(owner(), temp_index()); |
1428 node->closure()->Visit(&for_closure); | 1426 node->closure()->Visit(&for_closure); |
1429 Append(for_closure); | 1427 Append(for_closure); |
1430 PushArgumentInstr* push_closure = PushArgument(for_closure.value()); | 1428 PushArgumentInstr* push_closure = PushArgument(for_closure.value()); |
1431 | 1429 |
1432 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1430 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1433 new ZoneGrowableArray<PushArgumentInstr*>(node->arguments()->length()); | 1431 new ZoneGrowableArray<PushArgumentInstr*>(node->arguments()->length()); |
1434 arguments->Add(push_closure); | 1432 arguments->Add(push_closure); |
1435 BuildPushArguments(*node->arguments(), arguments); | 1433 BuildPushArguments(*node->arguments(), arguments); |
1436 | 1434 |
1437 // Save context around the call. | 1435 // Save context around the call. |
1438 BuildStoreContext(*owner()->parsed_function().expression_temp_var()); | 1436 BuildStoreContext(*owner()->parsed_function().expression_temp_var()); |
1439 return new ClosureCallComp(node, owner()->try_index(), arguments); | 1437 return new ClosureCallComp(node, arguments); |
1440 } | 1438 } |
1441 | 1439 |
1442 | 1440 |
1443 void EffectGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { | 1441 void EffectGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { |
1444 Do(BuildClosureCall(node)); | 1442 Do(BuildClosureCall(node)); |
1445 // Restore context from saved location. | 1443 // Restore context from saved location. |
1446 BuildLoadContext(*owner()->parsed_function().expression_temp_var()); | 1444 BuildLoadContext(*owner()->parsed_function().expression_temp_var()); |
1447 } | 1445 } |
1448 | 1446 |
1449 | 1447 |
1450 void ValueGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { | 1448 void ValueGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { |
1451 Value* result = Bind(BuildClosureCall(node)); | 1449 Value* result = Bind(BuildClosureCall(node)); |
1452 // Restore context from temp. | 1450 // Restore context from temp. |
1453 BuildLoadContext(*owner()->parsed_function().expression_temp_var()); | 1451 BuildLoadContext(*owner()->parsed_function().expression_temp_var()); |
1454 ReturnValue(result); | 1452 ReturnValue(result); |
1455 } | 1453 } |
1456 | 1454 |
1457 | 1455 |
1458 void EffectGraphVisitor::VisitCloneContextNode(CloneContextNode* node) { | 1456 void EffectGraphVisitor::VisitCloneContextNode(CloneContextNode* node) { |
1459 Value* context = Bind(new CurrentContextComp()); | 1457 Value* context = Bind(new CurrentContextComp()); |
1460 Value* clone = Bind(new CloneContextComp(node->token_pos(), | 1458 Value* clone = Bind(new CloneContextComp(node->token_pos(), context)); |
1461 owner()->try_index(), | |
1462 context)); | |
1463 ReturnComputation(new StoreContextComp(clone)); | 1459 ReturnComputation(new StoreContextComp(clone)); |
1464 } | 1460 } |
1465 | 1461 |
1466 | 1462 |
1467 Value* EffectGraphVisitor::BuildObjectAllocation( | 1463 Value* EffectGraphVisitor::BuildObjectAllocation( |
1468 ConstructorCallNode* node) { | 1464 ConstructorCallNode* node) { |
1469 const Class& cls = Class::ZoneHandle(node->constructor().Owner()); | 1465 const Class& cls = Class::ZoneHandle(node->constructor().Owner()); |
1470 const bool requires_type_arguments = cls.HasTypeArguments(); | 1466 const bool requires_type_arguments = cls.HasTypeArguments(); |
1471 | 1467 |
1472 // In checked mode, if the type arguments are uninstantiated, they may need to | 1468 // In checked mode, if the type arguments are uninstantiated, they may need to |
1473 // be checked against declared bounds at run time. | 1469 // be checked against declared bounds at run time. |
1474 Computation* allocate_comp = NULL; | 1470 Computation* allocate_comp = NULL; |
1475 if (FLAG_enable_type_checks && | 1471 if (FLAG_enable_type_checks && |
1476 requires_type_arguments && | 1472 requires_type_arguments && |
1477 !node->type_arguments().IsNull() && | 1473 !node->type_arguments().IsNull() && |
1478 !node->type_arguments().IsInstantiated() && | 1474 !node->type_arguments().IsInstantiated() && |
1479 !node->type_arguments().IsWithinBoundsOf(cls, | 1475 !node->type_arguments().IsWithinBoundsOf(cls, |
1480 node->type_arguments(), | 1476 node->type_arguments(), |
1481 NULL)) { | 1477 NULL)) { |
1482 Value* type_arguments = NULL; | 1478 Value* type_arguments = NULL; |
1483 Value* instantiator = NULL; | 1479 Value* instantiator = NULL; |
1484 BuildConstructorTypeArguments(node, &type_arguments, &instantiator, NULL); | 1480 BuildConstructorTypeArguments(node, &type_arguments, &instantiator, NULL); |
1485 | 1481 |
1486 // The uninstantiated type arguments cannot be verified to be within their | 1482 // The uninstantiated type arguments cannot be verified to be within their |
1487 // bounds at compile time, so verify them at runtime. | 1483 // bounds at compile time, so verify them at runtime. |
1488 // Although the type arguments may be uninstantiated at compile time, they | 1484 // Although the type arguments may be uninstantiated at compile time, they |
1489 // may represent the identity vector and may be replaced by the instantiated | 1485 // may represent the identity vector and may be replaced by the instantiated |
1490 // type arguments of the instantiator at run time. | 1486 // type arguments of the instantiator at run time. |
1491 allocate_comp = new AllocateObjectWithBoundsCheckComp(node, | 1487 allocate_comp = new AllocateObjectWithBoundsCheckComp(node, |
1492 owner()->try_index(), | |
1493 type_arguments, | 1488 type_arguments, |
1494 instantiator); | 1489 instantiator); |
1495 } else { | 1490 } else { |
1496 ZoneGrowableArray<PushArgumentInstr*>* allocate_arguments = | 1491 ZoneGrowableArray<PushArgumentInstr*>* allocate_arguments = |
1497 new ZoneGrowableArray<PushArgumentInstr*>(); | 1492 new ZoneGrowableArray<PushArgumentInstr*>(); |
1498 | 1493 |
1499 if (requires_type_arguments) { | 1494 if (requires_type_arguments) { |
1500 BuildConstructorTypeArguments(node, NULL, NULL, allocate_arguments); | 1495 BuildConstructorTypeArguments(node, NULL, NULL, allocate_arguments); |
1501 } | 1496 } |
1502 | 1497 |
1503 allocate_comp = new AllocateObjectComp(node, | 1498 allocate_comp = new AllocateObjectComp(node, allocate_arguments); |
1504 owner()->try_index(), | |
1505 allocate_arguments); | |
1506 } | 1499 } |
1507 return Bind(allocate_comp); | 1500 return Bind(allocate_comp); |
1508 } | 1501 } |
1509 | 1502 |
1510 | 1503 |
1511 void EffectGraphVisitor::BuildConstructorCall( | 1504 void EffectGraphVisitor::BuildConstructorCall( |
1512 ConstructorCallNode* node, | 1505 ConstructorCallNode* node, |
1513 PushArgumentInstr* push_alloc_value) { | 1506 PushArgumentInstr* push_alloc_value) { |
1514 Value* ctor_arg = Bind( | 1507 Value* ctor_arg = Bind( |
1515 Constant(Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll)))); | 1508 Constant(Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll)))); |
1516 PushArgumentInstr* push_ctor_arg = PushArgument(ctor_arg); | 1509 PushArgumentInstr* push_ctor_arg = PushArgument(ctor_arg); |
1517 | 1510 |
1518 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1511 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1519 new ZoneGrowableArray<PushArgumentInstr*>(2); | 1512 new ZoneGrowableArray<PushArgumentInstr*>(2); |
1520 arguments->Add(push_alloc_value); | 1513 arguments->Add(push_alloc_value); |
1521 arguments->Add(push_ctor_arg); | 1514 arguments->Add(push_ctor_arg); |
1522 | 1515 |
1523 BuildPushArguments(*node->arguments(), arguments); | 1516 BuildPushArguments(*node->arguments(), arguments); |
1524 Do(new StaticCallComp(node->token_pos(), | 1517 Do(new StaticCallComp(node->token_pos(), |
1525 owner()->try_index(), | |
1526 node->constructor(), | 1518 node->constructor(), |
1527 node->arguments()->names(), | 1519 node->arguments()->names(), |
1528 arguments)); | 1520 arguments)); |
1529 } | 1521 } |
1530 | 1522 |
1531 | 1523 |
1532 void EffectGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) { | 1524 void EffectGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) { |
1533 if (node->constructor().IsFactory()) { | 1525 if (node->constructor().IsFactory()) { |
1534 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1526 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1535 new ZoneGrowableArray<PushArgumentInstr*>(); | 1527 new ZoneGrowableArray<PushArgumentInstr*>(); |
1536 PushArgumentInstr* push_type_arguments = PushArgument( | 1528 PushArgumentInstr* push_type_arguments = PushArgument( |
1537 BuildInstantiatedTypeArguments(node->token_pos(), | 1529 BuildInstantiatedTypeArguments(node->token_pos(), |
1538 node->type_arguments())); | 1530 node->type_arguments())); |
1539 arguments->Add(push_type_arguments); | 1531 arguments->Add(push_type_arguments); |
1540 ASSERT(arguments->length() == 1); | 1532 ASSERT(arguments->length() == 1); |
1541 BuildPushArguments(*node->arguments(), arguments); | 1533 BuildPushArguments(*node->arguments(), arguments); |
1542 StaticCallComp* call = | 1534 StaticCallComp* call = |
1543 new StaticCallComp(node->token_pos(), | 1535 new StaticCallComp(node->token_pos(), |
1544 owner()->try_index(), | |
1545 node->constructor(), | 1536 node->constructor(), |
1546 node->arguments()->names(), | 1537 node->arguments()->names(), |
1547 arguments); | 1538 arguments); |
1548 ReturnComputation(call); | 1539 ReturnComputation(call); |
1549 return; | 1540 return; |
1550 } | 1541 } |
1551 // t_n contains the allocated and initialized object. | 1542 // t_n contains the allocated and initialized object. |
1552 // t_n <- AllocateObject(class) | 1543 // t_n <- AllocateObject(class) |
1553 // t_n+1 <- ctor-arg | 1544 // t_n+1 <- ctor-arg |
1554 // t_n+2... <- constructor arguments start here | 1545 // t_n+2... <- constructor arguments start here |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1637 Value* EffectGraphVisitor::BuildInstantiatedTypeArguments( | 1628 Value* EffectGraphVisitor::BuildInstantiatedTypeArguments( |
1638 intptr_t token_pos, | 1629 intptr_t token_pos, |
1639 const AbstractTypeArguments& type_arguments) { | 1630 const AbstractTypeArguments& type_arguments) { |
1640 if (type_arguments.IsNull() || type_arguments.IsInstantiated()) { | 1631 if (type_arguments.IsNull() || type_arguments.IsInstantiated()) { |
1641 return Bind(Constant(type_arguments)); | 1632 return Bind(Constant(type_arguments)); |
1642 } | 1633 } |
1643 // The type arguments are uninstantiated. | 1634 // The type arguments are uninstantiated. |
1644 Value* instantiator_value = | 1635 Value* instantiator_value = |
1645 BuildInstantiatorTypeArguments(token_pos, NULL); | 1636 BuildInstantiatorTypeArguments(token_pos, NULL); |
1646 return Bind(new InstantiateTypeArgumentsComp(token_pos, | 1637 return Bind(new InstantiateTypeArgumentsComp(token_pos, |
1647 owner()->try_index(), | |
1648 type_arguments, | 1638 type_arguments, |
1649 instantiator_value)); | 1639 instantiator_value)); |
1650 } | 1640 } |
1651 | 1641 |
1652 | 1642 |
1653 void EffectGraphVisitor::BuildConstructorTypeArguments( | 1643 void EffectGraphVisitor::BuildConstructorTypeArguments( |
1654 ConstructorCallNode* node, | 1644 ConstructorCallNode* node, |
1655 Value** type_arguments, | 1645 Value** type_arguments, |
1656 Value** instantiator, | 1646 Value** instantiator, |
1657 ZoneGrowableArray<PushArgumentInstr*>* call_arguments) { | 1647 ZoneGrowableArray<PushArgumentInstr*>* call_arguments) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1694 Value* instantiator_type_arguments = BuildInstantiatorTypeArguments( | 1684 Value* instantiator_type_arguments = BuildInstantiatorTypeArguments( |
1695 node->token_pos(), NULL); | 1685 node->token_pos(), NULL); |
1696 ASSERT(instantiator_type_arguments->IsUse()); | 1686 ASSERT(instantiator_type_arguments->IsUse()); |
1697 Value* stored_instantiator = | 1687 Value* stored_instantiator = |
1698 Bind(BuildStoreLocal(t1, instantiator_type_arguments)); | 1688 Bind(BuildStoreLocal(t1, instantiator_type_arguments)); |
1699 // t1: instantiator type arguments. | 1689 // t1: instantiator type arguments. |
1700 | 1690 |
1701 Value* extract_type_arguments = Bind( | 1691 Value* extract_type_arguments = Bind( |
1702 new ExtractConstructorTypeArgumentsComp( | 1692 new ExtractConstructorTypeArgumentsComp( |
1703 node->token_pos(), | 1693 node->token_pos(), |
1704 owner()->try_index(), | |
1705 node->type_arguments(), | 1694 node->type_arguments(), |
1706 stored_instantiator)); | 1695 stored_instantiator)); |
1707 | 1696 |
1708 Do(BuildStoreLocal(t2, extract_type_arguments)); | 1697 Do(BuildStoreLocal(t2, extract_type_arguments)); |
1709 // t2: extracted constructor type arguments. | 1698 // t2: extracted constructor type arguments. |
1710 Value* load_instantiator = Bind(BuildLoadLocal(t1)); | 1699 Value* load_instantiator = Bind(BuildLoadLocal(t1)); |
1711 | 1700 |
1712 Value* extract_instantiator = | 1701 Value* extract_instantiator = |
1713 Bind(new ExtractConstructorInstantiatorComp(node, load_instantiator)); | 1702 Bind(new ExtractConstructorInstantiatorComp(node, load_instantiator)); |
1714 Do(BuildStoreLocal(t1, extract_instantiator)); | 1703 Do(BuildStoreLocal(t1, extract_instantiator)); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1766 ValueGraphVisitor for_receiver(owner(), temp_index()); | 1755 ValueGraphVisitor for_receiver(owner(), temp_index()); |
1767 node->receiver()->Visit(&for_receiver); | 1756 node->receiver()->Visit(&for_receiver); |
1768 Append(for_receiver); | 1757 Append(for_receiver); |
1769 PushArgumentInstr* push_receiver = PushArgument(for_receiver.value()); | 1758 PushArgumentInstr* push_receiver = PushArgument(for_receiver.value()); |
1770 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1759 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1771 new ZoneGrowableArray<PushArgumentInstr*>(1); | 1760 new ZoneGrowableArray<PushArgumentInstr*>(1); |
1772 arguments->Add(push_receiver); | 1761 arguments->Add(push_receiver); |
1773 const String& name = | 1762 const String& name = |
1774 String::ZoneHandle(Field::GetterSymbol(node->field_name())); | 1763 String::ZoneHandle(Field::GetterSymbol(node->field_name())); |
1775 InstanceCallComp* call = new InstanceCallComp( | 1764 InstanceCallComp* call = new InstanceCallComp( |
1776 node->token_pos(), owner()->try_index(), name, Token::kGET, | 1765 node->token_pos(), name, Token::kGET, |
1777 arguments, Array::ZoneHandle(), 1); | 1766 arguments, Array::ZoneHandle(), 1); |
1778 ReturnComputation(call); | 1767 ReturnComputation(call); |
1779 } | 1768 } |
1780 | 1769 |
1781 | 1770 |
1782 void EffectGraphVisitor::BuildInstanceSetterArguments( | 1771 void EffectGraphVisitor::BuildInstanceSetterArguments( |
1783 InstanceSetterNode* node, | 1772 InstanceSetterNode* node, |
1784 ZoneGrowableArray<PushArgumentInstr*>* arguments, | 1773 ZoneGrowableArray<PushArgumentInstr*>* arguments, |
1785 bool result_is_needed) { | 1774 bool result_is_needed) { |
1786 ValueGraphVisitor for_receiver(owner(), temp_index()); | 1775 ValueGraphVisitor for_receiver(owner(), temp_index()); |
(...skipping 17 matching lines...) Expand all Loading... |
1804 } | 1793 } |
1805 | 1794 |
1806 | 1795 |
1807 void EffectGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) { | 1796 void EffectGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) { |
1808 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1797 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1809 new ZoneGrowableArray<PushArgumentInstr*>(2); | 1798 new ZoneGrowableArray<PushArgumentInstr*>(2); |
1810 BuildInstanceSetterArguments(node, arguments, false); // Value not used. | 1799 BuildInstanceSetterArguments(node, arguments, false); // Value not used. |
1811 const String& name = | 1800 const String& name = |
1812 String::ZoneHandle(Field::SetterSymbol(node->field_name())); | 1801 String::ZoneHandle(Field::SetterSymbol(node->field_name())); |
1813 InstanceCallComp* call = new InstanceCallComp(node->token_pos(), | 1802 InstanceCallComp* call = new InstanceCallComp(node->token_pos(), |
1814 owner()->try_index(), | |
1815 name, | 1803 name, |
1816 Token::kSET, | 1804 Token::kSET, |
1817 arguments, | 1805 arguments, |
1818 Array::ZoneHandle(), | 1806 Array::ZoneHandle(), |
1819 1); // Checked argument count. | 1807 1); // Checked argument count. |
1820 ReturnComputation(call); | 1808 ReturnComputation(call); |
1821 } | 1809 } |
1822 | 1810 |
1823 | 1811 |
1824 void ValueGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) { | 1812 void ValueGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) { |
1825 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1813 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1826 new ZoneGrowableArray<PushArgumentInstr*>(2); | 1814 new ZoneGrowableArray<PushArgumentInstr*>(2); |
1827 BuildInstanceSetterArguments(node, arguments, true); // Value used. | 1815 BuildInstanceSetterArguments(node, arguments, true); // Value used. |
1828 const String& name = | 1816 const String& name = |
1829 String::ZoneHandle(Field::SetterSymbol(node->field_name())); | 1817 String::ZoneHandle(Field::SetterSymbol(node->field_name())); |
1830 Do(new InstanceCallComp(node->token_pos(), | 1818 Do(new InstanceCallComp(node->token_pos(), |
1831 owner()->try_index(), | |
1832 name, | 1819 name, |
1833 Token::kSET, | 1820 Token::kSET, |
1834 arguments, | 1821 arguments, |
1835 Array::ZoneHandle(), | 1822 Array::ZoneHandle(), |
1836 1)); // Checked argument count. | 1823 1)); // Checked argument count. |
1837 ReturnComputation( | 1824 ReturnComputation( |
1838 BuildLoadLocal(*owner()->parsed_function().expression_temp_var())); | 1825 BuildLoadLocal(*owner()->parsed_function().expression_temp_var())); |
1839 } | 1826 } |
1840 | 1827 |
1841 | 1828 |
(...skipping 11 matching lines...) Expand all Loading... |
1853 ASSERT(node->receiver() != NULL); | 1840 ASSERT(node->receiver() != NULL); |
1854 ValueGraphVisitor receiver_value(owner(), temp_index()); | 1841 ValueGraphVisitor receiver_value(owner(), temp_index()); |
1855 node->receiver()->Visit(&receiver_value); | 1842 node->receiver()->Visit(&receiver_value); |
1856 Append(receiver_value); | 1843 Append(receiver_value); |
1857 arguments->Add(PushArgument(receiver_value.value())); | 1844 arguments->Add(PushArgument(receiver_value.value())); |
1858 } else { | 1845 } else { |
1859 getter_function = node->cls().LookupStaticFunction(getter_name); | 1846 getter_function = node->cls().LookupStaticFunction(getter_name); |
1860 ASSERT(!getter_function.IsNull()); | 1847 ASSERT(!getter_function.IsNull()); |
1861 } | 1848 } |
1862 StaticCallComp* call = new StaticCallComp(node->token_pos(), | 1849 StaticCallComp* call = new StaticCallComp(node->token_pos(), |
1863 owner()->try_index(), | |
1864 getter_function, | 1850 getter_function, |
1865 Array::ZoneHandle(), // No names. | 1851 Array::ZoneHandle(), // No names. |
1866 arguments); | 1852 arguments); |
1867 ReturnComputation(call); | 1853 ReturnComputation(call); |
1868 } | 1854 } |
1869 | 1855 |
1870 | 1856 |
1871 void EffectGraphVisitor::BuildStaticSetter(StaticSetterNode* node, | 1857 void EffectGraphVisitor::BuildStaticSetter(StaticSetterNode* node, |
1872 bool result_is_needed) { | 1858 bool result_is_needed) { |
1873 const String& setter_name = | 1859 const String& setter_name = |
(...skipping 24 matching lines...) Expand all Loading... |
1898 if (result_is_needed) { | 1884 if (result_is_needed) { |
1899 value = Bind( | 1885 value = Bind( |
1900 BuildStoreLocal(*owner()->parsed_function().expression_temp_var(), | 1886 BuildStoreLocal(*owner()->parsed_function().expression_temp_var(), |
1901 for_value.value())); | 1887 for_value.value())); |
1902 } else { | 1888 } else { |
1903 value = for_value.value(); | 1889 value = for_value.value(); |
1904 } | 1890 } |
1905 arguments->Add(PushArgument(value)); | 1891 arguments->Add(PushArgument(value)); |
1906 | 1892 |
1907 StaticCallComp* call = new StaticCallComp(node->token_pos(), | 1893 StaticCallComp* call = new StaticCallComp(node->token_pos(), |
1908 owner()->try_index(), | |
1909 setter_function, | 1894 setter_function, |
1910 Array::ZoneHandle(), // No names. | 1895 Array::ZoneHandle(), // No names. |
1911 arguments); | 1896 arguments); |
1912 if (result_is_needed) { | 1897 if (result_is_needed) { |
1913 Do(call); | 1898 Do(call); |
1914 ReturnComputation( | 1899 ReturnComputation( |
1915 BuildLoadLocal(*owner()->parsed_function().expression_temp_var())); | 1900 BuildLoadLocal(*owner()->parsed_function().expression_temp_var())); |
1916 } else { | 1901 } else { |
1917 ReturnComputation(call); | 1902 ReturnComputation(call); |
1918 } | 1903 } |
1919 } | 1904 } |
1920 | 1905 |
1921 | 1906 |
1922 void EffectGraphVisitor::VisitStaticSetterNode(StaticSetterNode* node) { | 1907 void EffectGraphVisitor::VisitStaticSetterNode(StaticSetterNode* node) { |
1923 BuildStaticSetter(node, false); // Result not needed. | 1908 BuildStaticSetter(node, false); // Result not needed. |
1924 } | 1909 } |
1925 | 1910 |
1926 | 1911 |
1927 void ValueGraphVisitor::VisitStaticSetterNode(StaticSetterNode* node) { | 1912 void ValueGraphVisitor::VisitStaticSetterNode(StaticSetterNode* node) { |
1928 BuildStaticSetter(node, true); // Result needed. | 1913 BuildStaticSetter(node, true); // Result needed. |
1929 } | 1914 } |
1930 | 1915 |
1931 | 1916 |
1932 void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) { | 1917 void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) { |
1933 NativeCallComp* native_call = | 1918 NativeCallComp* native_call = new NativeCallComp(node); |
1934 new NativeCallComp(node, owner()->try_index()); | |
1935 ReturnComputation(native_call); | 1919 ReturnComputation(native_call); |
1936 } | 1920 } |
1937 | 1921 |
1938 | 1922 |
1939 void EffectGraphVisitor::VisitPrimaryNode(PrimaryNode* node) { | 1923 void EffectGraphVisitor::VisitPrimaryNode(PrimaryNode* node) { |
1940 // PrimaryNodes are temporary during parsing. | 1924 // PrimaryNodes are temporary during parsing. |
1941 UNREACHABLE(); | 1925 UNREACHABLE(); |
1942 } | 1926 } |
1943 | 1927 |
1944 | 1928 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2053 | 2037 |
2054 ValueGraphVisitor for_index(owner(), temp_index()); | 2038 ValueGraphVisitor for_index(owner(), temp_index()); |
2055 node->index_expr()->Visit(&for_index); | 2039 node->index_expr()->Visit(&for_index); |
2056 Append(for_index); | 2040 Append(for_index); |
2057 arguments->Add(PushArgument(for_index.value())); | 2041 arguments->Add(PushArgument(for_index.value())); |
2058 | 2042 |
2059 const intptr_t checked_argument_count = 1; | 2043 const intptr_t checked_argument_count = 1; |
2060 const String& name = | 2044 const String& name = |
2061 String::ZoneHandle(Symbols::New(Token::Str(Token::kINDEX))); | 2045 String::ZoneHandle(Symbols::New(Token::Str(Token::kINDEX))); |
2062 InstanceCallComp* load = new InstanceCallComp(node->token_pos(), | 2046 InstanceCallComp* load = new InstanceCallComp(node->token_pos(), |
2063 owner()->try_index(), | |
2064 name, | 2047 name, |
2065 Token::kINDEX, | 2048 Token::kINDEX, |
2066 arguments, | 2049 arguments, |
2067 Array::ZoneHandle(), | 2050 Array::ZoneHandle(), |
2068 checked_argument_count); | 2051 checked_argument_count); |
2069 ReturnComputation(load); | 2052 ReturnComputation(load); |
2070 } | 2053 } |
2071 | 2054 |
2072 | 2055 |
2073 Computation* EffectGraphVisitor::BuildStoreIndexedValues( | 2056 Computation* EffectGraphVisitor::BuildStoreIndexedValues( |
(...skipping 21 matching lines...) Expand all Loading... |
2095 for_value.value())); | 2078 for_value.value())); |
2096 } else { | 2079 } else { |
2097 value = for_value.value(); | 2080 value = for_value.value(); |
2098 } | 2081 } |
2099 arguments->Add(PushArgument(value)); | 2082 arguments->Add(PushArgument(value)); |
2100 | 2083 |
2101 const intptr_t checked_argument_count = 1; | 2084 const intptr_t checked_argument_count = 1; |
2102 const String& name = | 2085 const String& name = |
2103 String::ZoneHandle(Symbols::New(Token::Str(Token::kASSIGN_INDEX))); | 2086 String::ZoneHandle(Symbols::New(Token::Str(Token::kASSIGN_INDEX))); |
2104 InstanceCallComp* store = new InstanceCallComp(node->token_pos(), | 2087 InstanceCallComp* store = new InstanceCallComp(node->token_pos(), |
2105 owner()->try_index(), | |
2106 name, | 2088 name, |
2107 Token::kASSIGN_INDEX, | 2089 Token::kASSIGN_INDEX, |
2108 arguments, | 2090 arguments, |
2109 Array::ZoneHandle(), | 2091 Array::ZoneHandle(), |
2110 checked_argument_count); | 2092 checked_argument_count); |
2111 if (result_is_needed) { | 2093 if (result_is_needed) { |
2112 Do(store); | 2094 Do(store); |
2113 return BuildLoadLocal(*owner()->parsed_function().expression_temp_var()); | 2095 return BuildLoadLocal(*owner()->parsed_function().expression_temp_var()); |
2114 } else { | 2096 } else { |
2115 return store; | 2097 return store; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2151 void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) { | 2133 void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) { |
2152 LocalScope* scope = node->scope(); | 2134 LocalScope* scope = node->scope(); |
2153 const intptr_t num_context_variables = | 2135 const intptr_t num_context_variables = |
2154 (scope != NULL) ? scope->num_context_variables() : 0; | 2136 (scope != NULL) ? scope->num_context_variables() : 0; |
2155 int previous_context_level = owner()->context_level(); | 2137 int previous_context_level = owner()->context_level(); |
2156 if (num_context_variables > 0) { | 2138 if (num_context_variables > 0) { |
2157 // The loop local scope declares variables that are captured. | 2139 // The loop local scope declares variables that are captured. |
2158 // Allocate and chain a new context. | 2140 // Allocate and chain a new context. |
2159 // Allocate context computation (uses current CTX) | 2141 // Allocate context computation (uses current CTX) |
2160 Value* allocated_context = | 2142 Value* allocated_context = |
2161 Bind(new AllocateContextComp(node->token_pos(), | 2143 Bind(new AllocateContextComp(node->token_pos(), num_context_variables)); |
2162 owner()->try_index(), | |
2163 num_context_variables)); | |
2164 | 2144 |
2165 // If this node_sequence is the body of the function being compiled, and if | 2145 // If this node_sequence is the body of the function being compiled, and if |
2166 // this function is not a closure, do not link the current context as the | 2146 // this function is not a closure, do not link the current context as the |
2167 // parent of the newly allocated context, as it is not accessible. Instead, | 2147 // parent of the newly allocated context, as it is not accessible. Instead, |
2168 // save it in a pre-allocated variable and restore it on exit. | 2148 // save it in a pre-allocated variable and restore it on exit. |
2169 if (MustSaveRestoreContext(node)) { | 2149 if (MustSaveRestoreContext(node)) { |
2170 Value* current_context = Bind(new CurrentContextComp()); | 2150 Value* current_context = Bind(new CurrentContextComp()); |
2171 Do(BuildStoreLocal(*owner()->parsed_function().saved_context_var(), | 2151 Do(BuildStoreLocal(*owner()->parsed_function().saved_context_var(), |
2172 current_context)); | 2152 current_context)); |
2173 Value* null_context = Bind(Constant(Object::ZoneHandle())); | 2153 Value* null_context = Bind(Constant(Object::ZoneHandle())); |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2301 void EffectGraphVisitor::VisitTryCatchNode(TryCatchNode* node) { | 2281 void EffectGraphVisitor::VisitTryCatchNode(TryCatchNode* node) { |
2302 intptr_t old_try_index = owner()->try_index(); | 2282 intptr_t old_try_index = owner()->try_index(); |
2303 intptr_t try_index = owner()->AllocateTryIndex(); | 2283 intptr_t try_index = owner()->AllocateTryIndex(); |
2304 owner()->set_try_index(try_index); | 2284 owner()->set_try_index(try_index); |
2305 | 2285 |
2306 // Preserve CTX into local variable '%saved_context'. | 2286 // Preserve CTX into local variable '%saved_context'. |
2307 BuildStoreContext(node->context_var()); | 2287 BuildStoreContext(node->context_var()); |
2308 | 2288 |
2309 EffectGraphVisitor for_try_block(owner(), temp_index()); | 2289 EffectGraphVisitor for_try_block(owner(), temp_index()); |
2310 node->try_block()->Visit(&for_try_block); | 2290 node->try_block()->Visit(&for_try_block); |
2311 Append(for_try_block); | 2291 |
| 2292 if (for_try_block.is_open()) { |
| 2293 JoinEntryInstr* after_try = new JoinEntryInstr(old_try_index); |
| 2294 for_try_block.Goto(after_try); |
| 2295 for_try_block.exit_ = after_try; |
| 2296 } |
| 2297 |
| 2298 JoinEntryInstr* try_entry = new JoinEntryInstr(try_index); |
| 2299 |
| 2300 Goto(try_entry); |
| 2301 AppendFragment(try_entry, for_try_block); |
| 2302 exit_ = for_try_block.exit_; |
2312 | 2303 |
2313 // We are done generating code for the try block. | 2304 // We are done generating code for the try block. |
2314 owner()->set_try_index(old_try_index); | 2305 owner()->set_try_index(old_try_index); |
2315 | 2306 |
2316 CatchClauseNode* catch_block = node->catch_block(); | 2307 CatchClauseNode* catch_block = node->catch_block(); |
2317 if (catch_block != NULL) { | 2308 if (catch_block != NULL) { |
2318 // Set the corresponding try index for this catch block so | 2309 // Set the corresponding try index for this catch block so |
2319 // that we can set the appropriate handler pc when we generate | 2310 // that we can set the appropriate handler pc when we generate |
2320 // code for this catch block. | 2311 // code for this catch block. |
2321 catch_block->set_try_index(try_index); | 2312 catch_block->set_try_index(try_index); |
2322 EffectGraphVisitor for_catch_block(owner(), temp_index()); | 2313 EffectGraphVisitor for_catch_block(owner(), temp_index()); |
2323 catch_block->Visit(&for_catch_block); | 2314 catch_block->Visit(&for_catch_block); |
2324 TargetEntryInstr* catch_entry = new TargetEntryInstr(try_index); | 2315 TargetEntryInstr* catch_entry = new TargetEntryInstr(old_try_index, |
| 2316 try_index); |
2325 owner()->AddCatchEntry(catch_entry); | 2317 owner()->AddCatchEntry(catch_entry); |
2326 ASSERT(!for_catch_block.is_open()); | 2318 ASSERT(!for_catch_block.is_open()); |
2327 AppendFragment(catch_entry, for_catch_block); | 2319 AppendFragment(catch_entry, for_catch_block); |
2328 if (node->end_catch_label() != NULL) { | 2320 if (node->end_catch_label() != NULL) { |
2329 JoinEntryInstr* join = node->end_catch_label()->join_for_continue(); | 2321 JoinEntryInstr* join = node->end_catch_label()->join_for_continue(); |
2330 if (join != NULL) { | 2322 if (join != NULL) { |
2331 if (is_open()) Goto(join); | 2323 if (is_open()) Goto(join); |
2332 exit_ = join; | 2324 exit_ = join; |
2333 } | 2325 } |
2334 } | 2326 } |
2335 } | 2327 } |
2336 | 2328 |
2337 // Generate code for the finally block if one exists. | 2329 // Generate code for the finally block if one exists. |
2338 if ((node->finally_block() != NULL) && is_open()) { | 2330 if ((node->finally_block() != NULL) && is_open()) { |
2339 EffectGraphVisitor for_finally_block(owner(), temp_index()); | 2331 EffectGraphVisitor for_finally_block(owner(), temp_index()); |
2340 node->finally_block()->Visit(&for_finally_block); | 2332 node->finally_block()->Visit(&for_finally_block); |
2341 Append(for_finally_block); | 2333 Append(for_finally_block); |
2342 } | 2334 } |
2343 } | 2335 } |
2344 | 2336 |
2345 | 2337 |
2346 void EffectGraphVisitor::BuildThrowNode(ThrowNode* node) { | 2338 void EffectGraphVisitor::BuildThrowNode(ThrowNode* node) { |
2347 ValueGraphVisitor for_exception(owner(), temp_index()); | 2339 ValueGraphVisitor for_exception(owner(), temp_index()); |
2348 node->exception()->Visit(&for_exception); | 2340 node->exception()->Visit(&for_exception); |
2349 Append(for_exception); | 2341 Append(for_exception); |
2350 PushArgument(for_exception.value()); | 2342 PushArgument(for_exception.value()); |
2351 Instruction* instr = NULL; | 2343 Instruction* instr = NULL; |
2352 if (node->stacktrace() == NULL) { | 2344 if (node->stacktrace() == NULL) { |
2353 instr = new ThrowInstr(node->token_pos(), owner()->try_index()); | 2345 instr = new ThrowInstr(node->token_pos()); |
2354 } else { | 2346 } else { |
2355 ValueGraphVisitor for_stack_trace(owner(), temp_index()); | 2347 ValueGraphVisitor for_stack_trace(owner(), temp_index()); |
2356 node->stacktrace()->Visit(&for_stack_trace); | 2348 node->stacktrace()->Visit(&for_stack_trace); |
2357 Append(for_stack_trace); | 2349 Append(for_stack_trace); |
2358 PushArgument(for_stack_trace.value()); | 2350 PushArgument(for_stack_trace.value()); |
2359 instr = new ReThrowInstr(node->token_pos(), owner()->try_index()); | 2351 instr = new ReThrowInstr(node->token_pos()); |
2360 } | 2352 } |
2361 AddInstruction(instr); | 2353 AddInstruction(instr); |
2362 } | 2354 } |
2363 | 2355 |
2364 | 2356 |
2365 void EffectGraphVisitor::VisitThrowNode(ThrowNode* node) { | 2357 void EffectGraphVisitor::VisitThrowNode(ThrowNode* node) { |
2366 BuildThrowNode(node); | 2358 BuildThrowNode(node); |
2367 CloseFragment(); | 2359 CloseFragment(); |
2368 } | 2360 } |
2369 | 2361 |
2370 | 2362 |
2371 // A throw cannot be part of an expression, however, the parser may replace | 2363 // A throw cannot be part of an expression, however, the parser may replace |
2372 // certain expression nodes with a throw. In that case generate a literal null | 2364 // certain expression nodes with a throw. In that case generate a literal null |
2373 // so that the fragment is not closed in the middle of an expression. | 2365 // so that the fragment is not closed in the middle of an expression. |
2374 void ValueGraphVisitor::VisitThrowNode(ThrowNode* node) { | 2366 void ValueGraphVisitor::VisitThrowNode(ThrowNode* node) { |
2375 BuildThrowNode(node); | 2367 BuildThrowNode(node); |
2376 ReturnComputation(Constant(Instance::ZoneHandle())); | 2368 ReturnComputation(Constant(Instance::ZoneHandle())); |
2377 } | 2369 } |
2378 | 2370 |
2379 | 2371 |
2380 void EffectGraphVisitor::VisitInlinedFinallyNode(InlinedFinallyNode* node) { | 2372 void EffectGraphVisitor::VisitInlinedFinallyNode(InlinedFinallyNode* node) { |
2381 const intptr_t try_index = owner()->try_index(); | 2373 const intptr_t try_index = owner()->try_index(); |
2382 if (try_index >= 0) { | 2374 if (try_index >= 0) { |
2383 // We are about to generate code for an inlined finally block. Exceptions | 2375 // We are about to generate code for an inlined finally block. Exceptions |
2384 // thrown in this block of code should be treated as though they are | 2376 // thrown in this block of code should be treated as though they are |
2385 // thrown not from the current try block but the outer try block if any. | 2377 // thrown not from the current try block but the outer try block if any. |
2386 owner()->set_try_index((try_index - 1)); | 2378 owner()->set_try_index((try_index - 1)); |
2387 } | 2379 } |
2388 BuildLoadContext(node->context_var()); | 2380 BuildLoadContext(node->context_var()); |
| 2381 |
| 2382 JoinEntryInstr* finally_entry = new JoinEntryInstr(owner()->try_index()); |
2389 EffectGraphVisitor for_finally_block(owner(), temp_index()); | 2383 EffectGraphVisitor for_finally_block(owner(), temp_index()); |
2390 node->finally_block()->Visit(&for_finally_block); | 2384 node->finally_block()->Visit(&for_finally_block); |
2391 Append(for_finally_block); | 2385 |
2392 if (try_index >= 0) { | 2386 if (try_index >= 0) { |
2393 owner()->set_try_index(try_index); | 2387 owner()->set_try_index(try_index); |
2394 } | 2388 } |
| 2389 |
| 2390 if (for_finally_block.is_open()) { |
| 2391 JoinEntryInstr* after_finally = new JoinEntryInstr(owner()->try_index()); |
| 2392 for_finally_block.Goto(after_finally); |
| 2393 for_finally_block.exit_ = after_finally; |
| 2394 } |
| 2395 |
| 2396 Goto(finally_entry); |
| 2397 AppendFragment(finally_entry, for_finally_block); |
| 2398 exit_ = for_finally_block.exit_; |
2395 } | 2399 } |
2396 | 2400 |
2397 | 2401 |
2398 FlowGraph* FlowGraphBuilder::BuildGraph() { | 2402 FlowGraph* FlowGraphBuilder::BuildGraph() { |
2399 if (FLAG_print_ast) { | 2403 if (FLAG_print_ast) { |
2400 // Print the function ast before IL generation. | 2404 // Print the function ast before IL generation. |
2401 AstPrinter::PrintFunctionNodes(parsed_function()); | 2405 AstPrinter::PrintFunctionNodes(parsed_function()); |
2402 } | 2406 } |
2403 // Compilation can be nested, preserve the computation-id. | 2407 // Compilation can be nested, preserve the computation-id. |
2404 const Function& function = parsed_function().function(); | 2408 const Function& function = parsed_function().function(); |
2405 TargetEntryInstr* normal_entry = new TargetEntryInstr(); | 2409 TargetEntryInstr* normal_entry = new TargetEntryInstr( |
| 2410 CatchClauseNode::kInvalidTryIndex); |
2406 graph_entry_ = new GraphEntryInstr(normal_entry); | 2411 graph_entry_ = new GraphEntryInstr(normal_entry); |
2407 EffectGraphVisitor for_effect(this, 0); | 2412 EffectGraphVisitor for_effect(this, 0); |
2408 // TODO(kmillikin): We can eliminate stack checks in some cases (e.g., the | 2413 // TODO(kmillikin): We can eliminate stack checks in some cases (e.g., the |
2409 // stack check on entry for leaf routines). | 2414 // stack check on entry for leaf routines). |
2410 for_effect.Do(new CheckStackOverflowComp(function.token_pos(), | 2415 for_effect.Do(new CheckStackOverflowComp(function.token_pos())); |
2411 CatchClauseNode::kInvalidTryIndex)); | |
2412 parsed_function().node_sequence()->Visit(&for_effect); | 2416 parsed_function().node_sequence()->Visit(&for_effect); |
2413 AppendFragment(normal_entry, for_effect); | 2417 AppendFragment(normal_entry, for_effect); |
2414 // Check that the graph is properly terminated. | 2418 // Check that the graph is properly terminated. |
2415 ASSERT(!for_effect.is_open()); | 2419 ASSERT(!for_effect.is_open()); |
2416 return new FlowGraph(*this, graph_entry_); | 2420 return new FlowGraph(*this, graph_entry_); |
2417 } | 2421 } |
2418 | 2422 |
2419 | 2423 |
2420 void FlowGraphBuilder::Bailout(const char* reason) { | 2424 void FlowGraphBuilder::Bailout(const char* reason) { |
2421 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; | 2425 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; |
2422 const char* function_name = parsed_function_.function().ToCString(); | 2426 const char* function_name = parsed_function_.function().ToCString(); |
2423 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 2427 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
2424 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 2428 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
2425 OS::SNPrint(chars, len, kFormat, function_name, reason); | 2429 OS::SNPrint(chars, len, kFormat, function_name, reason); |
2426 const Error& error = Error::Handle( | 2430 const Error& error = Error::Handle( |
2427 LanguageError::New(String::Handle(String::New(chars)))); | 2431 LanguageError::New(String::Handle(String::New(chars)))); |
2428 Isolate::Current()->long_jump_base()->Jump(1, error); | 2432 Isolate::Current()->long_jump_base()->Jump(1, error); |
2429 } | 2433 } |
2430 | 2434 |
2431 | 2435 |
2432 } // namespace dart | 2436 } // namespace dart |
OLD | NEW |