| 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/flags.h" | 8 #include "vm/flags.h" |
| 9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
| 10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 const EffectGraphVisitor& false_fragment) { | 46 const EffectGraphVisitor& false_fragment) { |
| 47 // We have: a test graph fragment with zero, one, or two available exits; | 47 // We have: a test graph fragment with zero, one, or two available exits; |
| 48 // and a pair of effect graph fragments with zero or one available exits. | 48 // and a pair of effect graph fragments with zero or one available exits. |
| 49 // We want to append the branch and (if necessary) a join node to this | 49 // We want to append the branch and (if necessary) a join node to this |
| 50 // graph fragment. | 50 // graph fragment. |
| 51 ASSERT(is_open()); | 51 ASSERT(is_open()); |
| 52 | 52 |
| 53 // 1. Connect the test to this graph. | 53 // 1. Connect the test to this graph. |
| 54 Append(test_fragment); | 54 Append(test_fragment); |
| 55 | 55 |
| 56 // 2. Connect the true and false bodies to the test if they are reachable, | 56 // 2. Connect the true and false bodies to the test and record their exits |
| 57 // and if so record their exits (if any). | 57 // (if any). |
| 58 Instruction* true_exit = NULL; | 58 Instruction* true_exit = NULL; |
| 59 Instruction* false_exit = NULL; | 59 Instruction* false_exit = NULL; |
| 60 if (test_fragment.can_be_true()) { | 60 TargetEntryInstr* true_entry = new TargetEntryInstr(); |
| 61 TargetEntryInstr* true_entry = new TargetEntryInstr(); | 61 *test_fragment.true_successor_address() = true_entry; |
| 62 *test_fragment.true_successor_address() = true_entry; | 62 true_entry->SetSuccessor(true_fragment.entry()); |
| 63 true_entry->SetSuccessor(true_fragment.entry()); | 63 true_exit = true_fragment.is_empty() ? true_entry : true_fragment.exit(); |
| 64 true_exit = true_fragment.is_empty() ? true_entry : true_fragment.exit(); | |
| 65 | 64 |
| 66 TargetEntryInstr* false_entry = new TargetEntryInstr(); | 65 TargetEntryInstr* false_entry = new TargetEntryInstr(); |
| 67 *test_fragment.false_successor_address() = false_entry; | 66 *test_fragment.false_successor_address() = false_entry; |
| 68 false_entry->SetSuccessor(false_fragment.entry()); | 67 false_entry->SetSuccessor(false_fragment.entry()); |
| 69 false_exit = | 68 false_exit = false_fragment.is_empty() ? false_entry : false_fragment.exit(); |
| 70 false_fragment.is_empty() ? false_entry : false_fragment.exit(); | |
| 71 } | |
| 72 | 69 |
| 73 // 3. Add a join or select one (or neither) of the arms as exit. | 70 // 3. Add a join or select one (or neither) of the arms as exit. |
| 74 if (true_exit == NULL) { | 71 if (true_exit == NULL) { |
| 75 exit_ = false_exit; // May be NULL. | 72 exit_ = false_exit; // May be NULL. |
| 76 } else if (false_exit == NULL) { | 73 } else if (false_exit == NULL) { |
| 77 exit_ = true_exit; | 74 exit_ = true_exit; |
| 78 } else { | 75 } else { |
| 79 exit_ = new JoinEntryInstr(); | 76 exit_ = new JoinEntryInstr(); |
| 80 true_exit->SetSuccessor(exit_); | 77 true_exit->SetSuccessor(exit_); |
| 81 false_exit->SetSuccessor(exit_); | 78 false_exit->SetSuccessor(exit_); |
| 82 } | 79 } |
| 83 } | 80 } |
| 84 | 81 |
| 85 | 82 |
| 86 void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment, | 83 void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment, |
| 87 const EffectGraphVisitor& body_fragment) { | 84 const EffectGraphVisitor& body_fragment) { |
| 88 // We have: a test graph fragment with zero, one, or two available exits; | 85 // We have: a test graph fragment with zero, one, or two available exits; |
| 89 // and an effect graph fragment with zero or one available exits. We want | 86 // and an effect graph fragment with zero or one available exits. We want |
| 90 // to append the 'while loop' consisting of the test graph fragment as | 87 // to append the 'while loop' consisting of the test graph fragment as |
| 91 // condition and the effect graph fragment as body. | 88 // condition and the effect graph fragment as body. |
| 92 ASSERT(is_open()); | 89 ASSERT(is_open()); |
| 93 | 90 |
| 94 // 1. Connect the body to the test if it is reachable, and if so record | 91 // 1. Connect the body to the test if it is reachable, and if so record |
| 95 // its exit (if any). | 92 // its exit (if any). |
| 96 Instruction* body_exit = NULL; | 93 Instruction* body_exit = NULL; |
| 97 if (test_fragment.can_be_true()) { | 94 TargetEntryInstr* body_entry = new TargetEntryInstr(); |
| 98 TargetEntryInstr* body_entry = new TargetEntryInstr(); | 95 *test_fragment.true_successor_address() = body_entry; |
| 99 *test_fragment.true_successor_address() = body_entry; | 96 body_entry->SetSuccessor(body_fragment.entry()); |
| 100 body_entry->SetSuccessor(body_fragment.entry()); | 97 body_exit = body_fragment.is_empty() ? body_entry : body_fragment.exit(); |
| 101 body_exit = body_fragment.is_empty() ? body_entry : body_fragment.exit(); | |
| 102 } | |
| 103 | 98 |
| 104 // 2. Connect the test to this graph, including the body if reachable and | 99 // 2. Connect the test to this graph, including the body if reachable and |
| 105 // using a fresh join node if the body is reachable and has an open exit. | 100 // using a fresh join node if the body is reachable and has an open exit. |
| 106 if (body_exit == NULL) { | 101 if (body_exit == NULL) { |
| 107 Append(test_fragment); | 102 Append(test_fragment); |
| 108 } else { | 103 } else { |
| 109 JoinEntryInstr* join = new JoinEntryInstr(); | 104 JoinEntryInstr* join = new JoinEntryInstr(); |
| 110 AddInstruction(join); | 105 AddInstruction(join); |
| 111 join->SetSuccessor(test_fragment.entry()); | 106 join->SetSuccessor(test_fragment.entry()); |
| 112 body_exit->SetSuccessor(join); | 107 body_exit->SetSuccessor(join); |
| 113 } | 108 } |
| 114 | 109 |
| 115 // 3. Set the exit to the graph to be empty or a fresh target node | 110 // 3. Set the exit to the graph to be the false successor of the test, a |
| 116 // depending on whether the false branch of the test is reachable. | 111 // fresh target node |
| 117 if (test_fragment.can_be_false()) { | 112 exit_ = *test_fragment.false_successor_address() = new TargetEntryInstr(); |
| 118 exit_ = *test_fragment.false_successor_address() = new TargetEntryInstr(); | |
| 119 } else { | |
| 120 exit_ = NULL; | |
| 121 } | |
| 122 } | 113 } |
| 123 | 114 |
| 124 | 115 |
| 125 void TestGraphVisitor::ReturnValue(Value* value) { | 116 void TestGraphVisitor::ReturnValue(Value* value) { |
| 126 BranchInstr* branch = new BranchInstr(value); | 117 BranchInstr* branch = new BranchInstr(value); |
| 127 AddInstruction(branch); | 118 AddInstruction(branch); |
| 128 CloseFragment(); | 119 CloseFragment(); |
| 129 true_successor_address_ = branch->true_successor_address(); | 120 true_successor_address_ = branch->true_successor_address(); |
| 130 false_successor_address_ = branch->false_successor_address(); | 121 false_successor_address_ = branch->false_successor_address(); |
| 131 } | 122 } |
| (...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 624 new InstanceCallComp(node->store_id(), node->token_index(), store_name, | 615 new InstanceCallComp(node->store_id(), node->token_index(), store_name, |
| 625 arguments, Array::ZoneHandle(), 1); | 616 arguments, Array::ZoneHandle(), 1); |
| 626 AddInstruction(new DoInstr(store)); | 617 AddInstruction(new DoInstr(store)); |
| 627 ReturnValue(new TempVal(AllocateTempIndex())); | 618 ReturnValue(new TempVal(AllocateTempIndex())); |
| 628 } | 619 } |
| 629 | 620 |
| 630 | 621 |
| 631 void EffectGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) { | 622 void EffectGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) { |
| 632 TestGraphVisitor for_test(owner(), temp_index()); | 623 TestGraphVisitor for_test(owner(), temp_index()); |
| 633 node->condition()->Visit(&for_test); | 624 node->condition()->Visit(&for_test); |
| 634 ASSERT(for_test.can_be_true() && for_test.can_be_false()); | |
| 635 | 625 |
| 636 // Translate the subexpressions for their effects. | 626 // Translate the subexpressions for their effects. |
| 637 EffectGraphVisitor for_true(owner(), temp_index()); | 627 EffectGraphVisitor for_true(owner(), temp_index()); |
| 638 node->true_expr()->Visit(&for_true); | 628 node->true_expr()->Visit(&for_true); |
| 639 EffectGraphVisitor for_false(owner(), temp_index()); | 629 EffectGraphVisitor for_false(owner(), temp_index()); |
| 640 node->false_expr()->Visit(&for_false); | 630 node->false_expr()->Visit(&for_false); |
| 641 | 631 |
| 642 Join(for_test, for_true, for_false); | 632 Join(for_test, for_true, for_false); |
| 643 } | 633 } |
| 644 | 634 |
| 645 | 635 |
| 646 void ValueGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) { | 636 void ValueGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) { |
| 647 TestGraphVisitor for_test(owner(), temp_index()); | 637 TestGraphVisitor for_test(owner(), temp_index()); |
| 648 node->condition()->Visit(&for_test); | 638 node->condition()->Visit(&for_test); |
| 649 ASSERT(for_test.can_be_true() && for_test.can_be_false()); | |
| 650 | 639 |
| 651 // Ensure that the value of the true/false subexpressions are named with | 640 // Ensure that the value of the true/false subexpressions are named with |
| 652 // the same temporary name. | 641 // the same temporary name. |
| 653 ValueGraphVisitor for_true(owner(), temp_index()); | 642 ValueGraphVisitor for_true(owner(), temp_index()); |
| 654 node->true_expr()->Visit(&for_true); | 643 node->true_expr()->Visit(&for_true); |
| 655 ASSERT(for_true.is_open()); | 644 ASSERT(for_true.is_open()); |
| 656 if (for_true.value()->IsTemp()) { | 645 if (for_true.value()->IsTemp()) { |
| 657 ASSERT(for_true.value()->AsTemp()->index() == temp_index()); | 646 ASSERT(for_true.value()->AsTemp()->index() == temp_index()); |
| 658 } else { | 647 } else { |
| 659 for_true.AddInstruction(new BindInstr(temp_index(), for_true.value())); | 648 for_true.AddInstruction(new BindInstr(temp_index(), for_true.value())); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 676 // <Statement> ::= If { condition: <Expression> | 665 // <Statement> ::= If { condition: <Expression> |
| 677 // true_branch: <Sequence> | 666 // true_branch: <Sequence> |
| 678 // false_branch: <Sequence> } | 667 // false_branch: <Sequence> } |
| 679 void EffectGraphVisitor::VisitIfNode(IfNode* node) { | 668 void EffectGraphVisitor::VisitIfNode(IfNode* node) { |
| 680 TestGraphVisitor for_test(owner(), temp_index()); | 669 TestGraphVisitor for_test(owner(), temp_index()); |
| 681 node->condition()->Visit(&for_test); | 670 node->condition()->Visit(&for_test); |
| 682 | 671 |
| 683 EffectGraphVisitor for_true(owner(), temp_index()); | 672 EffectGraphVisitor for_true(owner(), temp_index()); |
| 684 EffectGraphVisitor for_false(owner(), temp_index()); | 673 EffectGraphVisitor for_false(owner(), temp_index()); |
| 685 | 674 |
| 686 if (for_test.can_be_true()) { | 675 node->true_branch()->Visit(&for_true); |
| 687 node->true_branch()->Visit(&for_true); | 676 // The for_false graph fragment will be empty (default graph fragment) if |
| 688 // The for_false graph fragment will be empty (default graph fragment) | 677 // we do not call Visit. |
| 689 // if we do not call Visit. | 678 if (node->false_branch() != NULL) node->false_branch()->Visit(&for_false); |
| 690 if (node->false_branch() != NULL) node->false_branch()->Visit(&for_false); | |
| 691 } | |
| 692 Join(for_test, for_true, for_false); | 679 Join(for_test, for_true, for_false); |
| 693 } | 680 } |
| 694 | 681 |
| 695 | 682 |
| 696 void EffectGraphVisitor::VisitSwitchNode(SwitchNode* node) { | 683 void EffectGraphVisitor::VisitSwitchNode(SwitchNode* node) { |
| 697 Bailout("EffectGraphVisitor::VisitSwitchNode"); | 684 Bailout("EffectGraphVisitor::VisitSwitchNode"); |
| 698 } | 685 } |
| 699 | 686 |
| 700 | 687 |
| 701 void EffectGraphVisitor::VisitCaseNode(CaseNode* node) { | 688 void EffectGraphVisitor::VisitCaseNode(CaseNode* node) { |
| 702 Bailout("EffectGraphVisitor::VisitCaseNode"); | 689 Bailout("EffectGraphVisitor::VisitCaseNode"); |
| 703 } | 690 } |
| 704 | 691 |
| 705 | 692 |
| 706 // <Statement> ::= While { label: SourceLabel | 693 // <Statement> ::= While { label: SourceLabel |
| 707 // condition: <Expression> | 694 // condition: <Expression> |
| 708 // body: <Sequence> } | 695 // body: <Sequence> } |
| 709 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) { | 696 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) { |
| 710 TestGraphVisitor for_test(owner(), temp_index()); | 697 TestGraphVisitor for_test(owner(), temp_index()); |
| 711 node->condition()->Visit(&for_test); | 698 node->condition()->Visit(&for_test); |
| 712 | 699 |
| 713 EffectGraphVisitor for_body(owner(), temp_index()); | 700 EffectGraphVisitor for_body(owner(), temp_index()); |
| 714 if (for_test.can_be_true()) node->body()->Visit(&for_body); | 701 node->body()->Visit(&for_body); |
| 715 TieLoop(for_test, for_body); | 702 TieLoop(for_test, for_body); |
| 716 } | 703 } |
| 717 | 704 |
| 718 | 705 |
| 719 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { | 706 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { |
| 720 EffectGraphVisitor for_body(owner(), temp_index()); | 707 EffectGraphVisitor for_body(owner(), temp_index()); |
| 721 node->body()->Visit(&for_body); | 708 node->body()->Visit(&for_body); |
| 722 TestGraphVisitor for_test(owner(), temp_index()); | 709 TestGraphVisitor for_test(owner(), temp_index()); |
| 723 node->condition()->Visit(&for_test); | 710 node->condition()->Visit(&for_test); |
| 724 ASSERT(is_open()); | 711 ASSERT(is_open()); |
| (...skipping 916 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1641 char* chars = reinterpret_cast<char*>( | 1628 char* chars = reinterpret_cast<char*>( |
| 1642 Isolate::Current()->current_zone()->Allocate(len)); | 1629 Isolate::Current()->current_zone()->Allocate(len)); |
| 1643 OS::SNPrint(chars, len, kFormat, function_name, reason); | 1630 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 1644 const Error& error = Error::Handle( | 1631 const Error& error = Error::Handle( |
| 1645 LanguageError::New(String::Handle(String::New(chars)))); | 1632 LanguageError::New(String::Handle(String::New(chars)))); |
| 1646 Isolate::Current()->long_jump_base()->Jump(1, error); | 1633 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 1647 } | 1634 } |
| 1648 | 1635 |
| 1649 | 1636 |
| 1650 } // namespace dart | 1637 } // namespace dart |
| OLD | NEW |