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

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

Issue 9907001: Implement JumpNode for break/continue in for loops. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 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 | « runtime/vm/ast.h ('k') | runtime/vm/scopes.h » ('j') | 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 730 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 body_exit->SetSuccessor(target_entry); 741 body_exit->SetSuccessor(target_entry);
742 } 742 }
743 743
744 TargetEntryInstr* back_target_entry = new TargetEntryInstr(); 744 TargetEntryInstr* back_target_entry = new TargetEntryInstr();
745 *for_test.true_successor_address() = back_target_entry; 745 *for_test.true_successor_address() = back_target_entry;
746 back_target_entry->SetSuccessor(join); 746 back_target_entry->SetSuccessor(join);
747 exit_ = *for_test.false_successor_address() = new TargetEntryInstr(); 747 exit_ = *for_test.false_successor_address() = new TargetEntryInstr();
748 } 748 }
749 749
750 750
751 // A ForNode can contain break and continue jumps. 'break' joins to
752 // ForNode exit, 'continue' joins at iteration entry.
751 void EffectGraphVisitor::VisitForNode(ForNode* node) { 753 void EffectGraphVisitor::VisitForNode(ForNode* node) {
752 EffectGraphVisitor for_initializer(owner(), temp_index()); 754 EffectGraphVisitor for_initializer(owner(), temp_index());
753 node->initializer()->Visit(&for_initializer); 755 node->initializer()->Visit(&for_initializer);
754 Append(for_initializer); 756 Append(for_initializer);
755 ASSERT(is_open()); 757 ASSERT(is_open());
756 758
759 JoinEntryInstr* for_break_join = NULL;
760 if (node->label()->is_break_jump_target()) {
Kevin Millikin (Google) 2012/03/29 11:38:31 You could do this lazily in VisitJumpNode: if ((n
761 for_break_join = new JoinEntryInstr();
762 // Must be set-up before body is traversed.
763 node->label()->set_join_for_break(for_break_join);
764 }
765
766 // Increment entry is either target or join.
767 BlockEntryInstr* increment_entry = NULL;
Kevin Millikin (Google) 2012/03/29 11:38:31 You could also do this lazily in VisitJumpNode.
768 if (node->label()->is_continue_jump_target()) {
769 JoinEntryInstr* join = new JoinEntryInstr();
770 // Must be set-up before body is traversed.
771 node->label()->set_join_for_continue(join);
772 increment_entry = join;
773 } else {
774 increment_entry = new TargetEntryInstr();
775 }
776
777 EffectGraphVisitor for_increment(owner(), temp_index());
Kevin Millikin (Google) 2012/03/29 11:38:31 Then you can: 1. Visit the body first. After vis
778 for_increment.AddInstruction(increment_entry);
779 node->increment()->Visit(&for_increment);
780
757 EffectGraphVisitor for_body(owner(), temp_index()); 781 EffectGraphVisitor for_body(owner(), temp_index());
782 TargetEntryInstr* body_entry = new TargetEntryInstr();
783 for_body.AddInstruction(body_entry);
758 node->body()->Visit(&for_body); 784 node->body()->Visit(&for_body);
785
759 if (for_body.is_open()) { 786 if (for_body.is_open()) {
760 EffectGraphVisitor for_increment(owner(), temp_index()); 787 ASSERT(!for_body.is_empty());
761 node->increment()->Visit(&for_increment); 788 for_body.exit()->SetSuccessor(increment_entry);
762 for_body.Append(for_increment);
763 } 789 }
764 790
765 if (node->condition() != NULL) { 791 if (node->condition() != NULL) {
792 JoinEntryInstr* test_entry = new JoinEntryInstr();
793 AddInstruction(test_entry);
766 TestGraphVisitor for_test(owner(), temp_index()); 794 TestGraphVisitor for_test(owner(), temp_index());
767 node->condition()->Visit(&for_test); 795 node->condition()->Visit(&for_test);
768 TieLoop(for_test, for_body); 796 Append(for_test);
769 return; 797 *for_test.true_successor_address() = body_entry;
798 for_increment.exit()->SetSuccessor(test_entry);
799
800 TargetEntryInstr* target_entry = new TargetEntryInstr();
801 *for_test.false_successor_address() = target_entry;
802 if (for_break_join == NULL) {
803 exit_ = target_entry;
804 } else {
805 target_entry->SetSuccessor(for_break_join);
806 exit_ = for_break_join;
807 }
808 } else {
809 // Endless loop
810 JoinEntryInstr* loop_start = new JoinEntryInstr();
811 AddInstruction(loop_start);
812 Append(for_body);
813 for_increment.exit()->SetSuccessor(loop_start);
814 if (node->label()->is_break_jump_target()) {
815 exit_ = for_break_join;
816 } else {
817 CloseFragment();
818 }
819 }
820 }
821
822
823 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) {
824 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) {
825 EffectGraphVisitor for_effect(owner(), temp_index());
826 node->InlinedFinallyNodeAt(i)->Visit(&for_effect);
827 Append(for_effect);
828 if (!is_open()) return;
770 } 829 }
771 830
772 // Degenerate cases. An absent condition is implicitly true. No 831 // Unchain the context(s) up to the outer context level of the scope which
773 // normal exit from loop => no back edge. 832 // contains the destination label.
774 if (!for_body.is_open()) { 833 SourceLabel* label = node->label();
775 Append(for_body); 834 ASSERT(label->owner() != NULL);
776 return; 835 int target_context_level = 0;
836 LocalScope* target_scope = label->owner();
837 if (target_scope->num_context_variables() > 0) {
838 // The scope of the target label allocates a context, therefore its outer
839 // scope is at a lower context level.
840 target_context_level = target_scope->context_level() - 1;
841 } else {
842 // The scope of the target label does not allocate a context, so its outer
843 // scope is at the same context level. Find it.
844 while ((target_scope != NULL) &&
845 (target_scope->num_context_variables() == 0)) {
846 target_scope = target_scope->parent();
847 }
848 if (target_scope != NULL) {
849 target_context_level = target_scope->context_level();
850 }
777 } 851 }
778 JoinEntryInstr* join = new JoinEntryInstr(); 852 ASSERT(target_context_level >= 0);
779 AddInstruction(join); 853 intptr_t current_context_level = owner()->context_level();
780 if (for_body.is_empty()) { 854 ASSERT(current_context_level >= target_context_level);
781 join->SetSuccessor(join); 855 while (current_context_level-- > target_context_level) {
856 UnchainContext();
857 }
858
859 if (node->kind() == Token::kBREAK) {
860 ASSERT(node->label()->is_break_jump_target());
861 if (node->label()->join_for_break() == NULL) {
862 Bailout("Join for JUMP BREAK not implemented");
863 }
864 entry_ = exit_ = node->label()->join_for_break();
Kevin Millikin (Google) 2012/03/29 11:38:31 Hmm. We don't need to set exit_, because CloseFra
782 } else { 865 } else {
783 join->SetSuccessor(for_body.entry()); 866 ASSERT(node->label()->is_continue_jump_target());
784 for_body.exit()->SetSuccessor(join); 867 if (node->label()->join_for_continue() == NULL) {
868 Bailout("Join for JUMP CONTINUE not implemented");
869 }
870 entry_ = exit_ = node->label()->join_for_continue();
785 } 871 }
786 CloseFragment(); 872 CloseFragment();
787 } 873 }
788 874
789 875
790 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) {
791 Bailout("EffectGraphVisitor::VisitJumpNode");
792 }
793
794
795 void EffectGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) { 876 void EffectGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) {
796 UNREACHABLE(); 877 UNREACHABLE();
797 } 878 }
798 879
799 880
800 void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) { 881 void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) {
801 // Translate the array elements and collect their values. 882 // Translate the array elements and collect their values.
802 ZoneGrowableArray<Value*>* values = 883 ZoneGrowableArray<Value*>* values =
803 new ZoneGrowableArray<Value*>(node->length()); 884 new ZoneGrowableArray<Value*>(node->length());
804 int index = temp_index(); 885 int index = temp_index();
(...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after
1406 if (FLAG_enable_type_checks && 1487 if (FLAG_enable_type_checks &&
1407 (node == owner()->parsed_function().node_sequence())) { 1488 (node == owner()->parsed_function().node_sequence())) {
1408 Bailout("VisitSequenceNode GenerateArgumentTypeChecks()"); 1489 Bailout("VisitSequenceNode GenerateArgumentTypeChecks()");
1409 } 1490 }
1410 1491
1411 intptr_t i = 0; 1492 intptr_t i = 0;
1412 while (is_open() && (i < node->length())) { 1493 while (is_open() && (i < node->length())) {
1413 EffectGraphVisitor for_effect(owner(), temp_index()); 1494 EffectGraphVisitor for_effect(owner(), temp_index());
1414 node->NodeAt(i++)->Visit(&for_effect); 1495 node->NodeAt(i++)->Visit(&for_effect);
1415 Append(for_effect); 1496 Append(for_effect);
1497 if (!is_open()) {
1498 // E.g., because of a JumpNode.
1499 break;
1500 }
1416 } 1501 }
1417 1502
1418 if (is_open()) { 1503 if (is_open()) {
1419 if (MustSaveRestoreContext(node)) { 1504 if (MustSaveRestoreContext(node)) {
1420 ASSERT(num_context_variables > 0); 1505 ASSERT(num_context_variables > 0);
1421 LoadLocalComp* load_comp = 1506 LoadLocalComp* load_comp =
1422 new LoadLocalComp(*owner()->parsed_function().saved_context_var(), 0); 1507 new LoadLocalComp(*owner()->parsed_function().saved_context_var(), 0);
1423 AddInstruction(new BindInstr(temp_index(), load_comp)); 1508 AddInstruction(new BindInstr(temp_index(), load_comp));
1424 TempVal* local_value = new TempVal(temp_index()); 1509 TempVal* local_value = new TempVal(temp_index());
1425 StoreContextComp* store_context = new StoreContextComp(local_value); 1510 StoreContextComp* store_context = new StoreContextComp(local_value);
(...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after
1960 char* chars = reinterpret_cast<char*>( 2045 char* chars = reinterpret_cast<char*>(
1961 Isolate::Current()->current_zone()->Allocate(len)); 2046 Isolate::Current()->current_zone()->Allocate(len));
1962 OS::SNPrint(chars, len, kFormat, function_name, reason); 2047 OS::SNPrint(chars, len, kFormat, function_name, reason);
1963 const Error& error = Error::Handle( 2048 const Error& error = Error::Handle(
1964 LanguageError::New(String::Handle(String::New(chars)))); 2049 LanguageError::New(String::Handle(String::New(chars))));
1965 Isolate::Current()->long_jump_base()->Jump(1, error); 2050 Isolate::Current()->long_jump_base()->Jump(1, error);
1966 } 2051 }
1967 2052
1968 2053
1969 } // namespace dart 2054 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/ast.h ('k') | runtime/vm/scopes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698