| 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/flags.h" | 7 #include "vm/flags.h" |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 #include "vm/longjump.h" | 9 #include "vm/longjump.h" |
| 10 #include "vm/os.h" | 10 #include "vm/os.h" |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 true_successor_address_ = branch->true_successor_address(); | 127 true_successor_address_ = branch->true_successor_address(); |
| 128 false_successor_address_ = branch->false_successor_address(); | 128 false_successor_address_ = branch->false_successor_address(); |
| 129 } | 129 } |
| 130 | 130 |
| 131 | 131 |
| 132 void EffectGraphVisitor::Bailout(const char* reason) { | 132 void EffectGraphVisitor::Bailout(const char* reason) { |
| 133 owner()->Bailout(reason); | 133 owner()->Bailout(reason); |
| 134 } | 134 } |
| 135 | 135 |
| 136 | 136 |
| 137 // 'bailout' is a statement (without a semicolon), typically a return. | |
| 138 #define CHECK_ALIVE(bailout) \ | |
| 139 do { \ | |
| 140 if (!is_open()) { \ | |
| 141 bailout; \ | |
| 142 } \ | |
| 143 } while (false) | |
| 144 | |
| 145 | |
| 146 // <Statement> ::= Return { value: <Expression> | 137 // <Statement> ::= Return { value: <Expression> |
| 147 // inlined_finally_list: <InlinedFinally>* } | 138 // inlined_finally_list: <InlinedFinally>* } |
| 148 void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) { | 139 void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) { |
| 149 ValueGraphVisitor for_value(owner(), temp_index()); | 140 ValueGraphVisitor for_value(owner(), temp_index()); |
| 150 node->value()->Visit(&for_value); | 141 node->value()->Visit(&for_value); |
| 151 Append(for_value); | 142 Append(for_value); |
| 152 CHECK_ALIVE(return); | |
| 153 | 143 |
| 154 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { | 144 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { |
| 155 EffectGraphVisitor for_effect(owner(), for_value.temp_index()); | 145 EffectGraphVisitor for_effect(owner(), for_value.temp_index()); |
| 156 node->InlinedFinallyNodeAt(i)->Visit(&for_effect); | 146 node->InlinedFinallyNodeAt(i)->Visit(&for_effect); |
| 157 Append(for_effect); | 147 Append(for_effect); |
| 158 CHECK_ALIVE(return); | 148 if (!is_open()) return; |
| 159 } | 149 } |
| 160 | 150 |
| 161 Value* return_value = for_value.value(); | 151 Value* return_value = for_value.value(); |
| 162 if (FLAG_enable_type_checks) { | 152 if (FLAG_enable_type_checks) { |
| 163 const RawFunction::Kind kind = owner()->parsed_function().function().kind(); | 153 const RawFunction::Kind kind = owner()->parsed_function().function().kind(); |
| 164 // Implicit getters do not need a type check at return. | 154 // Implicit getters do not need a type check at return. |
| 165 if ((kind != RawFunction::kImplicitGetter) && | 155 if ((kind != RawFunction::kImplicitGetter) && |
| 166 (kind != RawFunction::kConstImplicitGetter)) { | 156 (kind != RawFunction::kConstImplicitGetter)) { |
| 167 const AbstractType& type = | 157 const AbstractType& type = |
| 168 AbstractType::ZoneHandle( | 158 AbstractType::ZoneHandle( |
| (...skipping 29 matching lines...) Expand all Loading... |
| 198 void EffectGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); } | 188 void EffectGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); } |
| 199 | 189 |
| 200 | 190 |
| 201 // <Expression> :: Assignable { expr: <Expression> | 191 // <Expression> :: Assignable { expr: <Expression> |
| 202 // type: AbstractType | 192 // type: AbstractType |
| 203 // dst_name: String } | 193 // dst_name: String } |
| 204 void EffectGraphVisitor::VisitAssignableNode(AssignableNode* node) { | 194 void EffectGraphVisitor::VisitAssignableNode(AssignableNode* node) { |
| 205 ValueGraphVisitor for_value(owner(), temp_index()); | 195 ValueGraphVisitor for_value(owner(), temp_index()); |
| 206 node->expr()->Visit(&for_value); | 196 node->expr()->Visit(&for_value); |
| 207 Append(for_value); | 197 Append(for_value); |
| 208 CHECK_ALIVE(return); | |
| 209 | |
| 210 AssertAssignableComp* assert = | 198 AssertAssignableComp* assert = |
| 211 new AssertAssignableComp(for_value.value(), node->type()); | 199 new AssertAssignableComp(for_value.value(), node->type()); |
| 212 ReturnComputation(assert); | 200 ReturnComputation(assert); |
| 213 } | 201 } |
| 214 | 202 |
| 215 | 203 |
| 216 // <Expression> :: BinaryOp { kind: Token::Kind | 204 // <Expression> :: BinaryOp { kind: Token::Kind |
| 217 // left: <Expression> | 205 // left: <Expression> |
| 218 // right: <Expression> } | 206 // right: <Expression> } |
| 219 void EffectGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) { | 207 void EffectGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) { |
| 220 // Operators "&&" and "||" cannot be overloaded therefore do not call | 208 // Operators "&&" and "||" cannot be overloaded therefore do not call |
| 221 // operator. | 209 // operator. |
| 222 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { | 210 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { |
| 223 Bailout("EffectGraphVisitor::VisitBinaryOpNode AND/OR"); | 211 Bailout("EffectGraphVisitor::VisitBinaryOpNode AND/OR"); |
| 224 } | 212 } |
| 225 ValueGraphVisitor for_left_value(owner(), temp_index()); | 213 ValueGraphVisitor for_left_value(owner(), temp_index()); |
| 226 node->left()->Visit(&for_left_value); | 214 node->left()->Visit(&for_left_value); |
| 227 Append(for_left_value); | 215 Append(for_left_value); |
| 228 CHECK_ALIVE(return); | |
| 229 ValueGraphVisitor for_right_value(owner(), for_left_value.temp_index()); | 216 ValueGraphVisitor for_right_value(owner(), for_left_value.temp_index()); |
| 230 node->right()->Visit(&for_right_value); | 217 node->right()->Visit(&for_right_value); |
| 231 Append(for_right_value); | 218 Append(for_right_value); |
| 232 CHECK_ALIVE(return); | |
| 233 ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2); | 219 ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2); |
| 234 arguments->Add(for_left_value.value()); | 220 arguments->Add(for_left_value.value()); |
| 235 arguments->Add(for_right_value.value()); | 221 arguments->Add(for_right_value.value()); |
| 236 InstanceCallComp* call = new InstanceCallComp(node->Name(), arguments); | 222 InstanceCallComp* call = new InstanceCallComp(node->Name(), arguments); |
| 237 ReturnComputation(call); | 223 ReturnComputation(call); |
| 238 } | 224 } |
| 239 | 225 |
| 240 | 226 |
| 241 void EffectGraphVisitor::VisitStringConcatNode(StringConcatNode* node) { | 227 void EffectGraphVisitor::VisitStringConcatNode(StringConcatNode* node) { |
| 242 Bailout("EffectGraphVisitor::VisitStringConcatNode"); | 228 Bailout("EffectGraphVisitor::VisitStringConcatNode"); |
| 243 } | 229 } |
| 244 | 230 |
| 245 | 231 |
| 246 // <Expression> :: Comparison { kind: Token::Kind | 232 // <Expression> :: Comparison { kind: Token::Kind |
| 247 // left: <Expression> | 233 // left: <Expression> |
| 248 // right: <Expression> } | 234 // right: <Expression> } |
| 249 void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) { | 235 void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) { |
| 250 if (Token::IsInstanceofOperator(node->kind())) { | 236 if (Token::IsInstanceofOperator(node->kind())) { |
| 251 Bailout("instanceof not yet implemented"); | 237 Bailout("instanceof not yet implemented"); |
| 252 } else if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) { | 238 } else if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) { |
| 253 Bailout("'==' or '!=' comparison not yet implemented"); | 239 Bailout("'==' or '!=' comparison not yet implemented"); |
| 254 } | 240 } |
| 255 ValueGraphVisitor for_left_value(owner(), temp_index()); | 241 ValueGraphVisitor for_left_value(owner(), temp_index()); |
| 256 node->left()->Visit(&for_left_value); | 242 node->left()->Visit(&for_left_value); |
| 257 Append(for_left_value); | 243 Append(for_left_value); |
| 258 CHECK_ALIVE(return); | |
| 259 ValueGraphVisitor for_right_value(owner(), for_left_value.temp_index()); | 244 ValueGraphVisitor for_right_value(owner(), for_left_value.temp_index()); |
| 260 node->right()->Visit(&for_right_value); | 245 node->right()->Visit(&for_right_value); |
| 261 Append(for_right_value); | 246 Append(for_right_value); |
| 262 CHECK_ALIVE(return); | |
| 263 if ((node->kind() == Token::kEQ_STRICT) || | 247 if ((node->kind() == Token::kEQ_STRICT) || |
| 264 (node->kind() == Token::kNE_STRICT)) { | 248 (node->kind() == Token::kNE_STRICT)) { |
| 265 StrictCompareComp* comp = new StrictCompareComp( | 249 StrictCompareComp* comp = new StrictCompareComp( |
| 266 node->kind(), for_left_value.value(), for_right_value.value()); | 250 node->kind(), for_left_value.value(), for_right_value.value()); |
| 267 ReturnComputation(comp); | 251 ReturnComputation(comp); |
| 268 return; | 252 return; |
| 269 } | 253 } |
| 270 ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2); | 254 ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2); |
| 271 arguments->Add(for_left_value.value()); | 255 arguments->Add(for_left_value.value()); |
| 272 arguments->Add(for_right_value.value()); | 256 arguments->Add(for_right_value.value()); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 | 375 |
| 392 | 376 |
| 393 void EffectGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) { | 377 void EffectGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) { |
| 394 ArgumentListNode* arguments = node->arguments(); | 378 ArgumentListNode* arguments = node->arguments(); |
| 395 int length = arguments->length(); | 379 int length = arguments->length(); |
| 396 ZoneGrowableArray<Value*>* values = new ZoneGrowableArray<Value*>(length + 1); | 380 ZoneGrowableArray<Value*>* values = new ZoneGrowableArray<Value*>(length + 1); |
| 397 | 381 |
| 398 ValueGraphVisitor for_receiver(owner(), temp_index()); | 382 ValueGraphVisitor for_receiver(owner(), temp_index()); |
| 399 node->receiver()->Visit(&for_receiver); | 383 node->receiver()->Visit(&for_receiver); |
| 400 Append(for_receiver); | 384 Append(for_receiver); |
| 401 CHECK_ALIVE(return); | |
| 402 Value* receiver_value = for_receiver.value(); | 385 Value* receiver_value = for_receiver.value(); |
| 403 temp_index_ = for_receiver.temp_index(); | 386 temp_index_ = for_receiver.temp_index(); |
| 404 if (receiver_value->IsConstant()) { | 387 if (receiver_value->IsConstant()) { |
| 405 AddInstruction(new BindInstr(temp_index(), receiver_value)); | 388 AddInstruction(new BindInstr(temp_index(), receiver_value)); |
| 406 receiver_value = new TempVal(AllocateTempIndex()); | 389 receiver_value = new TempVal(AllocateTempIndex()); |
| 407 } | 390 } |
| 408 values->Add(receiver_value); | 391 values->Add(receiver_value); |
| 409 | 392 |
| 410 TranslateArgumentList(*arguments, values); | 393 TranslateArgumentList(*arguments, values); |
| 411 CHECK_ALIVE(return); | |
| 412 InstanceCallComp* call = | 394 InstanceCallComp* call = |
| 413 new InstanceCallComp(node->function_name().ToCString(), values); | 395 new InstanceCallComp(node->function_name().ToCString(), values); |
| 414 ReturnComputation(call); | 396 ReturnComputation(call); |
| 415 } | 397 } |
| 416 | 398 |
| 417 | 399 |
| 418 void EffectGraphVisitor::TranslateArgumentList( | 400 void EffectGraphVisitor::TranslateArgumentList( |
| 419 const ArgumentListNode& node, ZoneGrowableArray<Value*>* values) { | 401 const ArgumentListNode& node, ZoneGrowableArray<Value*>* values) { |
| 420 int index = temp_index(); | 402 int index = temp_index(); |
| 421 for (intptr_t i = 0; i < node.length(); ++i) { | 403 for (intptr_t i = 0; i < node.length(); ++i) { |
| 422 ValueGraphVisitor for_value(owner(), index); | 404 ValueGraphVisitor for_value(owner(), index); |
| 423 node.NodeAt(i)->Visit(&for_value); | 405 node.NodeAt(i)->Visit(&for_value); |
| 424 Append(for_value); | 406 Append(for_value); |
| 425 CHECK_ALIVE(return); | |
| 426 Value* argument_value = for_value.value(); | 407 Value* argument_value = for_value.value(); |
| 427 index = for_value.temp_index(); | 408 index = for_value.temp_index(); |
| 428 if (argument_value->IsConstant()) { | 409 if (argument_value->IsConstant()) { |
| 429 AddInstruction(new BindInstr(index, argument_value)); | 410 AddInstruction(new BindInstr(index, argument_value)); |
| 430 argument_value = new TempVal(index++); | 411 argument_value = new TempVal(index++); |
| 431 } | 412 } |
| 432 values->Add(argument_value); | 413 values->Add(argument_value); |
| 433 } | 414 } |
| 434 } | 415 } |
| 435 | 416 |
| 436 // <Expression> ::= StaticCall { function: Function | 417 // <Expression> ::= StaticCall { function: Function |
| 437 // arguments: <ArgumentList> } | 418 // arguments: <ArgumentList> } |
| 438 void EffectGraphVisitor::VisitStaticCallNode(StaticCallNode* node) { | 419 void EffectGraphVisitor::VisitStaticCallNode(StaticCallNode* node) { |
| 439 int length = node->arguments()->length(); | 420 int length = node->arguments()->length(); |
| 440 ZoneGrowableArray<Value*>* values = new ZoneGrowableArray<Value*>(length); | 421 ZoneGrowableArray<Value*>* values = new ZoneGrowableArray<Value*>(length); |
| 441 TranslateArgumentList(*node->arguments(), values); | 422 TranslateArgumentList(*node->arguments(), values); |
| 442 CHECK_ALIVE(return); | |
| 443 StaticCallComp* call = new StaticCallComp(node->function(), values); | 423 StaticCallComp* call = new StaticCallComp(node->function(), values); |
| 444 ReturnComputation(call); | 424 ReturnComputation(call); |
| 445 } | 425 } |
| 446 | 426 |
| 447 | 427 |
| 448 void EffectGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { | 428 void EffectGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { |
| 449 Bailout("EffectGraphVisitor::VisitClosureCallNode"); | 429 Bailout("EffectGraphVisitor::VisitClosureCallNode"); |
| 450 } | 430 } |
| 451 | 431 |
| 452 | 432 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 505 ReturnComputation(load); | 485 ReturnComputation(load); |
| 506 } | 486 } |
| 507 | 487 |
| 508 | 488 |
| 509 // <Expression> ::= StoreLocal { local: LocalVariable | 489 // <Expression> ::= StoreLocal { local: LocalVariable |
| 510 // value: <Expression> } | 490 // value: <Expression> } |
| 511 void EffectGraphVisitor::VisitStoreLocalNode(StoreLocalNode* node) { | 491 void EffectGraphVisitor::VisitStoreLocalNode(StoreLocalNode* node) { |
| 512 ValueGraphVisitor for_value(owner(), temp_index()); | 492 ValueGraphVisitor for_value(owner(), temp_index()); |
| 513 node->value()->Visit(&for_value); | 493 node->value()->Visit(&for_value); |
| 514 Append(for_value); | 494 Append(for_value); |
| 515 CHECK_ALIVE(return); | |
| 516 StoreLocalComp* store = new StoreLocalComp(node->local(), for_value.value()); | 495 StoreLocalComp* store = new StoreLocalComp(node->local(), for_value.value()); |
| 517 ReturnComputation(store); | 496 ReturnComputation(store); |
| 518 } | 497 } |
| 519 | 498 |
| 520 | 499 |
| 521 void EffectGraphVisitor::VisitLoadInstanceFieldNode( | 500 void EffectGraphVisitor::VisitLoadInstanceFieldNode( |
| 522 LoadInstanceFieldNode* node) { | 501 LoadInstanceFieldNode* node) { |
| 523 Bailout("EffectGraphVisitor::VisitLoadInstanceFieldNode"); | 502 Bailout("EffectGraphVisitor::VisitLoadInstanceFieldNode"); |
| 524 } | 503 } |
| 525 | 504 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 551 | 530 |
| 552 | 531 |
| 553 // <Statement> ::= Sequence { scope: LocalScope | 532 // <Statement> ::= Sequence { scope: LocalScope |
| 554 // nodes: <Statement>* | 533 // nodes: <Statement>* |
| 555 // label: SourceLabel } | 534 // label: SourceLabel } |
| 556 void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) { | 535 void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) { |
| 557 if ((node->scope() != NULL) && | 536 if ((node->scope() != NULL) && |
| 558 (node->scope()->num_context_variables() != 0)) { | 537 (node->scope()->num_context_variables() != 0)) { |
| 559 Bailout("Sequence needs a context. Gotta have a context."); | 538 Bailout("Sequence needs a context. Gotta have a context."); |
| 560 } | 539 } |
| 561 for (intptr_t i = 0; i < node->length(); ++i) { | 540 intptr_t i = 0; |
| 541 while (is_open() && (i < node->length())) { |
| 562 EffectGraphVisitor for_effect(owner(), temp_index()); | 542 EffectGraphVisitor for_effect(owner(), temp_index()); |
| 563 node->NodeAt(i)->Visit(&for_effect); | 543 node->NodeAt(i++)->Visit(&for_effect); |
| 564 Append(for_effect); | 544 Append(for_effect); |
| 565 CHECK_ALIVE(return); | |
| 566 } | 545 } |
| 567 } | 546 } |
| 568 | 547 |
| 569 | 548 |
| 570 void EffectGraphVisitor::VisitCatchClauseNode(CatchClauseNode* node) { | 549 void EffectGraphVisitor::VisitCatchClauseNode(CatchClauseNode* node) { |
| 571 Bailout("EffectGraphVisitor::VisitCatchClauseNode"); | 550 Bailout("EffectGraphVisitor::VisitCatchClauseNode"); |
| 572 } | 551 } |
| 573 | 552 |
| 574 | 553 |
| 575 void EffectGraphVisitor::VisitTryCatchNode(TryCatchNode* node) { | 554 void EffectGraphVisitor::VisitTryCatchNode(TryCatchNode* node) { |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 735 instr->value()->Accept(this); | 714 instr->value()->Accept(this); |
| 736 OS::Print(" goto(%d, %d)", instr->true_successor()->block_number(), | 715 OS::Print(" goto(%d, %d)", instr->true_successor()->block_number(), |
| 737 instr->false_successor()->block_number()); | 716 instr->false_successor()->block_number()); |
| 738 } | 717 } |
| 739 | 718 |
| 740 | 719 |
| 741 void FlowGraphBuilder::BuildGraph() { | 720 void FlowGraphBuilder::BuildGraph() { |
| 742 EffectGraphVisitor for_effect(this, 0); | 721 EffectGraphVisitor for_effect(this, 0); |
| 743 for_effect.AddInstruction(new TargetEntryInstr()); | 722 for_effect.AddInstruction(new TargetEntryInstr()); |
| 744 parsed_function().node_sequence()->Visit(&for_effect); | 723 parsed_function().node_sequence()->Visit(&for_effect); |
| 724 // Check that the graph is properly terminated. |
| 725 ASSERT(!for_effect.is_open()); |
| 745 if (for_effect.entry() != NULL) { | 726 if (for_effect.entry() != NULL) { |
| 746 // Accumulate basic block entries via postorder traversal. | 727 // Accumulate basic block entries via postorder traversal. |
| 747 for_effect.entry()->Postorder(&postorder_block_entries_); | 728 for_effect.entry()->Postorder(&postorder_block_entries_); |
| 748 // Number the blocks in reverse postorder starting with 0. | 729 // Number the blocks in reverse postorder starting with 0. |
| 749 intptr_t last_index = postorder_block_entries_.length() - 1; | 730 intptr_t last_index = postorder_block_entries_.length() - 1; |
| 750 for (intptr_t i = last_index; i >= 0; --i) { | 731 for (intptr_t i = last_index; i >= 0; --i) { |
| 751 postorder_block_entries_[i]->set_block_number(last_index - i); | 732 postorder_block_entries_[i]->set_block_number(last_index - i); |
| 752 } | 733 } |
| 753 } | 734 } |
| 754 if (FLAG_print_flow_graph) { | 735 if (FLAG_print_flow_graph) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 765 char* chars = reinterpret_cast<char*>( | 746 char* chars = reinterpret_cast<char*>( |
| 766 Isolate::Current()->current_zone()->Allocate(len)); | 747 Isolate::Current()->current_zone()->Allocate(len)); |
| 767 OS::SNPrint(chars, len, kFormat, function_name, reason); | 748 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 768 const Error& error = Error::Handle( | 749 const Error& error = Error::Handle( |
| 769 LanguageError::New(String::Handle(String::New(chars)))); | 750 LanguageError::New(String::Handle(String::New(chars)))); |
| 770 Isolate::Current()->long_jump_base()->Jump(1, error); | 751 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 771 } | 752 } |
| 772 | 753 |
| 773 | 754 |
| 774 } // namespace dart | 755 } // namespace dart |
| OLD | NEW |