| 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/flags.h" | 7 #include "vm/flags.h" |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 #include "vm/longjump.h" | 9 #include "vm/longjump.h" |
| 10 #include "vm/os.h" | 10 #include "vm/os.h" |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 const RawFunction::Kind kind = owner()->parsed_function().function().kind(); | 163 const RawFunction::Kind kind = owner()->parsed_function().function().kind(); |
| 164 // Implicit getters do not need a type check at return. | 164 // Implicit getters do not need a type check at return. |
| 165 if ((kind != RawFunction::kImplicitGetter) && | 165 if ((kind != RawFunction::kImplicitGetter) && |
| 166 (kind != RawFunction::kConstImplicitGetter)) { | 166 (kind != RawFunction::kConstImplicitGetter)) { |
| 167 const AbstractType& type = | 167 const AbstractType& type = |
| 168 AbstractType::ZoneHandle( | 168 AbstractType::ZoneHandle( |
| 169 owner()->parsed_function().function().result_type()); | 169 owner()->parsed_function().function().result_type()); |
| 170 AssertAssignableComp* assert = | 170 AssertAssignableComp* assert = |
| 171 new AssertAssignableComp(return_value, type); | 171 new AssertAssignableComp(return_value, type); |
| 172 AddInstruction(new BindInstr(temp_index(), assert)); | 172 AddInstruction(new BindInstr(temp_index(), assert)); |
| 173 return_value = new TempValue(temp_index()); | 173 return_value = new TempVal(temp_index()); |
| 174 } | 174 } |
| 175 } | 175 } |
| 176 | 176 |
| 177 AddInstruction(new ReturnInstr(return_value)); | 177 AddInstruction(new ReturnInstr(return_value)); |
| 178 CloseFragment(); | 178 CloseFragment(); |
| 179 } | 179 } |
| 180 | 180 |
| 181 void ValueGraphVisitor::VisitReturnNode(ReturnNode* node) { UNREACHABLE(); } | 181 void ValueGraphVisitor::VisitReturnNode(ReturnNode* node) { UNREACHABLE(); } |
| 182 void TestGraphVisitor::VisitReturnNode(ReturnNode* node) { UNREACHABLE(); } | 182 void TestGraphVisitor::VisitReturnNode(ReturnNode* node) { UNREACHABLE(); } |
| 183 | 183 |
| 184 | 184 |
| 185 // <Expression> ::= Literal { literal: Instance } | 185 // <Expression> ::= Literal { literal: Instance } |
| 186 void EffectGraphVisitor::VisitLiteralNode(LiteralNode* node) { | 186 void EffectGraphVisitor::VisitLiteralNode(LiteralNode* node) { |
| 187 return; | 187 return; |
| 188 } | 188 } |
| 189 | 189 |
| 190 void ValueGraphVisitor::VisitLiteralNode(LiteralNode* node) { | 190 void ValueGraphVisitor::VisitLiteralNode(LiteralNode* node) { |
| 191 ReturnValue(new ConstantValue(node->literal())); | 191 ReturnValue(new ConstantVal(node->literal())); |
| 192 } | 192 } |
| 193 | 193 |
| 194 void TestGraphVisitor::VisitLiteralNode(LiteralNode* node) { | 194 void TestGraphVisitor::VisitLiteralNode(LiteralNode* node) { |
| 195 BranchOnValue(new ConstantValue(node->literal())); | 195 BranchOnValue(new ConstantVal(node->literal())); |
| 196 } | 196 } |
| 197 | 197 |
| 198 | 198 |
| 199 // Type nodes only occur as the right-hand side of instanceof comparisons, | 199 // Type nodes only occur as the right-hand side of instanceof comparisons, |
| 200 // and they are handled specially in that context. | 200 // and they are handled specially in that context. |
| 201 void EffectGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); } | 201 void EffectGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); } |
| 202 void ValueGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); } | 202 void ValueGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); } |
| 203 void TestGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); } | 203 void TestGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); } |
| 204 | 204 |
| 205 | 205 |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 int index = temp_index(); | 600 int index = temp_index(); |
| 601 for (intptr_t i = 0; i < node.length(); ++i) { | 601 for (intptr_t i = 0; i < node.length(); ++i) { |
| 602 ValueGraphVisitor for_value(owner(), index); | 602 ValueGraphVisitor for_value(owner(), index); |
| 603 node.NodeAt(i)->Visit(&for_value); | 603 node.NodeAt(i)->Visit(&for_value); |
| 604 Append(for_value); | 604 Append(for_value); |
| 605 CHECK_ALIVE(return); | 605 CHECK_ALIVE(return); |
| 606 Value* argument_value = for_value.value(); | 606 Value* argument_value = for_value.value(); |
| 607 index = for_value.temp_index(); | 607 index = for_value.temp_index(); |
| 608 if (argument_value->IsConstant()) { | 608 if (argument_value->IsConstant()) { |
| 609 AddInstruction(new BindInstr(index, argument_value)); | 609 AddInstruction(new BindInstr(index, argument_value)); |
| 610 argument_value = new TempValue(index++); | 610 argument_value = new TempVal(index++); |
| 611 } | 611 } |
| 612 values->Add(argument_value); | 612 values->Add(argument_value); |
| 613 } | 613 } |
| 614 } | 614 } |
| 615 | 615 |
| 616 // <Expression> ::= StaticCall { function: Function | 616 // <Expression> ::= StaticCall { function: Function |
| 617 // arguments: <ArgumentList> } | 617 // arguments: <ArgumentList> } |
| 618 StaticCallComp* EffectGraphVisitor::TranslateStaticCall( | 618 StaticCallComp* EffectGraphVisitor::TranslateStaticCall( |
| 619 const StaticCallNode& node) { | 619 const StaticCallNode& node) { |
| 620 int length = node.arguments()->length(); | 620 int length = node.arguments()->length(); |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 917 } | 917 } |
| 918 void ValueGraphVisitor::VisitInlinedFinallyNode(InlinedFinallyNode* node) { | 918 void ValueGraphVisitor::VisitInlinedFinallyNode(InlinedFinallyNode* node) { |
| 919 Bailout("ValueGraphVisitor::VisitInlinedFinallyNode"); | 919 Bailout("ValueGraphVisitor::VisitInlinedFinallyNode"); |
| 920 } | 920 } |
| 921 void TestGraphVisitor::VisitInlinedFinallyNode(InlinedFinallyNode* node) { | 921 void TestGraphVisitor::VisitInlinedFinallyNode(InlinedFinallyNode* node) { |
| 922 Bailout("TestGraphVisitor::VisitInlinedFinallyNode"); | 922 Bailout("TestGraphVisitor::VisitInlinedFinallyNode"); |
| 923 } | 923 } |
| 924 | 924 |
| 925 | 925 |
| 926 // Graph printing. | 926 // Graph printing. |
| 927 class FlowGraphPrinter : public InstructionVisitor { | 927 class FlowGraphPrinter : public FlowGraphVisitor { |
| 928 public: | 928 public: |
| 929 explicit FlowGraphPrinter(const Function& function) : function_(function) { } | 929 explicit FlowGraphPrinter(const Function& function) : function_(function) { } |
| 930 | 930 |
| 931 virtual ~FlowGraphPrinter() {} | 931 virtual ~FlowGraphPrinter() {} |
| 932 | 932 |
| 933 // Print the instructions in a block terminated by newlines. Add "goto N" | 933 // Print the instructions in a block terminated by newlines. Add "goto N" |
| 934 // to the end of the block if it ends with an unconditional jump to | 934 // to the end of the block if it ends with an unconditional jump to |
| 935 // another block and that block is not next in reverse postorder. | 935 // another block and that block is not next in reverse postorder. |
| 936 void VisitBlocks(const GrowableArray<BlockEntryInstr*>& block_order); | 936 void VisitBlocks(const GrowableArray<BlockEntryInstr*>& block_order); |
| 937 | 937 |
| 938 // Each visit function prints an instruction with a four space | 938 // Visiting a computation prints it with no indentation or newline. |
| 939 // indent and no trailing newline. Basic block entries are labeled | 939 #define DECLARE_VISIT_COMPUTATION(ShortName, ClassName) \ |
| 940 // with their block number. | 940 virtual void Visit##ShortName(ClassName* comp); |
| 941 #define DECLARE_VISIT(type) \ | 941 |
| 942 virtual void Visit##type(type##Instr* instr); | 942 // Visiting an instruction prints it with a four space indent and no |
| 943 FOR_EACH_INSTRUCTION(DECLARE_VISIT) | 943 // trailing newline. Basic block entries are labeled with their block |
| 944 #undef DECLARE_VISIT | 944 // number. |
| 945 #define DECLARE_VISIT_INSTRUCTION(ShortName) \ |
| 946 virtual void Visit##ShortName(ShortName##Instr* instr); |
| 947 |
| 948 FOR_EACH_COMPUTATION(DECLARE_VISIT_COMPUTATION) |
| 949 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) |
| 950 |
| 951 #undef DECLARE_VISIT_COMPUTATION |
| 952 #undef DECLARE_VISIT_INSTRUCTION |
| 945 | 953 |
| 946 private: | 954 private: |
| 947 const Function& function_; | 955 const Function& function_; |
| 948 | 956 |
| 949 DISALLOW_COPY_AND_ASSIGN(FlowGraphPrinter); | 957 DISALLOW_COPY_AND_ASSIGN(FlowGraphPrinter); |
| 950 }; | 958 }; |
| 951 | 959 |
| 952 | 960 |
| 953 void FlowGraphPrinter::VisitBlocks( | 961 void FlowGraphPrinter::VisitBlocks( |
| 954 const GrowableArray<BlockEntryInstr*>& block_order) { | 962 const GrowableArray<BlockEntryInstr*>& block_order) { |
| 955 OS::Print("==== %s\n", function_.ToFullyQualifiedCString()); | 963 OS::Print("==== %s\n", function_.ToFullyQualifiedCString()); |
| 956 | 964 |
| 957 for (intptr_t i = block_order.length() - 1; i >= 0; --i) { | 965 for (intptr_t i = block_order.length() - 1; i >= 0; --i) { |
| 958 // Print the block entry. | 966 // Print the block entry. |
| 959 Instruction* current = block_order[i]->Accept(this); | 967 Instruction* current = block_order[i]->Accept(this); |
| 960 // And all the successors until an exit, branch, or a block entry. | 968 // And all the successors until an exit, branch, or a block entry. |
| 961 while ((current != NULL) && !current->IsBlockEntry()) { | 969 while ((current != NULL) && !current->IsBlockEntry()) { |
| 962 OS::Print("\n"); | 970 OS::Print("\n"); |
| 963 current = current->Accept(this); | 971 current = current->Accept(this); |
| 964 } | 972 } |
| 965 if ((current != NULL) && current->IsBlockEntry()) { | 973 if ((current != NULL) && current->IsBlockEntry()) { |
| 966 OS::Print(" goto %d", BlockEntryInstr::cast(current)->block_number()); | 974 OS::Print(" goto %d", BlockEntryInstr::cast(current)->block_number()); |
| 967 } | 975 } |
| 968 OS::Print("\n"); | 976 OS::Print("\n"); |
| 969 } | 977 } |
| 970 } | 978 } |
| 971 | 979 |
| 972 | 980 |
| 981 void FlowGraphPrinter::VisitTemp(TempVal* val) { |
| 982 OS::Print("t%d", val->index()); |
| 983 } |
| 984 |
| 985 |
| 986 void FlowGraphPrinter::VisitConstant(ConstantVal* val) { |
| 987 OS::Print("#%s", val->instance().ToCString()); |
| 988 } |
| 989 |
| 990 |
| 991 void FlowGraphPrinter::VisitAssertAssignable(AssertAssignableComp* comp) { |
| 992 OS::Print("AssertAssignable("); |
| 993 comp->value()->Accept(this); |
| 994 OS::Print(", %s)", comp->type().ToCString()); |
| 995 } |
| 996 |
| 997 |
| 998 void FlowGraphPrinter::VisitInstanceCall(InstanceCallComp* comp) { |
| 999 OS::Print("InstanceCall(%s", comp->name()); |
| 1000 for (int i = 0; i < comp->ArgumentCount(); ++i) { |
| 1001 OS::Print(", "); |
| 1002 comp->ArgumentAt(i)->Accept(this); |
| 1003 } |
| 1004 OS::Print(")"); |
| 1005 } |
| 1006 |
| 1007 |
| 1008 void FlowGraphPrinter::VisitStrictCompare(StrictCompareComp* comp) { |
| 1009 OS::Print("StrictCompare(%s, ", Token::Str(comp->kind())); |
| 1010 comp->left()->Accept(this); |
| 1011 OS::Print(", "); |
| 1012 comp->right()->Accept(this); |
| 1013 OS::Print(")"); |
| 1014 } |
| 1015 |
| 1016 |
| 1017 |
| 1018 void FlowGraphPrinter::VisitStaticCall(StaticCallComp* comp) { |
| 1019 OS::Print("StaticCall(%s", |
| 1020 String::Handle(comp->function().name()).ToCString()); |
| 1021 for (int i = 0; i < comp->ArgumentCount(); ++i) { |
| 1022 OS::Print(", "); |
| 1023 comp->ArgumentAt(i)->Accept(this); |
| 1024 } |
| 1025 OS::Print(")"); |
| 1026 } |
| 1027 |
| 1028 |
| 1029 void FlowGraphPrinter::VisitLoadLocal(LoadLocalComp* comp) { |
| 1030 OS::Print("LoadLocal(%s)", comp->local().name().ToCString()); |
| 1031 } |
| 1032 |
| 1033 |
| 1034 void FlowGraphPrinter::VisitStoreLocal(StoreLocalComp* comp) { |
| 1035 OS::Print("StoreLocal(%s, ", comp->local().name().ToCString()); |
| 1036 comp->value()->Accept(this); |
| 1037 OS::Print(")"); |
| 1038 } |
| 1039 |
| 1040 |
| 973 void FlowGraphPrinter::VisitJoinEntry(JoinEntryInstr* instr) { | 1041 void FlowGraphPrinter::VisitJoinEntry(JoinEntryInstr* instr) { |
| 974 OS::Print("%2d: [join]", instr->block_number()); | 1042 OS::Print("%2d: [join]", instr->block_number()); |
| 975 } | 1043 } |
| 976 | 1044 |
| 977 | 1045 |
| 978 void FlowGraphPrinter::VisitTargetEntry(TargetEntryInstr* instr) { | 1046 void FlowGraphPrinter::VisitTargetEntry(TargetEntryInstr* instr) { |
| 979 OS::Print("%2d: [target]", instr->block_number()); | 1047 OS::Print("%2d: [target]", instr->block_number()); |
| 980 } | 1048 } |
| 981 | 1049 |
| 982 | 1050 |
| 983 void FlowGraphPrinter::VisitDo(DoInstr* instr) { | 1051 void FlowGraphPrinter::VisitDo(DoInstr* instr) { |
| 984 OS::Print(" "); | 1052 OS::Print(" "); |
| 985 instr->computation()->Print(); | 1053 instr->computation()->Accept(this); |
| 986 } | 1054 } |
| 987 | 1055 |
| 988 | 1056 |
| 989 void FlowGraphPrinter::VisitBind(BindInstr* instr) { | 1057 void FlowGraphPrinter::VisitBind(BindInstr* instr) { |
| 990 OS::Print(" t%d <-", instr->temp_index()); | 1058 OS::Print(" t%d <-", instr->temp_index()); |
| 991 instr->computation()->Print(); | 1059 instr->computation()->Accept(this); |
| 992 } | 1060 } |
| 993 | 1061 |
| 994 | 1062 |
| 995 void FlowGraphPrinter::VisitReturn(ReturnInstr* instr) { | 1063 void FlowGraphPrinter::VisitReturn(ReturnInstr* instr) { |
| 996 OS::Print(" return "); | 1064 OS::Print(" return "); |
| 997 instr->value()->Print(); | 1065 instr->value()->Accept(this); |
| 998 } | 1066 } |
| 999 | 1067 |
| 1000 | 1068 |
| 1001 void FlowGraphPrinter::VisitBranch(BranchInstr* instr) { | 1069 void FlowGraphPrinter::VisitBranch(BranchInstr* instr) { |
| 1002 OS::Print(" if "); | 1070 OS::Print(" if "); |
| 1003 instr->value()->Print(); | 1071 instr->value()->Accept(this); |
| 1004 OS::Print(" goto(%d, %d)", instr->true_successor()->block_number(), | 1072 OS::Print(" goto(%d, %d)", instr->true_successor()->block_number(), |
| 1005 instr->false_successor()->block_number()); | 1073 instr->false_successor()->block_number()); |
| 1006 } | 1074 } |
| 1007 | 1075 |
| 1008 | 1076 |
| 1009 void FlowGraphBuilder::BuildGraph() { | 1077 void FlowGraphBuilder::BuildGraph() { |
| 1010 EffectGraphVisitor for_effect(this, 0); | 1078 EffectGraphVisitor for_effect(this, 0); |
| 1011 for_effect.AddInstruction(new TargetEntryInstr()); | 1079 for_effect.AddInstruction(new TargetEntryInstr()); |
| 1012 parsed_function().node_sequence()->Visit(&for_effect); | 1080 parsed_function().node_sequence()->Visit(&for_effect); |
| 1013 if (for_effect.entry() != NULL) { | 1081 if (for_effect.entry() != NULL) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1032 char* chars = reinterpret_cast<char*>( | 1100 char* chars = reinterpret_cast<char*>( |
| 1033 Isolate::Current()->current_zone()->Allocate(len)); | 1101 Isolate::Current()->current_zone()->Allocate(len)); |
| 1034 OS::SNPrint(chars, len, kFormat, reason); | 1102 OS::SNPrint(chars, len, kFormat, reason); |
| 1035 const Error& error = Error::Handle( | 1103 const Error& error = Error::Handle( |
| 1036 LanguageError::New(String::Handle(String::New(chars)))); | 1104 LanguageError::New(String::Handle(String::New(chars)))); |
| 1037 Isolate::Current()->long_jump_base()->Jump(1, error); | 1105 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 1038 } | 1106 } |
| 1039 | 1107 |
| 1040 | 1108 |
| 1041 } // namespace dart | 1109 } // namespace dart |
| OLD | NEW |