Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(75)

Side by Side Diff: runtime/vm/flow_graph_builder.cc

Issue 9958070: Implement JumpNode handling (continue, break) in Dowhile and While nodes. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698