Chromium Code Reviews| 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 695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 706 | 706 |
| 707 | 707 |
| 708 void EffectGraphVisitor::VisitCaseNode(CaseNode* node) { | 708 void EffectGraphVisitor::VisitCaseNode(CaseNode* node) { |
| 709 Bailout("EffectGraphVisitor::VisitCaseNode"); | 709 Bailout("EffectGraphVisitor::VisitCaseNode"); |
| 710 } | 710 } |
| 711 | 711 |
| 712 | 712 |
| 713 // <Statement> ::= While { label: SourceLabel | 713 // <Statement> ::= While { label: SourceLabel |
| 714 // condition: <Expression> | 714 // condition: <Expression> |
| 715 // body: <Sequence> } | 715 // body: <Sequence> } |
| 716 // The fragment is composed as follows: | |
| 717 // a) continue-join (optional) | |
| 718 // b) loop-join | |
| 719 // c) [ test ] -> (body-entry-target, loop-exit-target) | |
| 720 // d) body-entry-target | |
| 721 // e) [ body ] -> (loop-join) | |
| 722 // f) loop-exit-target | |
| 723 // g) break-join | |
|
regis
2012/04/02 17:53:52
Isn't the break-join optional?
srdjan
2012/04/04 17:33:18
Yes, added comment.
| |
| 716 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) { | 724 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) { |
| 717 TestGraphVisitor for_test(owner(), temp_index()); | 725 TestGraphVisitor for_test(owner(), temp_index()); |
| 718 node->condition()->Visit(&for_test); | 726 node->condition()->Visit(&for_test); |
| 727 ASSERT(!for_test.is_empty()); // Language spec. | |
| 719 | 728 |
| 720 EffectGraphVisitor for_body(owner(), temp_index()); | 729 EffectGraphVisitor for_body(owner(), temp_index()); |
| 721 node->body()->Visit(&for_body); | 730 node->body()->Visit(&for_body); |
| 731 | |
| 732 // Labels are set after body traversal. | |
| 733 SourceLabel* lbl = node->label(); | |
| 734 ASSERT(lbl != NULL); | |
| 735 if (lbl->join_for_continue() != NULL) { | |
| 736 AddInstruction(lbl->join_for_continue()); | |
| 737 } | |
| 722 TieLoop(for_test, for_body); | 738 TieLoop(for_test, for_body); |
| 723 // TODO(srdjan): Implement JumpNode handling. | 739 if (lbl->join_for_break() != NULL) { |
| 724 if ((node->label() != NULL) && | 740 AddInstruction(lbl->join_for_break()); |
| 725 ((node->label()->join_for_break() != NULL) || | |
| 726 (node->label()->join_for_continue() != NULL))) { | |
| 727 Bailout("Jump in WhileNode"); | |
| 728 } | 741 } |
| 729 } | 742 } |
| 730 | 743 |
| 731 | 744 |
| 745 // The fragment is composed as follows: | |
| 746 // a) body-entry-join | |
| 747 // b) [ body ] | |
| 748 // c) test-entry (continue-join or body-exit-target) | |
| 749 // d) [ test-entry ] -> (back-target, loop-exit-target) | |
| 750 // e) back-target -> (body-entry-join) | |
| 751 // f) loop-exit-target | |
| 752 // g) break-join | |
| 732 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { | 753 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { |
| 754 // Traverse body first in order to generate continue and break labels. | |
| 733 EffectGraphVisitor for_body(owner(), temp_index()); | 755 EffectGraphVisitor for_body(owner(), temp_index()); |
| 734 node->body()->Visit(&for_body); | 756 node->body()->Visit(&for_body); |
| 757 | |
| 735 TestGraphVisitor for_test(owner(), temp_index()); | 758 TestGraphVisitor for_test(owner(), temp_index()); |
| 736 node->condition()->Visit(&for_test); | 759 node->condition()->Visit(&for_test); |
| 737 ASSERT(is_open()); | 760 ASSERT(is_open()); |
| 738 | 761 |
| 739 // Tie do-while loop (test is after the body). | 762 // Tie do-while loop (test is after the body). |
| 740 JoinEntryInstr* join = new JoinEntryInstr(); | 763 JoinEntryInstr* body_entry_join = new JoinEntryInstr(); |
| 741 AddInstruction(join); | 764 AddInstruction(body_entry_join); |
| 742 join->SetSuccessor(for_body.entry()); | 765 body_entry_join->SetSuccessor(for_body.entry()); |
| 743 Instruction* body_exit = for_body.is_empty() ? join : for_body.exit(); | 766 Instruction* body_exit = |
| 767 for_body.is_empty() ? body_entry_join : for_body.exit(); | |
| 744 | 768 |
| 745 if (body_exit != NULL) { | 769 if (for_body.is_open() || (node->label()->join_for_continue() != NULL)) { |
| 746 TargetEntryInstr* target_entry = new TargetEntryInstr(); | 770 BlockEntryInstr* test_entry = NULL; |
| 747 target_entry->SetSuccessor(for_test.entry()); | 771 if (node->label()->join_for_continue() == NULL) { |
| 748 body_exit->SetSuccessor(target_entry); | 772 test_entry = new TargetEntryInstr(); |
| 773 } else { | |
| 774 test_entry = node->label()->join_for_continue(); | |
| 775 } | |
| 776 test_entry->SetSuccessor(for_test.entry()); | |
| 777 if (body_exit != NULL) { | |
| 778 body_exit->SetSuccessor(test_entry); | |
| 779 } | |
| 749 } | 780 } |
| 750 | 781 |
| 751 TargetEntryInstr* back_target_entry = new TargetEntryInstr(); | 782 TargetEntryInstr* back_target_entry = new TargetEntryInstr(); |
| 752 *for_test.true_successor_address() = back_target_entry; | 783 *for_test.true_successor_address() = back_target_entry; |
| 753 back_target_entry->SetSuccessor(join); | 784 back_target_entry->SetSuccessor(body_entry_join); |
| 754 exit_ = *for_test.false_successor_address() = new TargetEntryInstr(); | 785 TargetEntryInstr* loop_exit_target = new TargetEntryInstr(); |
| 755 // TODO(srdjan): Implement JumpNode handling. | 786 *for_test.false_successor_address() = loop_exit_target; |
| 756 if ((node->label() != NULL) && | 787 if (node->label()->join_for_break() == NULL) { |
| 757 ((node->label()->join_for_break() != NULL) || | 788 exit_ = loop_exit_target; |
| 758 (node->label()->join_for_continue() != NULL))) { | 789 } else { |
| 759 Bailout("Jump in DoWhileNode"); | 790 loop_exit_target->SetSuccessor(node->label()->join_for_break()); |
| 791 exit_ = node->label()->join_for_break(); | |
| 760 } | 792 } |
| 761 } | 793 } |
| 762 | 794 |
| 763 | 795 |
| 764 // A ForNode can contain break and continue jumps. 'break' joins to | 796 // A ForNode can contain break and continue jumps. 'break' joins to |
| 765 // ForNode exit, 'continue' joins at increment entry. | 797 // ForNode exit, 'continue' joins at increment entry. The fragment is composed |
| 798 // as follows: | |
| 799 // a) [ initializer ] | |
| 800 // b) loop-join | |
| 801 // c) [ test ] -> (body-entry-target, loop-exit-target) | |
| 802 // d) body-entry-target | |
| 803 // e) [ body ] | |
| 804 // f) continue-join (optional) | |
| 805 // g) [ increment ] -> (loop-join) | |
| 806 // h) loop-exit-target | |
| 807 // i) break-join | |
| 766 void EffectGraphVisitor::VisitForNode(ForNode* node) { | 808 void EffectGraphVisitor::VisitForNode(ForNode* node) { |
| 767 EffectGraphVisitor for_initializer(owner(), temp_index()); | 809 EffectGraphVisitor for_initializer(owner(), temp_index()); |
| 768 node->initializer()->Visit(&for_initializer); | 810 node->initializer()->Visit(&for_initializer); |
| 769 Append(for_initializer); | 811 Append(for_initializer); |
| 770 ASSERT(is_open()); | 812 ASSERT(is_open()); |
| 771 | 813 |
| 772 // Compose body to set any jump labels. | 814 // Compose body to set any jump labels. |
| 773 EffectGraphVisitor for_body(owner(), temp_index()); | 815 EffectGraphVisitor for_body(owner(), temp_index()); |
| 774 TargetEntryInstr* body_entry = new TargetEntryInstr(); | 816 TargetEntryInstr* body_entry = new TargetEntryInstr(); |
| 775 for_body.AddInstruction(body_entry); | 817 for_body.AddInstruction(body_entry); |
| 776 node->body()->Visit(&for_body); | 818 node->body()->Visit(&for_body); |
| 777 | 819 |
| 778 // Join loop body, increment and compute their end instruction. | 820 // Join loop body, increment and compute their end instruction. |
| 821 ASSERT(!for_body.is_empty()); | |
| 779 Instruction* loop_increment_end = NULL; | 822 Instruction* loop_increment_end = NULL; |
| 780 EffectGraphVisitor for_increment(owner(), temp_index()); | 823 EffectGraphVisitor for_increment(owner(), temp_index()); |
| 781 if ((node->label()->join_for_continue() == NULL) && for_body.is_open()) { | 824 if ((node->label()->join_for_continue() == NULL) && for_body.is_open()) { |
| 782 // Do not insert an extra basic block. | 825 // Do not insert an extra basic block. |
| 783 node->increment()->Visit(&for_increment); | 826 node->increment()->Visit(&for_increment); |
| 784 for_body.Append(for_increment); | 827 for_body.Append(for_increment); |
| 785 loop_increment_end = for_body.exit(); | 828 loop_increment_end = for_body.exit(); |
| 829 // 'for_body' contains at least the TargetInstruction 'body_entry'. | |
| 786 ASSERT(loop_increment_end != NULL); | 830 ASSERT(loop_increment_end != NULL); |
| 787 } else if (node->label()->join_for_continue() != NULL) { | 831 } else if (node->label()->join_for_continue() != NULL) { |
| 788 // Insert join between body and increment. | 832 // Insert join between body and increment. |
| 789 if (for_body.is_open()) { | 833 if (for_body.is_open()) { |
| 790 for_body.exit()->SetSuccessor(node->label()->join_for_continue()); | 834 for_body.exit()->SetSuccessor(node->label()->join_for_continue()); |
| 791 } | 835 } |
| 792 for_increment.AddInstruction(node->label()->join_for_continue()); | 836 for_increment.AddInstruction(node->label()->join_for_continue()); |
| 793 node->increment()->Visit(&for_increment); | 837 node->increment()->Visit(&for_increment); |
| 794 loop_increment_end = for_increment.exit(); | 838 loop_increment_end = for_increment.exit(); |
| 795 ASSERT(loop_increment_end != NULL); | 839 ASSERT(loop_increment_end != NULL); |
| 840 } else { | |
| 841 loop_increment_end = NULL; | |
| 842 ASSERT(!for_body.is_open() && node->label()->join_for_continue() == NULL); | |
| 796 } | 843 } |
| 797 | 844 |
| 798 // 'loop_increment_end' is NULL only if there is no join for continue and the | 845 // 'loop_increment_end' is NULL only if there is no join for continue and the |
| 799 // body is not open, i.e., no backward branch exists. | 846 // body is not open, i.e., no backward branch exists. |
| 800 if (loop_increment_end != NULL) { | 847 if (loop_increment_end != NULL) { |
| 801 JoinEntryInstr* loop_start = new JoinEntryInstr(); | 848 JoinEntryInstr* loop_start = new JoinEntryInstr(); |
| 802 AddInstruction(loop_start); | 849 AddInstruction(loop_start); |
| 803 loop_increment_end->SetSuccessor(loop_start); | 850 loop_increment_end->SetSuccessor(loop_start); |
| 804 } | 851 } |
| 805 | 852 |
| (...skipping 1256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2062 char* chars = reinterpret_cast<char*>( | 2109 char* chars = reinterpret_cast<char*>( |
| 2063 Isolate::Current()->current_zone()->Allocate(len)); | 2110 Isolate::Current()->current_zone()->Allocate(len)); |
| 2064 OS::SNPrint(chars, len, kFormat, function_name, reason); | 2111 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 2065 const Error& error = Error::Handle( | 2112 const Error& error = Error::Handle( |
| 2066 LanguageError::New(String::Handle(String::New(chars)))); | 2113 LanguageError::New(String::Handle(String::New(chars)))); |
| 2067 Isolate::Current()->long_jump_base()->Jump(1, error); | 2114 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2068 } | 2115 } |
| 2069 | 2116 |
| 2070 | 2117 |
| 2071 } // namespace dart | 2118 } // namespace dart |
| OLD | NEW |