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

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

Issue 9959127: New compiler: implement switch/case in graph builder. (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 | « 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 683 matching lines...) Expand 10 before | Expand all | Expand 10 after
694 694
695 node->true_branch()->Visit(&for_true); 695 node->true_branch()->Visit(&for_true);
696 // The for_false graph fragment will be empty (default graph fragment) if 696 // The for_false graph fragment will be empty (default graph fragment) if
697 // we do not call Visit. 697 // we do not call Visit.
698 if (node->false_branch() != NULL) node->false_branch()->Visit(&for_false); 698 if (node->false_branch() != NULL) node->false_branch()->Visit(&for_false);
699 Join(for_test, for_true, for_false); 699 Join(for_test, for_true, for_false);
700 } 700 }
701 701
702 702
703 void EffectGraphVisitor::VisitSwitchNode(SwitchNode* node) { 703 void EffectGraphVisitor::VisitSwitchNode(SwitchNode* node) {
704 Bailout("EffectGraphVisitor::VisitSwitchNode"); 704 EffectGraphVisitor switch_body(owner(), temp_index());
705 node->body()->Visit(&switch_body);
706 Append(switch_body);
707 if ((node->label() != NULL) && (node->label()->join_for_break() != NULL)) {
708 if (is_open()) {
709 AddInstruction(node->label()->join_for_break());
710 } else {
711 exit_ = node->label()->join_for_break();
712 }
713 }
714 // No continue label allowed.
715 ASSERT((node->label() == NULL) ||
716 (node->label()->join_for_continue() == NULL));
705 } 717 }
706 718
707 719
720 // A case node contains zero or more case expressions, can contain default
721 // and a case statement body.
722 // Compose fragment as follows:
723 // - if no case expressions, must have default:
724 // a) target
725 // b) [ case-statements ]
726 //
727 // - if has 1 or more case statements
728 // a) target-0
729 // b) [ case-expression-0 ] -> (true-target-0, target-1)
730 // c) target-1
731 // d) [ case-expression-1 ] -> (true-target-1, exit-target)
732 // e) true-target-0 -> case-statements-join
733 // f) true-target-1 -> case-statements-join
734 // g) case-statements-join
735 // h) [ case-statements ] -> exit-join
736 // i) exit-target -> exit-join
737 // j) exit-join
738 //
739 // Note: The specification of switch/case is under discussion and may change
740 // drastically.
708 void EffectGraphVisitor::VisitCaseNode(CaseNode* node) { 741 void EffectGraphVisitor::VisitCaseNode(CaseNode* node) {
709 Bailout("EffectGraphVisitor::VisitCaseNode"); 742 const intptr_t len = node->case_expressions()->length();
743 // Create case statements instructions.
744 const bool needs_join_at_statement_entry =
745 (len > 1) || ((len > 0) && (node->contains_default()));
746 EffectGraphVisitor for_case_statements(owner(), temp_index());
747 // Compute start of statements fragment.
748 BlockEntryInstr* statement_start = NULL;
749 if ((node->label() != NULL) && (node->label()->is_continue_target())) {
750 // Since a labeled jump continue statement occur in a different case node,
751 // allocate JoinNode here and use it as statement start.
752 if (node->label()->join_for_continue() == NULL) {
753 node->label()->set_join_for_continue(new JoinEntryInstr());
754 }
755 statement_start = node->label()->join_for_continue();
756 } else if (needs_join_at_statement_entry) {
757 statement_start = new JoinEntryInstr();
758 } else {
759 statement_start = new TargetEntryInstr();
760 }
761 for_case_statements.AddInstruction(statement_start);
762 node->statements()->Visit(&for_case_statements);
763 if (is_open() && (len == 0)) {
764 ASSERT(node->contains_default());
765 // Default only case node.
766 Append(for_case_statements);
767 return;
768 }
769
770 // Generate instructions for all case expressions and collect data to
771 // connect them.
772 GrowableArray<TargetEntryInstr**> case_true_addresses;
773 GrowableArray<TargetEntryInstr**> case_false_addresses;
774 GrowableArray<TargetEntryInstr*> case_entries;
775 for (intptr_t i = 0; i < len; i++) {
776 AstNode* case_expr = node->case_expressions()->NodeAt(i);
777 TestGraphVisitor for_case_expression(owner(), temp_index());
778 if (i == 0) {
779 case_entries.Add(NULL); // Not to be used
780 case_expr->Visit(&for_case_expression);
781 // Append only the first one, everything else is connected from it.
782 Append(for_case_expression);
783 } else {
784 TargetEntryInstr* case_entry_target = new TargetEntryInstr();
785 case_entries.Add(case_entry_target);
786 for_case_expression.AddInstruction(case_entry_target);
787 case_expr->Visit(&for_case_expression);
788 }
789 case_true_addresses.Add(for_case_expression.true_successor_address());
790 case_false_addresses.Add(for_case_expression.false_successor_address());
791 }
792
793 // Once a test fragment has been added, this fragment is closed.
794 ASSERT(!is_open());
regis 2012/04/04 01:31:08 Can you move this ASSERT up inside the loop? Each
srdjan 2012/04/04 17:33:00 Discussed offline, leaving it here. Checking that
795
796 // Connect all test cases except the last one.
797 for (intptr_t i = 0; i < (len - 1); i++) {
798 ASSERT(needs_join_at_statement_entry);
799 *case_false_addresses[i] = case_entries[i + 1];
800 TargetEntryInstr* true_target = new TargetEntryInstr();
801 *case_true_addresses[i] = true_target;
802 true_target->SetSuccessor(statement_start);
803 }
804
805 BlockEntryInstr* exit_instruction = NULL;
806 // Handle last (or only) case: false goes to exit or to statement if this
807 // node contains default.
808 if (len > 0) {
809 if (statement_start->IsTargetEntry()) {
810 *case_true_addresses[len - 1] = statement_start->AsTargetEntry();
811 } else {
812 TargetEntryInstr* true_target = new TargetEntryInstr();
813 *case_true_addresses[len - 1] = true_target;
814 true_target->SetSuccessor(statement_start);
815 }
816 TargetEntryInstr* false_target = new TargetEntryInstr();
817 *case_false_addresses[len - 1] = false_target;
818 if (node->contains_default()) {
819 // True and false go to statement start.
820 false_target->SetSuccessor(statement_start);
821 if (for_case_statements.is_open()) {
822 exit_instruction = new TargetEntryInstr();
823 for_case_statements.exit()->SetSuccessor(exit_instruction);
824 }
825 } else {
826 if (for_case_statements.is_open()) {
827 exit_instruction = new JoinEntryInstr();
828 for_case_statements.exit()->SetSuccessor(exit_instruction);
829 } else {
830 exit_instruction = new TargetEntryInstr();
831 }
832 false_target->SetSuccessor(exit_instruction);
833 }
834 } else {
835 // A CaseNode without case expressions must contain default.
836 ASSERT(node->contains_default());
837 AddInstruction(statement_start);
838 }
839
840 ASSERT(!is_open());
841 exit_ = exit_instruction;
710 } 842 }
711 843
712 844
713 // <Statement> ::= While { label: SourceLabel 845 // <Statement> ::= While { label: SourceLabel
714 // condition: <Expression> 846 // condition: <Expression>
715 // body: <Sequence> } 847 // body: <Sequence> }
716 // The fragment is composed as follows: 848 // The fragment is composed as follows:
717 // a) continue-join (optional) 849 // a) continue-join (optional)
718 // b) loop-join 850 // b) loop-join
719 // c) [ test ] -> (body-entry-target, loop-exit-target) 851 // c) [ test ] -> (body-entry-target, loop-exit-target)
(...skipping 1389 matching lines...) Expand 10 before | Expand all | Expand 10 after
2109 char* chars = reinterpret_cast<char*>( 2241 char* chars = reinterpret_cast<char*>(
2110 Isolate::Current()->current_zone()->Allocate(len)); 2242 Isolate::Current()->current_zone()->Allocate(len));
2111 OS::SNPrint(chars, len, kFormat, function_name, reason); 2243 OS::SNPrint(chars, len, kFormat, function_name, reason);
2112 const Error& error = Error::Handle( 2244 const Error& error = Error::Handle(
2113 LanguageError::New(String::Handle(String::New(chars)))); 2245 LanguageError::New(String::Handle(String::New(chars))));
2114 Isolate::Current()->long_jump_base()->Jump(1, error); 2246 Isolate::Current()->long_jump_base()->Jump(1, error);
2115 } 2247 }
2116 2248
2117 2249
2118 } // namespace dart 2250 } // 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