| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |