| 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 701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 712 // <Statement> ::= While { label: SourceLabel | 712 // <Statement> ::= While { label: SourceLabel |
| 713 // condition: <Expression> | 713 // condition: <Expression> |
| 714 // body: <Sequence> } | 714 // body: <Sequence> } |
| 715 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) { | 715 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) { |
| 716 TestGraphVisitor for_test(owner(), temp_index()); | 716 TestGraphVisitor for_test(owner(), temp_index()); |
| 717 node->condition()->Visit(&for_test); | 717 node->condition()->Visit(&for_test); |
| 718 | 718 |
| 719 EffectGraphVisitor for_body(owner(), temp_index()); | 719 EffectGraphVisitor for_body(owner(), temp_index()); |
| 720 node->body()->Visit(&for_body); | 720 node->body()->Visit(&for_body); |
| 721 TieLoop(for_test, for_body); | 721 TieLoop(for_test, for_body); |
| 722 // TODO(srdjan): Implement JumpNode handling. |
| 723 if ((node->label() != NULL) && |
| 724 ((node->label()->join_for_break() != NULL) || |
| 725 (node->label()->join_for_continue() != NULL))) { |
| 726 Bailout("Jump in WhileNode"); |
| 727 } |
| 722 } | 728 } |
| 723 | 729 |
| 724 | 730 |
| 725 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { | 731 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { |
| 726 EffectGraphVisitor for_body(owner(), temp_index()); | 732 EffectGraphVisitor for_body(owner(), temp_index()); |
| 727 node->body()->Visit(&for_body); | 733 node->body()->Visit(&for_body); |
| 728 TestGraphVisitor for_test(owner(), temp_index()); | 734 TestGraphVisitor for_test(owner(), temp_index()); |
| 729 node->condition()->Visit(&for_test); | 735 node->condition()->Visit(&for_test); |
| 730 ASSERT(is_open()); | 736 ASSERT(is_open()); |
| 731 | 737 |
| 732 // Tie do-while loop (test is after the body). | 738 // Tie do-while loop (test is after the body). |
| 733 JoinEntryInstr* join = new JoinEntryInstr(); | 739 JoinEntryInstr* join = new JoinEntryInstr(); |
| 734 AddInstruction(join); | 740 AddInstruction(join); |
| 735 join->SetSuccessor(for_body.entry()); | 741 join->SetSuccessor(for_body.entry()); |
| 736 Instruction* body_exit = for_body.is_empty() ? join : for_body.exit(); | 742 Instruction* body_exit = for_body.is_empty() ? join : for_body.exit(); |
| 737 | 743 |
| 738 if (body_exit != NULL) { | 744 if (body_exit != NULL) { |
| 739 TargetEntryInstr* target_entry = new TargetEntryInstr(); | 745 TargetEntryInstr* target_entry = new TargetEntryInstr(); |
| 740 target_entry->SetSuccessor(for_test.entry()); | 746 target_entry->SetSuccessor(for_test.entry()); |
| 741 body_exit->SetSuccessor(target_entry); | 747 body_exit->SetSuccessor(target_entry); |
| 742 } | 748 } |
| 743 | 749 |
| 744 TargetEntryInstr* back_target_entry = new TargetEntryInstr(); | 750 TargetEntryInstr* back_target_entry = new TargetEntryInstr(); |
| 745 *for_test.true_successor_address() = back_target_entry; | 751 *for_test.true_successor_address() = back_target_entry; |
| 746 back_target_entry->SetSuccessor(join); | 752 back_target_entry->SetSuccessor(join); |
| 747 exit_ = *for_test.false_successor_address() = new TargetEntryInstr(); | 753 exit_ = *for_test.false_successor_address() = new TargetEntryInstr(); |
| 754 // TODO(srdjan): Implement JumpNode handling. |
| 755 if ((node->label() != NULL) && |
| 756 ((node->label()->join_for_break() != NULL) || |
| 757 (node->label()->join_for_continue() != NULL))) { |
| 758 Bailout("Jump in DoWhileNode"); |
| 759 } |
| 748 } | 760 } |
| 749 | 761 |
| 750 | 762 |
| 763 // A ForNode can contain break and continue jumps. 'break' joins to |
| 764 // ForNode exit, 'continue' joins at increment entry. |
| 751 void EffectGraphVisitor::VisitForNode(ForNode* node) { | 765 void EffectGraphVisitor::VisitForNode(ForNode* node) { |
| 752 EffectGraphVisitor for_initializer(owner(), temp_index()); | 766 EffectGraphVisitor for_initializer(owner(), temp_index()); |
| 753 node->initializer()->Visit(&for_initializer); | 767 node->initializer()->Visit(&for_initializer); |
| 754 Append(for_initializer); | 768 Append(for_initializer); |
| 755 ASSERT(is_open()); | 769 ASSERT(is_open()); |
| 756 | 770 |
| 771 // Compose body to set any jump labels. |
| 757 EffectGraphVisitor for_body(owner(), temp_index()); | 772 EffectGraphVisitor for_body(owner(), temp_index()); |
| 773 TargetEntryInstr* body_entry = new TargetEntryInstr(); |
| 774 for_body.AddInstruction(body_entry); |
| 758 node->body()->Visit(&for_body); | 775 node->body()->Visit(&for_body); |
| 759 if (for_body.is_open()) { | 776 |
| 760 EffectGraphVisitor for_increment(owner(), temp_index()); | 777 // Join loop body, increment and compute their end instruction. |
| 778 Instruction* loop_increment_end = NULL; |
| 779 EffectGraphVisitor for_increment(owner(), temp_index()); |
| 780 if ((node->label()->join_for_continue() == NULL) && for_body.is_open()) { |
| 781 // Do not insert an extra basic block. |
| 761 node->increment()->Visit(&for_increment); | 782 node->increment()->Visit(&for_increment); |
| 762 for_body.Append(for_increment); | 783 for_body.Append(for_increment); |
| 784 loop_increment_end = for_body.exit(); |
| 785 ASSERT(loop_increment_end != NULL); |
| 786 } else if (node->label()->join_for_continue() != NULL) { |
| 787 // Insert join between body and increment. |
| 788 if (for_body.is_open()) { |
| 789 for_body.exit()->SetSuccessor(node->label()->join_for_continue()); |
| 790 } |
| 791 for_increment.AddInstruction(node->label()->join_for_continue()); |
| 792 node->increment()->Visit(&for_increment); |
| 793 loop_increment_end = for_increment.exit(); |
| 794 ASSERT(loop_increment_end != NULL); |
| 763 } | 795 } |
| 764 | 796 |
| 765 if (node->condition() != NULL) { | 797 // 'loop_increment_end' is NULL only if there is no join for continue and the |
| 798 // body is not open, i.e., no backward branch exists. |
| 799 if (loop_increment_end != NULL) { |
| 800 JoinEntryInstr* loop_start = new JoinEntryInstr(); |
| 801 AddInstruction(loop_start); |
| 802 loop_increment_end->SetSuccessor(loop_start); |
| 803 } |
| 804 |
| 805 if (node->condition() == NULL) { |
| 806 // Endless loop, no test. |
| 807 Append(for_body); |
| 808 if (node->label()->join_for_break() == NULL) { |
| 809 CloseFragment(); |
| 810 } else { |
| 811 // Control flow of ForLoop continues into join_for_break. |
| 812 exit_ = node->label()->join_for_break(); |
| 813 } |
| 814 } else { |
| 815 TargetEntryInstr* loop_exit = new TargetEntryInstr(); |
| 766 TestGraphVisitor for_test(owner(), temp_index()); | 816 TestGraphVisitor for_test(owner(), temp_index()); |
| 767 node->condition()->Visit(&for_test); | 817 node->condition()->Visit(&for_test); |
| 768 TieLoop(for_test, for_body); | 818 Append(for_test); |
| 769 return; | 819 *for_test.true_successor_address() = body_entry; |
| 820 *for_test.false_successor_address() = loop_exit; |
| 821 if (node->label()->join_for_break() == NULL) { |
| 822 exit_ = loop_exit; |
| 823 } else { |
| 824 loop_exit->SetSuccessor(node->label()->join_for_break()); |
| 825 exit_ = node->label()->join_for_break(); |
| 826 } |
| 827 } |
| 828 } |
| 829 |
| 830 |
| 831 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { |
| 832 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { |
| 833 EffectGraphVisitor for_effect(owner(), temp_index()); |
| 834 node->InlinedFinallyNodeAt(i)->Visit(&for_effect); |
| 835 Append(for_effect); |
| 836 if (!is_open()) return; |
| 770 } | 837 } |
| 771 | 838 |
| 772 // Degenerate cases. An absent condition is implicitly true. No | 839 // Unchain the context(s) up to the outer context level of the scope which |
| 773 // normal exit from loop => no back edge. | 840 // contains the destination label. |
| 774 if (!for_body.is_open()) { | 841 SourceLabel* label = node->label(); |
| 775 Append(for_body); | 842 ASSERT(label->owner() != NULL); |
| 776 return; | 843 int target_context_level = 0; |
| 844 LocalScope* target_scope = label->owner(); |
| 845 if (target_scope->num_context_variables() > 0) { |
| 846 // The scope of the target label allocates a context, therefore its outer |
| 847 // scope is at a lower context level. |
| 848 target_context_level = target_scope->context_level() - 1; |
| 849 } else { |
| 850 // The scope of the target label does not allocate a context, so its outer |
| 851 // scope is at the same context level. Find it. |
| 852 while ((target_scope != NULL) && |
| 853 (target_scope->num_context_variables() == 0)) { |
| 854 target_scope = target_scope->parent(); |
| 855 } |
| 856 if (target_scope != NULL) { |
| 857 target_context_level = target_scope->context_level(); |
| 858 } |
| 777 } | 859 } |
| 778 JoinEntryInstr* join = new JoinEntryInstr(); | 860 ASSERT(target_context_level >= 0); |
| 779 AddInstruction(join); | 861 intptr_t current_context_level = owner()->context_level(); |
| 780 if (for_body.is_empty()) { | 862 ASSERT(current_context_level >= target_context_level); |
| 781 join->SetSuccessor(join); | 863 while (current_context_level-- > target_context_level) { |
| 864 UnchainContext(); |
| 865 } |
| 866 |
| 867 Instruction* jump_target = NULL; |
| 868 if (node->kind() == Token::kBREAK) { |
| 869 if (node->label()->join_for_break() == NULL) { |
| 870 node->label()->set_join_for_break(new JoinEntryInstr()); |
| 871 } |
| 872 jump_target = node->label()->join_for_break(); |
| 782 } else { | 873 } else { |
| 783 join->SetSuccessor(for_body.entry()); | 874 if (node->label()->join_for_continue() == NULL) { |
| 784 for_body.exit()->SetSuccessor(join); | 875 node->label()->set_join_for_continue(new JoinEntryInstr()); |
| 876 } |
| 877 jump_target = node->label()->join_for_continue(); |
| 785 } | 878 } |
| 879 AddInstruction(jump_target); |
| 786 CloseFragment(); | 880 CloseFragment(); |
| 787 } | 881 } |
| 788 | 882 |
| 789 | 883 |
| 790 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { | |
| 791 Bailout("EffectGraphVisitor::VisitJumpNode"); | |
| 792 } | |
| 793 | |
| 794 | |
| 795 void EffectGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) { | 884 void EffectGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) { |
| 796 UNREACHABLE(); | 885 UNREACHABLE(); |
| 797 } | 886 } |
| 798 | 887 |
| 799 | 888 |
| 800 void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) { | 889 void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) { |
| 801 // Translate the array elements and collect their values. | 890 // Translate the array elements and collect their values. |
| 802 ZoneGrowableArray<Value*>* values = | 891 ZoneGrowableArray<Value*>* values = |
| 803 new ZoneGrowableArray<Value*>(node->length()); | 892 new ZoneGrowableArray<Value*>(node->length()); |
| 804 int index = temp_index(); | 893 int index = temp_index(); |
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1406 if (FLAG_enable_type_checks && | 1495 if (FLAG_enable_type_checks && |
| 1407 (node == owner()->parsed_function().node_sequence())) { | 1496 (node == owner()->parsed_function().node_sequence())) { |
| 1408 Bailout("VisitSequenceNode GenerateArgumentTypeChecks()"); | 1497 Bailout("VisitSequenceNode GenerateArgumentTypeChecks()"); |
| 1409 } | 1498 } |
| 1410 | 1499 |
| 1411 intptr_t i = 0; | 1500 intptr_t i = 0; |
| 1412 while (is_open() && (i < node->length())) { | 1501 while (is_open() && (i < node->length())) { |
| 1413 EffectGraphVisitor for_effect(owner(), temp_index()); | 1502 EffectGraphVisitor for_effect(owner(), temp_index()); |
| 1414 node->NodeAt(i++)->Visit(&for_effect); | 1503 node->NodeAt(i++)->Visit(&for_effect); |
| 1415 Append(for_effect); | 1504 Append(for_effect); |
| 1505 if (!is_open()) { |
| 1506 // E.g., because of a JumpNode. |
| 1507 break; |
| 1508 } |
| 1416 } | 1509 } |
| 1417 | 1510 |
| 1418 if (is_open()) { | 1511 if (is_open()) { |
| 1419 if (MustSaveRestoreContext(node)) { | 1512 if (MustSaveRestoreContext(node)) { |
| 1420 ASSERT(num_context_variables > 0); | 1513 ASSERT(num_context_variables > 0); |
| 1421 LoadLocalComp* load_comp = | 1514 LoadLocalComp* load_comp = |
| 1422 new LoadLocalComp(*owner()->parsed_function().saved_context_var(), 0); | 1515 new LoadLocalComp(*owner()->parsed_function().saved_context_var(), 0); |
| 1423 AddInstruction(new BindInstr(temp_index(), load_comp)); | 1516 AddInstruction(new BindInstr(temp_index(), load_comp)); |
| 1424 TempVal* local_value = new TempVal(temp_index()); | 1517 TempVal* local_value = new TempVal(temp_index()); |
| 1425 StoreContextComp* store_context = new StoreContextComp(local_value); | 1518 StoreContextComp* store_context = new StoreContextComp(local_value); |
| 1426 AddInstruction(new DoInstr(store_context)); | 1519 AddInstruction(new DoInstr(store_context)); |
| 1427 } else if (num_context_variables > 0) { | 1520 } else if (num_context_variables > 0) { |
| 1428 UnchainContext(); | 1521 UnchainContext(); |
| 1429 } | 1522 } |
| 1430 } | 1523 } |
| 1431 | 1524 |
| 1432 // If this node sequence is labeled, a break out of the sequence will have | 1525 // If this node sequence is labeled, a break out of the sequence will have |
| 1433 // taken care of unchaining the context. | 1526 // taken care of unchaining the context. |
| 1527 if ((node->label() != NULL) && |
| 1528 ((node->label()->join_for_break() != NULL) || |
| 1529 (node->label()->join_for_continue() != NULL))) { |
| 1530 Bailout("Jump in SequenceNode"); |
| 1531 } |
| 1532 |
| 1434 if (node->label() != NULL) { | 1533 if (node->label() != NULL) { |
| 1435 // TODO(srdjan): Check that the break label is bound? Is this a jump? | 1534 // TODO(srdjan): Check that the break label is bound? Is this a jump? |
| 1436 Bailout("VisitSequenceNode bind break and unchain CTX"); | 1535 Bailout("VisitSequenceNode bind break and unchain CTX"); |
| 1437 } | 1536 } |
| 1438 owner()->set_context_level(previous_context_level); | 1537 owner()->set_context_level(previous_context_level); |
| 1439 } | 1538 } |
| 1440 | 1539 |
| 1441 | 1540 |
| 1442 void EffectGraphVisitor::VisitCatchClauseNode(CatchClauseNode* node) { | 1541 void EffectGraphVisitor::VisitCatchClauseNode(CatchClauseNode* node) { |
| 1443 Bailout("EffectGraphVisitor::VisitCatchClauseNode"); | 1542 Bailout("EffectGraphVisitor::VisitCatchClauseNode"); |
| (...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1960 char* chars = reinterpret_cast<char*>( | 2059 char* chars = reinterpret_cast<char*>( |
| 1961 Isolate::Current()->current_zone()->Allocate(len)); | 2060 Isolate::Current()->current_zone()->Allocate(len)); |
| 1962 OS::SNPrint(chars, len, kFormat, function_name, reason); | 2061 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 1963 const Error& error = Error::Handle( | 2062 const Error& error = Error::Handle( |
| 1964 LanguageError::New(String::Handle(String::New(chars)))); | 2063 LanguageError::New(String::Handle(String::New(chars)))); |
| 1965 Isolate::Current()->long_jump_base()->Jump(1, error); | 2064 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 1966 } | 2065 } |
| 1967 | 2066 |
| 1968 | 2067 |
| 1969 } // namespace dart | 2068 } // namespace dart |
| OLD | NEW |