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

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, 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 | 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 701 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/scopes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698