Index: runtime/vm/flow_graph_builder.cc |
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..3a57ccaaaa7f5466cd53b7ef4946ba9b06c8c671 |
--- /dev/null |
+++ b/runtime/vm/flow_graph_builder.cc |
@@ -0,0 +1,904 @@ |
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+#include "vm/flow_graph_builder.h" |
+ |
+#include "vm/flags.h" |
+#include "vm/intermediate_language.h" |
+#include "vm/os.h" |
+#include "vm/parser.h" |
+ |
+namespace dart { |
+ |
+DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from graph builder."); |
+DEFINE_FLAG(bool, print_flow_graph, false, "Print the IR flow graph."); |
+DECLARE_FLAG(bool, enable_type_checks); |
+ |
+void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) { |
+ ASSERT(is_open()); |
+ if (other_fragment.is_empty()) return; |
+ if (is_empty()) { |
+ entry_ = other_fragment.entry(); |
+ exit_ = other_fragment.exit(); |
+ } else { |
+ exit()->set_successor(other_fragment.entry()); |
+ exit_ = other_fragment.exit(); |
+ } |
+} |
+ |
+ |
+void EffectGraphVisitor::AddInstruction(Instruction* instruction) { |
+ ASSERT(is_open()); |
+ if (is_empty()) { |
+ entry_ = exit_ = instruction; |
+ } else { |
+ exit()->set_successor(instruction); |
+ exit_ = instruction; |
+ } |
+} |
+ |
+ |
+void EffectGraphVisitor::Join(const TestGraphVisitor& test_fragment, |
+ const EffectGraphVisitor& true_fragment, |
+ const EffectGraphVisitor& false_fragment) { |
+ // We have: a test graph fragment with zero, one, or two available exits; |
+ // and a pair of effect graph fragments with zero or one available exits. |
+ // We want to append the branch and (if necessary) a join node to this |
+ // graph fragment. |
+ ASSERT(is_open()); |
+ |
+ // 1. Connect the test to this graph. |
+ Append(test_fragment); |
+ |
+ // 2. Connect the true body to the test if it is reachable, and if so |
+ // record its exit (if any). |
+ Instruction* true_exit = NULL; |
+ if (test_fragment.can_be_true()) { |
+ TargetEntryInstr* true_entry = new TargetEntryInstr(); |
+ *test_fragment.true_successor_address() = true_entry; |
+ true_entry->set_successor(true_fragment.entry()); |
+ true_exit = true_fragment.is_empty() ? true_entry : true_fragment.exit(); |
+ } |
+ |
+ // 3. Connect the false body to the test if it is reachable, and if so |
+ // record its exit (if any). |
+ Instruction* false_exit = NULL; |
+ if (test_fragment.can_be_false()) { |
+ TargetEntryInstr* false_entry = new TargetEntryInstr(); |
+ *test_fragment.false_successor_address() = false_entry; |
+ false_entry->set_successor(false_fragment.entry()); |
+ false_exit = |
+ false_fragment.is_empty() ? false_entry : false_fragment.exit(); |
+ } |
+ |
+ // 4. Set the exit of this graph depending on which bodies are reachable |
+ // from the test and have open exits. |
+ if (true_exit == NULL) { |
+ exit_ = false_exit; // May be NULL. |
+ } else if (false_exit == NULL) { |
+ exit_ = true_exit; |
+ } else { |
+ exit_ = new JoinEntryInstr(); |
+ true_exit->set_successor(exit_); |
+ false_exit->set_successor(exit_); |
+ } |
+} |
+ |
+ |
+void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment, |
+ const EffectGraphVisitor& body_fragment) { |
+ // We have: a test graph fragment with zero, one, or two available exits; |
+ // and an effect graph fragment with zero or one available exits. We want |
+ // to append the 'while loop' consisting of the test graph fragment as |
+ // condition and the effect graph fragment as body. |
+ ASSERT(is_open()); |
+ |
+ // 1. Connect the body to the test if it is reachable, and if so record |
+ // its exit (if any). |
+ Instruction* body_exit = NULL; |
+ if (test_fragment.can_be_true()) { |
+ TargetEntryInstr* body_entry = new TargetEntryInstr(); |
+ *test_fragment.true_successor_address() = body_entry; |
+ body_entry->set_successor(body_fragment.entry()); |
+ body_exit = body_fragment.is_empty() ? body_entry : body_fragment.exit(); |
+ } |
+ |
+ // 2. Connect the test to this graph, including the body if reachable and |
+ // using a fresh join node if the body is reachable and has an open exit. |
+ if (body_exit == NULL) { |
+ Append(test_fragment); |
+ } else { |
+ JoinEntryInstr* join = new JoinEntryInstr(); |
+ AddInstruction(join); |
+ join->set_successor(test_fragment.entry()); |
+ body_exit->set_successor(join); |
+ } |
+ |
+ // 3. Set the exit to the graph to be empty or a fresh target node |
+ // depending on whether the false branch of the test is reachable. |
+ if (test_fragment.can_be_false()) { |
+ exit_ = *test_fragment.false_successor_address() = new TargetEntryInstr(); |
+ } else { |
+ exit_ = NULL; |
+ } |
+} |
+ |
+ |
+void TestGraphVisitor::BranchOnValue(Value* value) { |
+ BranchInstr* branch = new BranchInstr(value); |
+ AddInstruction(branch); |
+ CloseFragment(); |
+ true_successor_address_ = branch->true_successor_address(); |
+ false_successor_address_ = branch->false_successor_address(); |
+} |
+ |
+ |
+void EffectGraphVisitor::Bailout(const char* reason) { |
+ if (FLAG_trace_bailout) { |
+ OS::Print("Flow Graph Bailout: %s\n", reason); |
+ } |
+ bailing_out_ = true; |
+ owner()->Bailout(reason); |
srdjan
2012/02/21 14:33:41
If 'baling_out_' is always true when owner->Bailou
Kevin Millikin (Google)
2012/02/22 13:15:42
Done.
|
+} |
+ |
+ |
+#define CHECK_ALIVE(bailout) \ |
+ do { \ |
+ if (bailing_out() || !is_open()) { \ |
srdjan
2012/02/21 14:33:41
Question: when can it happen that we are visiting
Kevin Millikin (Google)
2012/02/22 13:15:42
After visiting a break, continue, return, or throw
srdjan
2012/02/22 14:08:16
Please add a comment when graph cannot be open (as
|
+ bailout; \ |
+ } \ |
+ } while (false) |
+ |
+ |
+// <Statement> ::= Return { value: <Expression> |
+// inlined_finally_list: <InlinedFinally>* } |
+void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) { |
+ ValueGraphVisitor for_value(owner(), temp_index()); |
+ node->value()->Visit(&for_value); |
+ Append(for_value); |
+ CHECK_ALIVE(return); |
+ |
+ for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { |
+ EffectGraphVisitor for_effect(owner(), for_value.temp_index()); |
+ node->InlinedFinallyNodeAt(i)->Visit(&for_effect); |
+ Append(for_effect); |
+ CHECK_ALIVE(return); |
+ } |
+ |
+ Value* return_value = for_value.value(); |
+ if (FLAG_enable_type_checks) { |
+ const RawFunction::Kind kind = owner()->parsed_function().function().kind(); |
+ // Implicit getters do not need a type check at return. |
+ if (kind != RawFunction::kImplicitGetter && |
+ kind != RawFunction::kConstImplicitGetter) { |
+ const AbstractType& type = |
+ AbstractType::ZoneHandle( |
+ owner()->parsed_function().function().result_type()); |
+ AssertAssignableComp* assert = |
+ new AssertAssignableComp(return_value, type); |
+ AddInstruction(new BindInstr(temp_index(), assert)); |
+ return_value = new TempValue(temp_index()); |
+ } |
+ } |
+ |
+ AddInstruction(new ReturnInstr(return_value)); |
+ CloseFragment(); |
+} |
+ |
+void ValueGraphVisitor::VisitReturnNode(ReturnNode* node) { UNREACHABLE(); } |
+void TestGraphVisitor::VisitReturnNode(ReturnNode* node) { UNREACHABLE(); } |
+ |
+ |
+// <Expression> ::= Literal { literal: Instance } |
+void EffectGraphVisitor::VisitLiteralNode(LiteralNode* node) { |
+ return; |
+} |
+ |
+void ValueGraphVisitor::VisitLiteralNode(LiteralNode* node) { |
+ ReturnValue(new ConstantValue(node->literal())); |
+} |
+ |
+void TestGraphVisitor::VisitLiteralNode(LiteralNode* node) { |
+ BranchOnValue(new ConstantValue(node->literal())); |
+} |
+ |
+ |
+// Type nodes only occur as the right-hand side of instanceof comparisons, |
+// and they are handled specially in that context. |
+void EffectGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); } |
+void ValueGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); } |
+void TestGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); } |
+ |
+ |
+// <Expression> :: Assignable { expr: <Expression> |
+// type: AbstractType |
+// dst_name: String } |
+AssertAssignableComp* EffectGraphVisitor::TranslateAssignable( |
+ AssignableNode* node) { |
+ ValueGraphVisitor for_value(owner(), temp_index()); |
+ node->expr()->Visit(&for_value); |
+ Append(for_value); |
+ CHECK_ALIVE(return NULL); |
+ |
+ return new AssertAssignableComp(for_value.value(), node->type()); |
+} |
+ |
+void EffectGraphVisitor::VisitAssignableNode(AssignableNode* node) { |
+ AssertAssignableComp* assert = TranslateAssignable(node); |
+ CHECK_ALIVE(return); |
+ DoComputation(assert); |
+} |
+ |
+void ValueGraphVisitor::VisitAssignableNode(AssignableNode* node) { |
+ AssertAssignableComp* assert = TranslateAssignable(node); |
+ CHECK_ALIVE(return); |
+ ReturnValueOf(assert); |
+} |
+ |
+ |
+void TestGraphVisitor::VisitAssignableNode(AssignableNode* node) { |
+ AssertAssignableComp* assert = TranslateAssignable(node); |
+ CHECK_ALIVE(return); |
+ BranchOnValueOf(assert); |
+} |
+ |
+ |
+// <Expression> :: BinaryOp { kind: Token::Kind |
+// left: <Expression> |
+// right: <Expression> } |
+InstanceCallComp* EffectGraphVisitor::TranslateBinaryOp(BinaryOpNode* node) { |
+ if (node->kind() == Token::kAND || node->kind() == Token::kOR) { |
+ Bailout("EffectGraphVisitor::VisitBinaryOpNode"); |
+ return NULL; |
+ } |
+ ValueGraphVisitor for_left_value(owner(), temp_index()); |
+ node->left()->Visit(&for_left_value); |
+ Append(for_left_value); |
+ CHECK_ALIVE(return NULL); |
+ ValueGraphVisitor for_right_value(owner(), for_left_value.temp_index()); |
+ node->right()->Visit(&for_right_value); |
+ Append(for_right_value); |
+ CHECK_ALIVE(return NULL); |
+ ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2); |
+ arguments->Add(for_left_value.value()); |
+ arguments->Add(for_right_value.value()); |
+ return new InstanceCallComp(node->Name(), arguments); |
+} |
+ |
+void EffectGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) { |
+ InstanceCallComp* call = TranslateBinaryOp(node); |
+ CHECK_ALIVE(return); |
+ DoComputation(call); |
+} |
+ |
+void ValueGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) { |
+ InstanceCallComp* call = TranslateBinaryOp(node); |
+ CHECK_ALIVE(return); |
+ ReturnValueOf(call); |
+} |
+ |
+void TestGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) { |
+ InstanceCallComp* call = TranslateBinaryOp(node); |
+ CHECK_ALIVE(return); |
+ BranchOnValueOf(call); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitStringConcatNode(StringConcatNode* node) { |
+ Bailout("EffectGraphVisitor::VisitStringConcatNode"); |
+} |
+void ValueGraphVisitor::VisitStringConcatNode(StringConcatNode* node) { |
+ Bailout("ValueGraphVisitor::VisitStringConcatNode"); |
+} |
+void TestGraphVisitor::VisitStringConcatNode(StringConcatNode* node) { |
+ Bailout("TestGraphVisitor::VisitStringConcatNode"); |
+} |
+ |
+ |
+// <Expression> :: Comparison { kind: Token::Kind |
+// left: <Expression> |
+// right: <Expression> } |
+InstanceCallComp* EffectGraphVisitor::TranslateComparison( |
+ ComparisonNode* node) { |
+ if (Token::IsInstanceofOperator(node->kind()) || |
+ node->kind() == Token::kEQ_STRICT || |
+ node->kind() == Token::kNE_STRICT || |
+ node->kind() == Token::kEQ || |
+ node->kind() == Token::kNE) { |
+ Bailout("Some kind of comparison we don't handle yet"); |
+ return NULL; |
+ } |
+ ValueGraphVisitor for_left_value(owner(), temp_index()); |
+ node->left()->Visit(&for_left_value); |
+ Append(for_left_value); |
+ CHECK_ALIVE(return NULL); |
+ ValueGraphVisitor for_right_value(owner(), for_left_value.temp_index()); |
+ node->right()->Visit(&for_right_value); |
+ Append(for_right_value); |
+ CHECK_ALIVE(return NULL); |
+ ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2); |
+ arguments->Add(for_left_value.value()); |
+ arguments->Add(for_right_value.value()); |
+ return new InstanceCallComp(node->Name(), arguments); |
+} |
+ |
+void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) { |
+ InstanceCallComp* call = TranslateComparison(node); |
+ CHECK_ALIVE(return); |
+ DoComputation(call); |
+} |
+ |
+void ValueGraphVisitor::VisitComparisonNode(ComparisonNode* node) { |
+ InstanceCallComp* call = TranslateComparison(node); |
+ CHECK_ALIVE(return); |
+ ReturnValueOf(call); |
+} |
+ |
+void TestGraphVisitor::VisitComparisonNode(ComparisonNode* node) { |
+ InstanceCallComp* call = TranslateComparison(node); |
+ CHECK_ALIVE(return); |
+ BranchOnValueOf(call); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitUnaryOpNode(UnaryOpNode* node) { |
+ Bailout("EffectGraphVisitor::VisitUnaryOpNode"); |
+} |
+void ValueGraphVisitor::VisitUnaryOpNode(UnaryOpNode* node) { |
+ Bailout("ValueGraphVisitor::VisitUnaryOpNode"); |
+} |
+void TestGraphVisitor::VisitUnaryOpNode(UnaryOpNode* node) { |
+ Bailout("TestGraphVisitor::VisitUnaryOpNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitIncrOpLocalNode(IncrOpLocalNode* node) { |
+ Bailout("EffectGraphVisitor::VisitIncrOpLocalNode"); |
+} |
+void ValueGraphVisitor::VisitIncrOpLocalNode(IncrOpLocalNode* node) { |
+ Bailout("ValueGraphVisitor::VisitIncrOpLocalNode"); |
+} |
+void TestGraphVisitor::VisitIncrOpLocalNode(IncrOpLocalNode* node) { |
+ Bailout("TestGraphVisitor::VisitIncrOpLocalNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitIncrOpInstanceFieldNode( |
+ IncrOpInstanceFieldNode* node) { |
+ Bailout("EffectGraphVisitor::VisitIncrOpInstanceFieldNode"); |
+} |
+void ValueGraphVisitor::VisitIncrOpInstanceFieldNode( |
+ IncrOpInstanceFieldNode* node) { |
+ Bailout("ValueGraphVisitor::VisitIncrOpInstanceFieldNode"); |
+} |
+void TestGraphVisitor::VisitIncrOpInstanceFieldNode( |
+ IncrOpInstanceFieldNode* node) { |
+ Bailout("TestGraphVisitor::VisitIncrOpInstanceFieldNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitIncrOpStaticFieldNode( |
+ IncrOpStaticFieldNode* node) { |
+ Bailout("EffectGraphVisitor::VisitIncrOpStaticFieldNode"); |
+} |
+void ValueGraphVisitor::VisitIncrOpStaticFieldNode( |
+ IncrOpStaticFieldNode* node) { |
+ Bailout("ValueGraphVisitor::VisitIncrOpStaticFieldNode"); |
+} |
+void TestGraphVisitor::VisitIncrOpStaticFieldNode(IncrOpStaticFieldNode* node) { |
+ Bailout("TestGraphVisitor::VisitIncrOpStaticFieldNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitIncrOpIndexedNode(IncrOpIndexedNode* node) { |
+ Bailout("EffectGraphVisitor::VisitIncrOpIndexedNode"); |
+} |
+void ValueGraphVisitor::VisitIncrOpIndexedNode(IncrOpIndexedNode* node) { |
+ Bailout("ValueGraphVisitor::VisitIncrOpIndexedNode"); |
+} |
+void TestGraphVisitor::VisitIncrOpIndexedNode(IncrOpIndexedNode* node) { |
+ Bailout("TestGraphVisitor::VisitIncrOpIndexedNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) { |
+ Bailout("EffectGraphVisitor::VisitConditionalExprNode"); |
+} |
+void ValueGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) { |
+ Bailout("ValueGraphVisitor::VisitConditionalExprNode"); |
+} |
+void TestGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) { |
+ Bailout("TestGraphVisitor::VisitConditionalExprNode"); |
+} |
+ |
+ |
+// <Statement> ::= If { condition: <Expression> |
+// true_branch: <Sequence> |
+// false_branch: <Sequence> } |
+void EffectGraphVisitor::VisitIfNode(IfNode* node) { |
+ TestGraphVisitor for_test(owner(), temp_index()); |
+ node->condition()->Visit(&for_test); |
+ Append(for_test); |
+ |
+ EffectGraphVisitor for_true(owner(), temp_index()); |
+ EffectGraphVisitor for_false(owner(), temp_index()); |
+ |
+ if (for_test.can_be_true()) node->true_branch()->Visit(&for_true); |
+ if (for_test.can_be_false()) { |
+ // The for_false graph fragment will be empty (default graph fragment) |
+ // if we do not call Visit. |
+ if (node->false_branch() != NULL) node->false_branch()->Visit(&for_false); |
+ } |
+ Join(for_test, for_true, for_false); |
+} |
+ |
+void ValueGraphVisitor::VisitIfNode(IfNode* node) { UNREACHABLE(); } |
+void TestGraphVisitor::VisitIfNode(IfNode* node) { UNREACHABLE(); } |
+ |
+ |
+void EffectGraphVisitor::VisitSwitchNode(SwitchNode* node) { |
+ Bailout("EffectGraphVisitor::VisitSwitchNode"); |
+} |
+void ValueGraphVisitor::VisitSwitchNode(SwitchNode* node) { |
+ Bailout("ValueGraphVisitor::VisitSwitchNode"); |
+} |
+void TestGraphVisitor::VisitSwitchNode(SwitchNode* node) { |
+ Bailout("TestGraphVisitor::VisitSwitchNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitCaseNode(CaseNode* node) { |
+ Bailout("EffectGraphVisitor::VisitCaseNode"); |
+} |
+void ValueGraphVisitor::VisitCaseNode(CaseNode* node) { |
+ Bailout("ValueGraphVisitor::VisitCaseNode"); |
+} |
+void TestGraphVisitor::VisitCaseNode(CaseNode* node) { |
+ Bailout("TestGraphVisitor::VisitCaseNode"); |
+} |
+ |
+ |
+// <Statement> ::= While { label: SourceLabel |
+// condition: <Expression> |
+// body: <Sequence> } |
+void EffectGraphVisitor::VisitWhileNode(WhileNode* node) { |
+ TestGraphVisitor for_test(owner(), temp_index()); |
+ node->condition()->Visit(&for_test); |
+ |
+ EffectGraphVisitor for_body(owner(), temp_index()); |
+ if (for_test.can_be_true()) node->body()->Visit(&for_body); |
+ TieLoop(for_test, for_body); |
+} |
+ |
+void ValueGraphVisitor::VisitWhileNode(WhileNode* node) { UNREACHABLE(); } |
+void TestGraphVisitor::VisitWhileNode(WhileNode* node) { UNREACHABLE(); } |
+ |
+ |
+void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { |
+ Bailout("EffectGraphVisitor::VisitDoWhileNode"); |
+} |
+void ValueGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { |
+ Bailout("ValueGraphVisitor::VisitDoWhileNode"); |
+} |
+void TestGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { |
+ Bailout("TestGraphVisitor::VisitDoWhileNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitForNode(ForNode* node) { |
+ Bailout("EffectGraphVisitor::VisitForNode"); |
+} |
+void ValueGraphVisitor::VisitForNode(ForNode* node) { |
+ Bailout("ValueGraphVisitor::VisitForNode"); |
+} |
+void TestGraphVisitor::VisitForNode(ForNode* node) { |
+ Bailout("TestGraphVisitor::VisitForNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { |
+ Bailout("EffectGraphVisitor::VisitJumpNode"); |
+} |
+void ValueGraphVisitor::VisitJumpNode(JumpNode* node) { |
+ Bailout("ValueGraphVisitor::VisitJumpNode"); |
+} |
+void TestGraphVisitor::VisitJumpNode(JumpNode* node) { |
+ Bailout("TestGraphVisitor::VisitJumpNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) { |
+ UNREACHABLE(); |
+} |
+void ValueGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) { |
+ UNREACHABLE(); |
+} |
+void TestGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) { |
+ UNREACHABLE(); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) { |
+ Bailout("EffectGraphVisitor::VisitArrayNode"); |
+} |
+void ValueGraphVisitor::VisitArrayNode(ArrayNode* node) { |
+ Bailout("ValueGraphVisitor::VisitArrayNode"); |
+} |
+void TestGraphVisitor::VisitArrayNode(ArrayNode* node) { |
+ Bailout("TestGraphVisitor::VisitArrayNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) { |
+ Bailout("EffectGraphVisitor::VisitClosureNode"); |
+} |
+void ValueGraphVisitor::VisitClosureNode(ClosureNode* node) { |
+ Bailout("ValueGraphVisitor::VisitClosureNode"); |
+} |
+void TestGraphVisitor::VisitClosureNode(ClosureNode* node) { |
+ Bailout("TestGraphVisitor::VisitClosureNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) { |
+ Bailout("EffectGraphVisitor::VisitInstanceCallNode"); |
+} |
+void ValueGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) { |
+ Bailout("ValueGraphVisitor::VisitInstanceCallNode"); |
+} |
+void TestGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) { |
+ Bailout("TestGraphVisitor::VisitInstanceCallNode"); |
+} |
+ |
+ |
+// <Expression> ::= StaticCall { function: Function |
+// arguments: <ArgumentList> } |
+StaticCallComp* EffectGraphVisitor::TranslateStaticCall(StaticCallNode* node) { |
+ ArgumentListNode* arguments = node->arguments(); |
+ int length = arguments->length(); |
+ ZoneGrowableArray<Value*>* values = new ZoneGrowableArray<Value*>(length); |
+ int index = temp_index(); |
+ for (intptr_t i = 0; i < length; ++i) { |
+ ValueGraphVisitor for_value(owner(), index); |
+ arguments->NodeAt(i)->Visit(&for_value); |
+ Append(for_value); |
+ CHECK_ALIVE(return NULL); |
+ values->Add(for_value.value()); |
+ index = for_value.temp_index(); |
+ } |
+ return new StaticCallComp(node->function(), values); |
+} |
+ |
+void EffectGraphVisitor::VisitStaticCallNode(StaticCallNode* node) { |
+ StaticCallComp* call = TranslateStaticCall(node); |
+ CHECK_ALIVE(return); |
+ DoComputation(call); |
+} |
+ |
+void ValueGraphVisitor::VisitStaticCallNode(StaticCallNode* node) { |
+ StaticCallComp* call = TranslateStaticCall(node); |
+ CHECK_ALIVE(return); |
+ ReturnValueOf(call); |
+} |
+ |
+void TestGraphVisitor::VisitStaticCallNode(StaticCallNode* node) { |
+ StaticCallComp* call = TranslateStaticCall(node); |
+ CHECK_ALIVE(return); |
+ BranchOnValueOf(call); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { |
+ Bailout("EffectGraphVisitor::VisitClosureCallNode"); |
+} |
+void ValueGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { |
+ Bailout("ValueGraphVisitor::VisitClosureCallNode"); |
+} |
+void TestGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { |
+ Bailout("TestGraphVisitor::VisitClosureCallNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitCloneContextNode(CloneContextNode* node) { |
+ Bailout("EffectGraphVisitor::VisitCloneContextNode"); |
+} |
+void ValueGraphVisitor::VisitCloneContextNode(CloneContextNode* node) { |
+ Bailout("ValueGraphVisitor::VisitCloneContextNode"); |
+} |
+void TestGraphVisitor::VisitCloneContextNode(CloneContextNode* node) { |
+ Bailout("TestGraphVisitor::VisitCloneContextNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) { |
+ Bailout("EffectGraphVisitor::VisitConstructorCallNode"); |
+} |
+void ValueGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) { |
+ Bailout("ValueGraphVisitor::VisitConstructorCallNode"); |
+} |
+void TestGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) { |
+ Bailout("TestGraphVisitor::VisitConstructorCallNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitInstanceGetterNode(InstanceGetterNode* node) { |
+ Bailout("EffectGraphVisitor::VisitInstanceGetterNode"); |
+} |
+void ValueGraphVisitor::VisitInstanceGetterNode(InstanceGetterNode* node) { |
+ Bailout("ValueGraphVisitor::VisitInstanceGetterNode"); |
+} |
+void TestGraphVisitor::VisitInstanceGetterNode(InstanceGetterNode* node) { |
+ Bailout("TestGraphVisitor::VisitInstanceGetterNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) { |
+ Bailout("EffectGraphVisitor::VisitInstanceSetterNode"); |
+} |
+void ValueGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) { |
+ Bailout("ValueGraphVisitor::VisitInstanceSetterNode"); |
+} |
+void TestGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) { |
+ Bailout("TestGraphVisitor::VisitInstanceSetterNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitStaticGetterNode(StaticGetterNode* node) { |
+ Bailout("EffectGraphVisitor::VisitStaticGetterNode"); |
+} |
+void ValueGraphVisitor::VisitStaticGetterNode(StaticGetterNode* node) { |
+ Bailout("ValueGraphVisitor::VisitStaticGetterNode"); |
+} |
+void TestGraphVisitor::VisitStaticGetterNode(StaticGetterNode* node) { |
+ Bailout("TestGraphVisitor::VisitStaticGetterNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitStaticSetterNode(StaticSetterNode* node) { |
+ Bailout("EffectGraphVisitor::VisitStaticSetterNode"); |
+} |
+void ValueGraphVisitor::VisitStaticSetterNode(StaticSetterNode* node) { |
+ Bailout("ValueGraphVisitor::VisitStaticSetterNode"); |
+} |
+void TestGraphVisitor::VisitStaticSetterNode(StaticSetterNode* node) { |
+ Bailout("TestGraphVisitor::VisitStaticSetterNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) { |
+ Bailout("EffectGraphVisitor::VisitNativeBodyNode"); |
+} |
+void ValueGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) { |
+ Bailout("ValueGraphVisitor::VisitNativeBodyNode"); |
+} |
+void TestGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) { |
+ Bailout("TestGraphVisitor::VisitNativeBodyNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitPrimaryNode(PrimaryNode* node) { |
+ Bailout("EffectGraphVisitor::VisitPrimaryNode"); |
+} |
+void ValueGraphVisitor::VisitPrimaryNode(PrimaryNode* node) { |
+ Bailout("ValueGraphVisitor::VisitPrimaryNode"); |
+} |
+void TestGraphVisitor::VisitPrimaryNode(PrimaryNode* node) { |
+ Bailout("TestGraphVisitor::VisitPrimaryNode"); |
+} |
+ |
+ |
+// <Expression> ::= LoadLocal { local: LocalVariable } |
+void EffectGraphVisitor::VisitLoadLocalNode(LoadLocalNode* node) { |
+ return; |
+} |
+ |
+void ValueGraphVisitor::VisitLoadLocalNode(LoadLocalNode* node) { |
+ LoadLocalComp* load = new LoadLocalComp(node->local()); |
+ ReturnValueOf(load); |
+} |
+ |
+void TestGraphVisitor::VisitLoadLocalNode(LoadLocalNode* node) { |
+ LoadLocalComp* load = new LoadLocalComp(node->local()); |
+ BranchOnValueOf(load); |
+} |
+ |
+ |
+// <Expression> ::= StoreLocal { local: LocalVariable |
+// value: <Expression> } |
+StoreLocalComp* EffectGraphVisitor::TranslateStoreLocal(StoreLocalNode* node) { |
+ ValueGraphVisitor for_value(owner(), temp_index()); |
+ node->value()->Visit(&for_value); |
+ Append(for_value); |
+ CHECK_ALIVE(return NULL); |
+ return new StoreLocalComp(node->local(), for_value.value()); |
+} |
+ |
+void EffectGraphVisitor::VisitStoreLocalNode(StoreLocalNode* node) { |
+ StoreLocalComp* store = TranslateStoreLocal(node); |
+ CHECK_ALIVE(return); |
+ DoComputation(store); |
+} |
+ |
+void ValueGraphVisitor::VisitStoreLocalNode(StoreLocalNode* node) { |
+ StoreLocalComp* store = TranslateStoreLocal(node); |
+ CHECK_ALIVE(return); |
+ ReturnValueOf(store); |
+} |
+ |
+void TestGraphVisitor::VisitStoreLocalNode(StoreLocalNode* node) { |
+ StoreLocalComp* store = TranslateStoreLocal(node); |
+ CHECK_ALIVE(return); |
+ BranchOnValueOf(store); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitLoadInstanceFieldNode( |
+ LoadInstanceFieldNode* node) { |
+ Bailout("EffectGraphVisitor::VisitLoadInstanceFieldNode"); |
+} |
+void ValueGraphVisitor::VisitLoadInstanceFieldNode( |
+ LoadInstanceFieldNode* node) { |
+ Bailout("ValueGraphVisitor::VisitLoadInstanceFieldNode"); |
+} |
+void TestGraphVisitor::VisitLoadInstanceFieldNode(LoadInstanceFieldNode* node) { |
+ Bailout("TestGraphVisitor::VisitLoadInstanceFieldNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitStoreInstanceFieldNode( |
+ StoreInstanceFieldNode* node) { |
+ Bailout("EffectGraphVisitor::VisitStoreInstanceFieldNode"); |
+} |
+void ValueGraphVisitor::VisitStoreInstanceFieldNode( |
+ StoreInstanceFieldNode* node) { |
+ Bailout("ValueGraphVisitor::VisitStoreInstanceFieldNode"); |
+} |
+void TestGraphVisitor::VisitStoreInstanceFieldNode( |
+ StoreInstanceFieldNode* node) { |
+ Bailout("TestGraphVisitor::VisitStoreInstanceFieldNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitLoadStaticFieldNode(LoadStaticFieldNode* node) { |
+ Bailout("EffectGraphVisitor::VisitLoadStaticFieldNode"); |
+} |
+void ValueGraphVisitor::VisitLoadStaticFieldNode(LoadStaticFieldNode* node) { |
+ Bailout("ValueGraphVisitor::VisitLoadStaticFieldNode"); |
+} |
+void TestGraphVisitor::VisitLoadStaticFieldNode(LoadStaticFieldNode* node) { |
+ Bailout("TestGraphVisitor::VisitLoadStaticFieldNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) { |
+ Bailout("EffectGraphVisitor::VisitStoreStaticFieldNode"); |
+} |
+void ValueGraphVisitor::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) { |
+ Bailout("ValueGraphVisitor::VisitStoreStaticFieldNode"); |
+} |
+void TestGraphVisitor::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) { |
+ Bailout("TestGraphVisitor::VisitStoreStaticFieldNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitLoadIndexedNode(LoadIndexedNode* node) { |
+ Bailout("EffectGraphVisitor::VisitLoadIndexedNode"); |
+} |
+void ValueGraphVisitor::VisitLoadIndexedNode(LoadIndexedNode* node) { |
+ Bailout("ValueGraphVisitor::VisitLoadIndexedNode"); |
+} |
+void TestGraphVisitor::VisitLoadIndexedNode(LoadIndexedNode* node) { |
+ Bailout("TestGraphVisitor::VisitLoadIndexedNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitStoreIndexedNode(StoreIndexedNode* node) { |
+ Bailout("EffectGraphVisitor::VisitStoreIndexedNode"); |
+} |
+void ValueGraphVisitor::VisitStoreIndexedNode(StoreIndexedNode* node) { |
+ Bailout("ValueGraphVisitor::VisitStoreIndexedNode"); |
+} |
+void TestGraphVisitor::VisitStoreIndexedNode(StoreIndexedNode* node) { |
+ Bailout("TestGraphVisitor::VisitStoreIndexedNode"); |
+} |
+ |
+ |
+// <Statement> ::= Sequence { scope: LocalScope |
+// nodes: <Statement>* |
+// label: SourceLabel } |
+void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) { |
+ if (node->scope() != NULL && node->scope()->num_context_variables() != 0) { |
+ Bailout("Sequence needs a context. Gotta have a context."); |
+ } |
+ for (intptr_t i = 0; i < node->length(); ++i) { |
+ EffectGraphVisitor for_effect(owner(), temp_index()); |
+ node->NodeAt(i)->Visit(&for_effect); |
+ Append(for_effect); |
+ CHECK_ALIVE(return); |
+ } |
+} |
+ |
+void ValueGraphVisitor::VisitSequenceNode(SequenceNode* node) { UNREACHABLE(); } |
+void TestGraphVisitor::VisitSequenceNode(SequenceNode* node) { UNREACHABLE(); } |
+ |
+ |
+void EffectGraphVisitor::VisitCatchClauseNode(CatchClauseNode* node) { |
+ Bailout("EffectGraphVisitor::VisitCatchClauseNode"); |
+} |
+void ValueGraphVisitor::VisitCatchClauseNode(CatchClauseNode* node) { |
+ Bailout("ValueGraphVisitor::VisitCatchClauseNode"); |
+} |
+void TestGraphVisitor::VisitCatchClauseNode(CatchClauseNode* node) { |
+ Bailout("TestGraphVisitor::VisitCatchClauseNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitTryCatchNode(TryCatchNode* node) { |
+ Bailout("EffectGraphVisitor::VisitTryCatchNode"); |
+} |
+void ValueGraphVisitor::VisitTryCatchNode(TryCatchNode* node) { |
+ Bailout("ValueGraphVisitor::VisitTryCatchNode"); |
+} |
+void TestGraphVisitor::VisitTryCatchNode(TryCatchNode* node) { |
+ Bailout("TestGraphVisitor::VisitTryCatchNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitThrowNode(ThrowNode* node) { |
+ Bailout("EffectGraphVisitor::VisitThrowNode"); |
+} |
+void ValueGraphVisitor::VisitThrowNode(ThrowNode* node) { |
+ Bailout("ValueGraphVisitor::VisitThrowNode"); |
+} |
+void TestGraphVisitor::VisitThrowNode(ThrowNode* node) { |
+ Bailout("TestGraphVisitor::VisitThrowNode"); |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitInlinedFinallyNode(InlinedFinallyNode* node) { |
+ Bailout("EffectGraphVisitor::VisitInlinedFinallyNode"); |
+} |
+void ValueGraphVisitor::VisitInlinedFinallyNode(InlinedFinallyNode* node) { |
+ Bailout("ValueGraphVisitor::VisitInlinedFinallyNode"); |
+} |
+void TestGraphVisitor::VisitInlinedFinallyNode(InlinedFinallyNode* node) { |
+ Bailout("TestGraphVisitor::VisitInlinedFinallyNode"); |
+} |
+ |
+ |
+void FlowGraphBuilder::TraceBailout() const { |
+ if (FLAG_trace_bailout && bailout_reason_ != NULL) { |
+ OS::Print("Failed: %s in %s\n", |
+ bailout_reason_, |
+ parsed_function().function().ToFullyQualifiedCString()); |
+ } |
+} |
+ |
+ |
+void FlowGraphBuilder::PrintGraph() const { |
+ if (!FLAG_print_flow_graph || bailout_reason_ != NULL) return; |
+ |
+ OS::Print("==== %s\n", |
+ parsed_function().function().ToFullyQualifiedCString()); |
+ |
+ for (intptr_t i = postorder_.length() - 1; i >= 0; --i) { |
+ OS::Print("%8d: ", postorder_.length() - i); |
+ postorder_[i]->Print(i, postorder_); |
+ OS::Print("\n"); |
+ } |
+ OS::Print("\n"); |
+} |
+ |
+ |
+void FlowGraphBuilder::BuildGraph() { |
+ EffectGraphVisitor for_effect(this, 0); |
+ parsed_function().node_sequence()->Visit(&for_effect); |
+ TraceBailout(); |
+ if (bailout_reason_ == NULL && for_effect.entry() != NULL) { |
srdjan
2012/02/22 00:41:34
Another "standard" in the VM code is to use parent
Kevin Millikin (Google)
2012/02/22 13:15:42
Done.
|
+ for_effect.entry()->Postorder(&postorder_); |
+ } |
+ PrintGraph(); |
+} |
+ |
+} // namespace dart |