| 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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 // and a pair of effect graph fragments with zero or one available exits. | 139 // and a pair of effect graph fragments with zero or one available exits. |
| 140 // We want to append the branch and (if necessary) a join node to this | 140 // We want to append the branch and (if necessary) a join node to this |
| 141 // graph fragment. | 141 // graph fragment. |
| 142 ASSERT(is_open()); | 142 ASSERT(is_open()); |
| 143 | 143 |
| 144 // 1. Connect the test to this graph. | 144 // 1. Connect the test to this graph. |
| 145 Append(test_fragment); | 145 Append(test_fragment); |
| 146 | 146 |
| 147 // 2. Connect the true and false bodies to the test and record their exits | 147 // 2. Connect the true and false bodies to the test and record their exits |
| 148 // (if any). | 148 // (if any). |
| 149 TargetEntryInstr* true_entry = new TargetEntryInstr(owner()->try_index()); | 149 BlockEntryInstr* true_entry = test_fragment.CreateTrueSuccessor(); |
| 150 *test_fragment.true_successor_address() = true_entry; | |
| 151 Instruction* true_exit = AppendFragment(true_entry, true_fragment); | 150 Instruction* true_exit = AppendFragment(true_entry, true_fragment); |
| 152 | 151 |
| 153 TargetEntryInstr* false_entry = new TargetEntryInstr(owner()->try_index()); | 152 BlockEntryInstr* false_entry = test_fragment.CreateFalseSuccessor(); |
| 154 *test_fragment.false_successor_address() = false_entry; | |
| 155 Instruction* false_exit = AppendFragment(false_entry, false_fragment); | 153 Instruction* false_exit = AppendFragment(false_entry, false_fragment); |
| 156 | 154 |
| 157 // 3. Add a join or select one (or neither) of the arms as exit. | 155 // 3. Add a join or select one (or neither) of the arms as exit. |
| 158 if (true_exit == NULL) { | 156 if (true_exit == NULL) { |
| 159 exit_ = false_exit; // May be NULL. | 157 exit_ = false_exit; // May be NULL. |
| 160 if (false_exit != NULL) temp_index_ = false_fragment.temp_index(); | 158 if (false_exit != NULL) temp_index_ = false_fragment.temp_index(); |
| 161 } else if (false_exit == NULL) { | 159 } else if (false_exit == NULL) { |
| 162 exit_ = true_exit; | 160 exit_ = true_exit; |
| 163 temp_index_ = true_fragment.temp_index(); | 161 temp_index_ = true_fragment.temp_index(); |
| 164 } else { | 162 } else { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 175 void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment, | 173 void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment, |
| 176 const EffectGraphVisitor& body_fragment) { | 174 const EffectGraphVisitor& body_fragment) { |
| 177 // We have: a test graph fragment with zero, one, or two available exits; | 175 // We have: a test graph fragment with zero, one, or two available exits; |
| 178 // and an effect graph fragment with zero or one available exits. We want | 176 // and an effect graph fragment with zero or one available exits. We want |
| 179 // to append the 'while loop' consisting of the test graph fragment as | 177 // to append the 'while loop' consisting of the test graph fragment as |
| 180 // condition and the effect graph fragment as body. | 178 // condition and the effect graph fragment as body. |
| 181 ASSERT(is_open()); | 179 ASSERT(is_open()); |
| 182 | 180 |
| 183 // 1. Connect the body to the test if it is reachable, and if so record | 181 // 1. Connect the body to the test if it is reachable, and if so record |
| 184 // its exit (if any). | 182 // its exit (if any). |
| 185 TargetEntryInstr* body_entry = new TargetEntryInstr(owner()->try_index()); | 183 BlockEntryInstr* body_entry = test_fragment.CreateTrueSuccessor(); |
| 186 *test_fragment.true_successor_address() = body_entry; | |
| 187 Instruction* body_exit = AppendFragment(body_entry, body_fragment); | 184 Instruction* body_exit = AppendFragment(body_entry, body_fragment); |
| 188 | 185 |
| 189 // 2. Connect the test to this graph, including the body if reachable and | 186 // 2. Connect the test to this graph, including the body if reachable and |
| 190 // using a fresh join node if the body is reachable and has an open exit. | 187 // using a fresh join node if the body is reachable and has an open exit. |
| 191 if (body_exit == NULL) { | 188 if (body_exit == NULL) { |
| 192 Append(test_fragment); | 189 Append(test_fragment); |
| 193 } else { | 190 } else { |
| 194 JoinEntryInstr* join = new JoinEntryInstr(owner()->try_index()); | 191 JoinEntryInstr* join = new JoinEntryInstr(owner()->try_index()); |
| 195 join->set_next(test_fragment.entry()); | 192 join->set_next(test_fragment.entry()); |
| 196 Goto(join); | 193 Goto(join); |
| 197 body_exit->Goto(join); | 194 body_exit->Goto(join); |
| 198 } | 195 } |
| 199 | 196 |
| 200 // 3. Set the exit to the graph to be the false successor of the test, a | 197 // 3. Set the exit to the graph to be the false successor of the test, a |
| 201 // fresh target node | 198 // fresh target node |
| 202 exit_ = *test_fragment.false_successor_address() = | 199 |
| 203 new TargetEntryInstr(owner()->try_index()); | 200 exit_ = test_fragment.CreateFalseSuccessor(); |
| 204 } | 201 } |
| 205 | 202 |
| 206 | 203 |
| 207 PushArgumentInstr* EffectGraphVisitor::PushArgument(Value* value) { | 204 PushArgumentInstr* EffectGraphVisitor::PushArgument(Value* value) { |
| 208 PushArgumentInstr* result = new PushArgumentInstr(value); | 205 PushArgumentInstr* result = new PushArgumentInstr(value); |
| 209 AddInstruction(result); | 206 AddInstruction(result); |
| 210 return result; | 207 return result; |
| 211 } | 208 } |
| 212 | 209 |
| 213 | 210 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 } | 256 } |
| 260 | 257 |
| 261 | 258 |
| 262 // Loads context saved in 'context_variable' into the current context. | 259 // Loads context saved in 'context_variable' into the current context. |
| 263 void EffectGraphVisitor::BuildLoadContext(const LocalVariable& variable) { | 260 void EffectGraphVisitor::BuildLoadContext(const LocalVariable& variable) { |
| 264 Value* load_saved_context = Bind(BuildLoadLocal(variable)); | 261 Value* load_saved_context = Bind(BuildLoadLocal(variable)); |
| 265 Do(new StoreContextComp(load_saved_context)); | 262 Do(new StoreContextComp(load_saved_context)); |
| 266 } | 263 } |
| 267 | 264 |
| 268 | 265 |
| 266 void TestGraphVisitor::ConnectBranchesTo( |
| 267 const GrowableArray<TargetEntryInstr**>& branches, |
| 268 JoinEntryInstr* join) const { |
| 269 ASSERT(!branches.is_empty()); |
| 270 for (intptr_t i = 0; i < branches.length(); i++) { |
| 271 TargetEntryInstr* target = new TargetEntryInstr(owner()->try_index()); |
| 272 *(branches[i]) = target; |
| 273 target->Goto(join); |
| 274 } |
| 275 } |
| 276 |
| 277 |
| 278 void TestGraphVisitor::IfTrueGoto(JoinEntryInstr* join) const { |
| 279 ConnectBranchesTo(true_successor_addresses_, join); |
| 280 } |
| 281 |
| 282 |
| 283 void TestGraphVisitor::IfFalseGoto(JoinEntryInstr* join) const { |
| 284 ConnectBranchesTo(false_successor_addresses_, join); |
| 285 } |
| 286 |
| 287 |
| 288 BlockEntryInstr* TestGraphVisitor::CreateSuccessorFor( |
| 289 const GrowableArray<TargetEntryInstr**>& branches) const { |
| 290 ASSERT(!branches.is_empty()); |
| 291 |
| 292 if (branches.length() == 1) { |
| 293 TargetEntryInstr* target = new TargetEntryInstr(owner()->try_index()); |
| 294 *(branches[0]) = target; |
| 295 return target; |
| 296 } |
| 297 |
| 298 JoinEntryInstr* join = new JoinEntryInstr(owner()->try_index()); |
| 299 ConnectBranchesTo(branches, join); |
| 300 return join; |
| 301 } |
| 302 |
| 303 |
| 304 BlockEntryInstr* TestGraphVisitor::CreateTrueSuccessor() const { |
| 305 return CreateSuccessorFor(true_successor_addresses_); |
| 306 } |
| 307 |
| 308 |
| 309 BlockEntryInstr* TestGraphVisitor::CreateFalseSuccessor() const { |
| 310 return CreateSuccessorFor(false_successor_addresses_); |
| 311 } |
| 312 |
| 313 |
| 269 void TestGraphVisitor::ReturnValue(Value* value) { | 314 void TestGraphVisitor::ReturnValue(Value* value) { |
| 270 if (FLAG_enable_type_checks) { | 315 if (FLAG_enable_type_checks) { |
| 271 value = Bind(new AssertBooleanComp(condition_token_pos(), value)); | 316 value = Bind(new AssertBooleanComp(condition_token_pos(), value)); |
| 272 } | 317 } |
| 273 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 318 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 274 Value* constant_true = Bind(new ConstantComp(bool_true)); | 319 Value* constant_true = Bind(new ConstantComp(bool_true)); |
| 275 StrictCompareComp* comp = | 320 StrictCompareComp* comp = |
| 276 new StrictCompareComp(Token::kEQ_STRICT, value, constant_true); | 321 new StrictCompareComp(Token::kEQ_STRICT, value, constant_true); |
| 277 BranchInstr* branch = new BranchInstr(comp); | 322 BranchInstr* branch = new BranchInstr(comp); |
| 278 AddInstruction(branch); | 323 AddInstruction(branch); |
| 279 CloseFragment(); | 324 CloseFragment(); |
| 280 true_successor_address_ = branch->true_successor_address(); | 325 |
| 281 false_successor_address_ = branch->false_successor_address(); | 326 true_successor_addresses_.Add(branch->true_successor_address()); |
| 327 false_successor_addresses_.Add(branch->false_successor_address()); |
| 282 } | 328 } |
| 283 | 329 |
| 284 | 330 |
| 285 void TestGraphVisitor::MergeBranchWithComparison(ComparisonComp* comp) { | 331 void TestGraphVisitor::MergeBranchWithComparison(ComparisonComp* comp) { |
| 286 ASSERT(!FLAG_enable_type_checks); | 332 ASSERT(!FLAG_enable_type_checks); |
| 287 ControlInstruction* branch; | 333 ControlInstruction* branch; |
| 288 if (Token::IsStrictEqualityOperator(comp->kind())) { | 334 if (Token::IsStrictEqualityOperator(comp->kind())) { |
| 289 branch = new BranchInstr(new StrictCompareComp(comp->kind(), | 335 branch = new BranchInstr(new StrictCompareComp(comp->kind(), |
| 290 comp->left(), | 336 comp->left(), |
| 291 comp->right())); | 337 comp->right())); |
| 292 } else if (Token::IsEqualityOperator(comp->kind()) && | 338 } else if (Token::IsEqualityOperator(comp->kind()) && |
| 293 (comp->left()->BindsToConstantNull() || | 339 (comp->left()->BindsToConstantNull() || |
| 294 comp->right()->BindsToConstantNull())) { | 340 comp->right()->BindsToConstantNull())) { |
| 295 branch = new BranchInstr(new StrictCompareComp( | 341 branch = new BranchInstr(new StrictCompareComp( |
| 296 (comp->kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT, | 342 (comp->kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT, |
| 297 comp->left(), | 343 comp->left(), |
| 298 comp->right())); | 344 comp->right())); |
| 299 } else { | 345 } else { |
| 300 branch = new BranchInstr(comp); | 346 branch = new BranchInstr(comp); |
| 301 } | 347 } |
| 302 AddInstruction(branch); | 348 AddInstruction(branch); |
| 303 CloseFragment(); | 349 CloseFragment(); |
| 304 true_successor_address_ = branch->true_successor_address(); | 350 true_successor_addresses_.Add(branch->true_successor_address()); |
| 305 false_successor_address_ = branch->false_successor_address(); | 351 false_successor_addresses_.Add(branch->false_successor_address()); |
| 306 } | 352 } |
| 307 | 353 |
| 308 | 354 |
| 309 void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateComp* comp) { | 355 void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateComp* comp) { |
| 310 ASSERT(!FLAG_enable_type_checks); | 356 ASSERT(!FLAG_enable_type_checks); |
| 311 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 357 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 312 Value* constant_true = Bind(new ConstantComp(bool_true)); | 358 Value* constant_true = Bind(new ConstantComp(bool_true)); |
| 313 BranchInstr* branch = new BranchInstr( | 359 BranchInstr* branch = new BranchInstr( |
| 314 new StrictCompareComp(Token::kNE_STRICT, | 360 new StrictCompareComp(Token::kNE_STRICT, |
| 315 comp->value(), | 361 comp->value(), |
| 316 constant_true)); | 362 constant_true)); |
| 317 AddInstruction(branch); | 363 AddInstruction(branch); |
| 318 CloseFragment(); | 364 CloseFragment(); |
| 319 true_successor_address_ = branch->true_successor_address(); | 365 true_successor_addresses_.Add(branch->true_successor_address()); |
| 320 false_successor_address_ = branch->false_successor_address(); | 366 false_successor_addresses_.Add(branch->false_successor_address()); |
| 321 } | 367 } |
| 322 | 368 |
| 323 | 369 |
| 324 void TestGraphVisitor::ReturnComputation(Computation* computation) { | 370 void TestGraphVisitor::ReturnComputation(Computation* computation) { |
| 325 if (!FLAG_enable_type_checks) { | 371 if (!FLAG_enable_type_checks) { |
| 326 if (computation->AsComparison() != NULL) { | 372 if (computation->AsComparison() != NULL) { |
| 327 MergeBranchWithComparison(computation->AsComparison()); | 373 MergeBranchWithComparison(computation->AsComparison()); |
| 328 return; | 374 return; |
| 329 } | 375 } |
| 330 if (computation->IsBooleanNegate()) { | 376 if (computation->IsBooleanNegate()) { |
| 331 MergeBranchWithNegate(computation->AsBooleanNegate()); | 377 MergeBranchWithNegate(computation->AsBooleanNegate()); |
| 332 return; | 378 return; |
| 333 } | 379 } |
| 334 } | 380 } |
| 335 ReturnValue(Bind(computation)); | 381 ReturnValue(Bind(computation)); |
| 336 } | 382 } |
| 337 | 383 |
| 338 | 384 |
| 385 // Special handling for AND/OR. |
| 386 void TestGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) { |
| 387 InlineBailout("TestGraphVisitor::VisitBinaryOpNode"); |
| 388 |
| 389 // Operators "&&" and "||" cannot be overloaded therefore do not call |
| 390 // operator. |
| 391 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { |
| 392 TestGraphVisitor for_left(owner(), |
| 393 temp_index(), |
| 394 node->left()->token_pos()); |
| 395 node->left()->Visit(&for_left); |
| 396 |
| 397 TestGraphVisitor for_right(owner(), |
| 398 temp_index(), |
| 399 node->right()->token_pos()); |
| 400 node->right()->Visit(&for_right); |
| 401 |
| 402 Append(for_left); |
| 403 |
| 404 if (node->kind() == Token::kAND) { |
| 405 AppendFragment(for_left.CreateTrueSuccessor(), for_right); |
| 406 true_successor_addresses_.AddArray(for_right.true_successor_addresses_); |
| 407 false_successor_addresses_.AddArray(for_left.false_successor_addresses_); |
| 408 false_successor_addresses_.AddArray(for_right.false_successor_addresses_); |
| 409 } else { |
| 410 ASSERT(node->kind() == Token::kOR); |
| 411 AppendFragment(for_left.CreateFalseSuccessor(), for_right); |
| 412 false_successor_addresses_.AddArray(for_right.false_successor_addresses_); |
| 413 true_successor_addresses_.AddArray(for_left.true_successor_addresses_); |
| 414 true_successor_addresses_.AddArray(for_right.true_successor_addresses_); |
| 415 } |
| 416 CloseFragment(); |
| 417 return; |
| 418 } |
| 419 ValueGraphVisitor::VisitBinaryOpNode(node); |
| 420 } |
| 421 |
| 422 |
| 339 void EffectGraphVisitor::Bailout(const char* reason) { | 423 void EffectGraphVisitor::Bailout(const char* reason) { |
| 340 owner()->Bailout(reason); | 424 owner()->Bailout(reason); |
| 341 } | 425 } |
| 342 | 426 |
| 343 | 427 |
| 344 void EffectGraphVisitor::InlineBailout(const char* reason) { | 428 void EffectGraphVisitor::InlineBailout(const char* reason) { |
| 345 if (owner()->InInliningContext()) owner()->Bailout(reason); | 429 if (owner()->InInliningContext()) owner()->Bailout(reason); |
| 346 } | 430 } |
| 347 | 431 |
| 348 | 432 |
| (...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1017 AppendFragment(statement_start, for_case_statements); | 1101 AppendFragment(statement_start, for_case_statements); |
| 1018 if (is_open() && (len == 0)) { | 1102 if (is_open() && (len == 0)) { |
| 1019 ASSERT(node->contains_default()); | 1103 ASSERT(node->contains_default()); |
| 1020 // Default only case node. | 1104 // Default only case node. |
| 1021 Goto(statement_start); | 1105 Goto(statement_start); |
| 1022 exit_ = statement_exit; | 1106 exit_ = statement_exit; |
| 1023 return; | 1107 return; |
| 1024 } | 1108 } |
| 1025 | 1109 |
| 1026 // Generate instructions for all case expressions. | 1110 // Generate instructions for all case expressions. |
| 1027 TargetEntryInstr** previous_false_address = NULL; | 1111 TargetEntryInstr* next_target = NULL; |
| 1028 for (intptr_t i = 0; i < len; i++) { | 1112 for (intptr_t i = 0; i < len; i++) { |
| 1029 AstNode* case_expr = node->case_expressions()->NodeAt(i); | 1113 AstNode* case_expr = node->case_expressions()->NodeAt(i); |
| 1030 TestGraphVisitor for_case_expression(owner(), | 1114 TestGraphVisitor for_case_expression(owner(), |
| 1031 temp_index(), | 1115 temp_index(), |
| 1032 case_expr->token_pos()); | 1116 case_expr->token_pos()); |
| 1033 case_expr->Visit(&for_case_expression); | 1117 case_expr->Visit(&for_case_expression); |
| 1034 if (i == 0) { | 1118 if (i == 0) { |
| 1035 // Append only the first one, everything else is connected from it. | 1119 // Append only the first one, everything else is connected from it. |
| 1036 Append(for_case_expression); | 1120 Append(for_case_expression); |
| 1037 } else { | 1121 } else { |
| 1038 TargetEntryInstr* case_entry_target = | 1122 ASSERT(next_target != NULL); |
| 1039 new TargetEntryInstr(owner()->try_index()); | 1123 AppendFragment(next_target, for_case_expression); |
| 1040 AppendFragment(case_entry_target, for_case_expression); | |
| 1041 *previous_false_address = case_entry_target; | |
| 1042 } | 1124 } |
| 1043 TargetEntryInstr* true_target = | 1125 for_case_expression.IfTrueGoto(statement_start); |
| 1044 new TargetEntryInstr(owner()->try_index()); | 1126 next_target = for_case_expression.CreateFalseSuccessor()->AsTargetEntry(); |
| 1045 *for_case_expression.true_successor_address() = true_target; | |
| 1046 true_target->Goto(statement_start); | |
| 1047 previous_false_address = for_case_expression.false_successor_address(); | |
| 1048 } | 1127 } |
| 1049 | 1128 |
| 1050 // Once a test fragment has been added, this fragment is closed. | 1129 // Once a test fragment has been added, this fragment is closed. |
| 1051 ASSERT(!is_open()); | 1130 ASSERT(!is_open()); |
| 1052 | 1131 |
| 1053 Instruction* exit_instruction = NULL; | 1132 Instruction* exit_instruction = NULL; |
| 1054 // Handle last (or only) case: false goes to exit or to statement if this | 1133 // Handle last (or only) case: false goes to exit or to statement if this |
| 1055 // node contains default. | 1134 // node contains default. |
| 1056 if (len > 0) { | 1135 if (len > 0) { |
| 1057 TargetEntryInstr* false_target = | 1136 ASSERT(next_target != NULL); |
| 1058 new TargetEntryInstr(owner()->try_index()); | |
| 1059 *previous_false_address = false_target; | |
| 1060 if (node->contains_default()) { | 1137 if (node->contains_default()) { |
| 1061 // True and false go to statement start. | 1138 // True and false go to statement start. |
| 1062 false_target->Goto(statement_start); | 1139 next_target->Goto(statement_start); |
| 1063 exit_instruction = statement_exit; | 1140 exit_instruction = statement_exit; |
| 1064 } else { | 1141 } else { |
| 1065 if (statement_exit != NULL) { | 1142 if (statement_exit != NULL) { |
| 1066 JoinEntryInstr* join = new JoinEntryInstr(owner()->try_index()); | 1143 JoinEntryInstr* join = new JoinEntryInstr(owner()->try_index()); |
| 1067 statement_exit->Goto(join); | 1144 statement_exit->Goto(join); |
| 1068 false_target->Goto(join); | 1145 next_target->Goto(join); |
| 1069 exit_instruction = join; | 1146 exit_instruction = join; |
| 1070 } else { | 1147 } else { |
| 1071 exit_instruction = false_target; | 1148 exit_instruction = next_target; |
| 1072 } | 1149 } |
| 1073 } | 1150 } |
| 1074 } else { | 1151 } else { |
| 1075 // A CaseNode without case expressions must contain default. | 1152 // A CaseNode without case expressions must contain default. |
| 1076 ASSERT(node->contains_default()); | 1153 ASSERT(node->contains_default()); |
| 1077 Goto(statement_start); | 1154 Goto(statement_start); |
| 1078 exit_instruction = statement_exit; | 1155 exit_instruction = statement_exit; |
| 1079 } | 1156 } |
| 1080 | 1157 |
| 1081 ASSERT(!is_open()); | 1158 ASSERT(!is_open()); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1153 | 1230 |
| 1154 JoinEntryInstr* join = node->label()->join_for_continue(); | 1231 JoinEntryInstr* join = node->label()->join_for_continue(); |
| 1155 if ((body_exit != NULL) || (join != NULL)) { | 1232 if ((body_exit != NULL) || (join != NULL)) { |
| 1156 if (join == NULL) join = new JoinEntryInstr(owner()->try_index()); | 1233 if (join == NULL) join = new JoinEntryInstr(owner()->try_index()); |
| 1157 join->set_next(for_test.entry()); | 1234 join->set_next(for_test.entry()); |
| 1158 if (body_exit != NULL) { | 1235 if (body_exit != NULL) { |
| 1159 body_exit->Goto(join); | 1236 body_exit->Goto(join); |
| 1160 } | 1237 } |
| 1161 } | 1238 } |
| 1162 | 1239 |
| 1163 TargetEntryInstr* back_target_entry = | 1240 |
| 1164 new TargetEntryInstr(owner()->try_index()); | 1241 for_test.IfTrueGoto(body_entry_join); |
| 1165 *for_test.true_successor_address() = back_target_entry; | |
| 1166 back_target_entry->Goto(body_entry_join); | |
| 1167 TargetEntryInstr* loop_exit_target = | |
| 1168 new TargetEntryInstr(owner()->try_index()); | |
| 1169 *for_test.false_successor_address() = loop_exit_target; | |
| 1170 if (node->label()->join_for_break() == NULL) { | 1242 if (node->label()->join_for_break() == NULL) { |
| 1171 exit_ = loop_exit_target; | 1243 exit_ = for_test.CreateFalseSuccessor(); |
| 1172 } else { | 1244 } else { |
| 1173 loop_exit_target->Goto(node->label()->join_for_break()); | 1245 for_test.IfFalseGoto(node->label()->join_for_break()); |
| 1174 exit_ = node->label()->join_for_break(); | 1246 exit_ = node->label()->join_for_break(); |
| 1175 } | 1247 } |
| 1176 } | 1248 } |
| 1177 | 1249 |
| 1178 | 1250 |
| 1179 // A ForNode can contain break and continue jumps. 'break' joins to | 1251 // A ForNode can contain break and continue jumps. 'break' joins to |
| 1180 // ForNode exit, 'continue' joins at increment entry. The fragment is composed | 1252 // ForNode exit, 'continue' joins at increment entry. The fragment is composed |
| 1181 // as follows: | 1253 // as follows: |
| 1182 // a) [ initializer ] | 1254 // a) [ initializer ] |
| 1183 // b) loop-join | 1255 // b) loop-join |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1234 if (node->condition() == NULL) { | 1306 if (node->condition() == NULL) { |
| 1235 // Endless loop, no test. | 1307 // Endless loop, no test. |
| 1236 JoinEntryInstr* body_entry = new JoinEntryInstr(owner()->try_index()); | 1308 JoinEntryInstr* body_entry = new JoinEntryInstr(owner()->try_index()); |
| 1237 AppendFragment(body_entry, for_body); | 1309 AppendFragment(body_entry, for_body); |
| 1238 Goto(body_entry); | 1310 Goto(body_entry); |
| 1239 if (node->label()->join_for_break() != NULL) { | 1311 if (node->label()->join_for_break() != NULL) { |
| 1240 // Control flow of ForLoop continues into join_for_break. | 1312 // Control flow of ForLoop continues into join_for_break. |
| 1241 exit_ = node->label()->join_for_break(); | 1313 exit_ = node->label()->join_for_break(); |
| 1242 } | 1314 } |
| 1243 } else { | 1315 } else { |
| 1244 TargetEntryInstr* loop_exit = new TargetEntryInstr(owner()->try_index()); | |
| 1245 TestGraphVisitor for_test(owner(), | 1316 TestGraphVisitor for_test(owner(), |
| 1246 temp_index(), | 1317 temp_index(), |
| 1247 node->condition()->token_pos()); | 1318 node->condition()->token_pos()); |
| 1248 node->condition()->Visit(&for_test); | 1319 node->condition()->Visit(&for_test); |
| 1249 Append(for_test); | 1320 Append(for_test); |
| 1250 TargetEntryInstr* body_entry = new TargetEntryInstr(owner()->try_index()); | 1321 |
| 1322 BlockEntryInstr* body_entry = for_test.CreateTrueSuccessor(); |
| 1251 AppendFragment(body_entry, for_body); | 1323 AppendFragment(body_entry, for_body); |
| 1252 *for_test.true_successor_address() = body_entry; | 1324 |
| 1253 *for_test.false_successor_address() = loop_exit; | |
| 1254 if (node->label()->join_for_break() == NULL) { | 1325 if (node->label()->join_for_break() == NULL) { |
| 1255 exit_ = loop_exit; | 1326 exit_ = for_test.CreateFalseSuccessor(); |
| 1256 } else { | 1327 } else { |
| 1257 loop_exit->Goto(node->label()->join_for_break()); | 1328 for_test.IfFalseGoto(node->label()->join_for_break()); |
| 1258 exit_ = node->label()->join_for_break(); | 1329 exit_ = node->label()->join_for_break(); |
| 1259 } | 1330 } |
| 1260 } | 1331 } |
| 1261 } | 1332 } |
| 1262 | 1333 |
| 1263 | 1334 |
| 1264 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { | 1335 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { |
| 1265 InlineBailout("EffectGraphVisitor::VisitJumpNode"); | 1336 InlineBailout("EffectGraphVisitor::VisitJumpNode"); |
| 1266 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { | 1337 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { |
| 1267 EffectGraphVisitor for_effect(owner(), temp_index()); | 1338 EffectGraphVisitor for_effect(owner(), temp_index()); |
| (...skipping 1271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2539 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 2610 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
| 2540 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 2611 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
| 2541 OS::SNPrint(chars, len, kFormat, function_name, reason); | 2612 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 2542 const Error& error = Error::Handle( | 2613 const Error& error = Error::Handle( |
| 2543 LanguageError::New(String::Handle(String::New(chars)))); | 2614 LanguageError::New(String::Handle(String::New(chars)))); |
| 2544 Isolate::Current()->long_jump_base()->Jump(1, error); | 2615 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2545 } | 2616 } |
| 2546 | 2617 |
| 2547 | 2618 |
| 2548 } // namespace dart | 2619 } // namespace dart |
| OLD | NEW |