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

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/dart_entry.h" 8 #include "vm/dart_entry.h"
9 #include "vm/flags.h" 9 #include "vm/flags.h"
10 #include "vm/intermediate_language.h" 10 #include "vm/intermediate_language.h"
(...skipping 761 matching lines...) Expand 10 before | Expand all | Expand 10 after
772 772
773 node->true_branch()->Visit(&for_true); 773 node->true_branch()->Visit(&for_true);
774 // The for_false graph fragment will be empty (default graph fragment) if 774 // The for_false graph fragment will be empty (default graph fragment) if
775 // we do not call Visit. 775 // we do not call Visit.
776 if (node->false_branch() != NULL) node->false_branch()->Visit(&for_false); 776 if (node->false_branch() != NULL) node->false_branch()->Visit(&for_false);
777 Join(for_test, for_true, for_false); 777 Join(for_test, for_true, for_false);
778 } 778 }
779 779
780 780
781 void EffectGraphVisitor::VisitSwitchNode(SwitchNode* node) { 781 void EffectGraphVisitor::VisitSwitchNode(SwitchNode* node) {
782 Bailout("EffectGraphVisitor::VisitSwitchNode"); 782 EffectGraphVisitor switch_body(owner(), temp_index());
783 node->body()->Visit(&switch_body);
784 Append(switch_body);
785 if ((node->label() != NULL) && (node->label()->join_for_break() != NULL)) {
786 if (is_open()) {
787 AddInstruction(node->label()->join_for_break());
788 } else {
789 exit_ = node->label()->join_for_break();
790 }
791 }
792 // No continue label allowed.
793 ASSERT((node->label() == NULL) ||
794 (node->label()->join_for_continue() == NULL));
783 } 795 }
784 796
785 797
798 // A case node contains zero or more case expressions, can contain default
799 // and a case statement body.
800 // Compose fragment as follows:
801 // - if no case expressions, must have default:
802 // a) target
803 // b) [ case-statements ]
804 //
805 // - if has 1 or more case statements
806 // a) target-0
807 // b) [ case-expression-0 ] -> (true-target-0, target-1)
808 // c) target-1
809 // d) [ case-expression-1 ] -> (true-target-1, exit-target)
810 // e) true-target-0 -> case-statements-join
811 // f) true-target-1 -> case-statements-join
812 // g) case-statements-join
813 // h) [ case-statements ] -> exit-join
814 // i) exit-target -> exit-join
815 // j) exit-join
816 //
817 // Note: The specification of switch/case is under discussion and may change
818 // drastically.
786 void EffectGraphVisitor::VisitCaseNode(CaseNode* node) { 819 void EffectGraphVisitor::VisitCaseNode(CaseNode* node) {
787 Bailout("EffectGraphVisitor::VisitCaseNode"); 820 const intptr_t len = node->case_expressions()->length();
821 // Create case statements instructions.
822 const bool needs_join_at_statement_entry =
823 (len > 1) || ((len > 0) && (node->contains_default()));
824 EffectGraphVisitor for_case_statements(owner(), temp_index());
825 // Compute start of statements fragment.
826 BlockEntryInstr* statement_start = NULL;
827 if ((node->label() != NULL) && (node->label()->is_continue_target())) {
828 // Since a labeled jump continue statement occur in a different case node,
829 // allocate JoinNode here and use it as statement start.
830 if (node->label()->join_for_continue() == NULL) {
831 node->label()->set_join_for_continue(new JoinEntryInstr());
832 }
833 statement_start = node->label()->join_for_continue();
834 } else if (needs_join_at_statement_entry) {
835 statement_start = new JoinEntryInstr();
836 } else {
837 statement_start = new TargetEntryInstr();
838 }
839 for_case_statements.AddInstruction(statement_start);
840 node->statements()->Visit(&for_case_statements);
841 if (is_open() && (len == 0)) {
842 ASSERT(node->contains_default());
843 // Default only case node.
844 Append(for_case_statements);
845 return;
846 }
847
848 // Generate instructions for all case expressions and collect data to
849 // connect them.
850 GrowableArray<TargetEntryInstr**> case_true_addresses;
851 GrowableArray<TargetEntryInstr**> case_false_addresses;
852 GrowableArray<TargetEntryInstr*> case_entries;
853 for (intptr_t i = 0; i < len; i++) {
854 AstNode* case_expr = node->case_expressions()->NodeAt(i);
855 TestGraphVisitor for_case_expression(owner(), temp_index());
856 if (i == 0) {
857 case_entries.Add(NULL); // Not to be used
858 case_expr->Visit(&for_case_expression);
859 // Append only the first one, everything else is connected from it.
860 Append(for_case_expression);
861 } else {
862 TargetEntryInstr* case_entry_target = new TargetEntryInstr();
863 case_entries.Add(case_entry_target);
864 for_case_expression.AddInstruction(case_entry_target);
865 case_expr->Visit(&for_case_expression);
866 }
867 case_true_addresses.Add(for_case_expression.true_successor_address());
868 case_false_addresses.Add(for_case_expression.false_successor_address());
869 }
870
871 // Once a test fragment has been added, this fragment is closed.
872 ASSERT(!is_open());
873
874 // Connect all test cases except the last one.
875 for (intptr_t i = 0; i < (len - 1); i++) {
876 ASSERT(needs_join_at_statement_entry);
877 *case_false_addresses[i] = case_entries[i + 1];
878 TargetEntryInstr* true_target = new TargetEntryInstr();
879 *case_true_addresses[i] = true_target;
880 true_target->SetSuccessor(statement_start);
881 }
882
883 BlockEntryInstr* exit_instruction = NULL;
884 // Handle last (or only) case: false goes to exit or to statement if this
885 // node contains default.
886 if (len > 0) {
887 if (statement_start->IsTargetEntry()) {
888 *case_true_addresses[len - 1] = statement_start->AsTargetEntry();
889 } else {
890 TargetEntryInstr* true_target = new TargetEntryInstr();
891 *case_true_addresses[len - 1] = true_target;
892 true_target->SetSuccessor(statement_start);
893 }
894 TargetEntryInstr* false_target = new TargetEntryInstr();
895 *case_false_addresses[len - 1] = false_target;
896 if (node->contains_default()) {
897 // True and false go to statement start.
898 false_target->SetSuccessor(statement_start);
899 if (for_case_statements.is_open()) {
900 exit_instruction = new TargetEntryInstr();
901 for_case_statements.exit()->SetSuccessor(exit_instruction);
902 }
903 } else {
904 if (for_case_statements.is_open()) {
905 exit_instruction = new JoinEntryInstr();
906 for_case_statements.exit()->SetSuccessor(exit_instruction);
907 } else {
908 exit_instruction = new TargetEntryInstr();
909 }
910 false_target->SetSuccessor(exit_instruction);
911 }
912 } else {
913 // A CaseNode without case expressions must contain default.
914 ASSERT(node->contains_default());
915 AddInstruction(statement_start);
916 }
917
918 ASSERT(!is_open());
919 exit_ = exit_instruction;
788 } 920 }
789 921
790 922
791 // <Statement> ::= While { label: SourceLabel 923 // <Statement> ::= While { label: SourceLabel
792 // condition: <Expression> 924 // condition: <Expression>
793 // body: <Sequence> } 925 // body: <Sequence> }
794 // The fragment is composed as follows: 926 // The fragment is composed as follows:
795 // a) continue-join (optional) 927 // a) continue-join (optional)
796 // b) loop-join 928 // b) loop-join
797 // c) [ test ] -> (body-entry-target, loop-exit-target) 929 // c) [ test ] -> (body-entry-target, loop-exit-target)
(...skipping 1389 matching lines...) Expand 10 before | Expand all | Expand 10 after
2187 char* chars = reinterpret_cast<char*>( 2319 char* chars = reinterpret_cast<char*>(
2188 Isolate::Current()->current_zone()->Allocate(len)); 2320 Isolate::Current()->current_zone()->Allocate(len));
2189 OS::SNPrint(chars, len, kFormat, function_name, reason); 2321 OS::SNPrint(chars, len, kFormat, function_name, reason);
2190 const Error& error = Error::Handle( 2322 const Error& error = Error::Handle(
2191 LanguageError::New(String::Handle(String::New(chars)))); 2323 LanguageError::New(String::Handle(String::New(chars))));
2192 Isolate::Current()->long_jump_base()->Jump(1, error); 2324 Isolate::Current()->long_jump_base()->Jump(1, error);
2193 } 2325 }
2194 2326
2195 2327
2196 } // namespace dart 2328 } // 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