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..93469b9587f98f287c18590ee1cce95892fc60d7 |
--- /dev/null |
+++ b/runtime/vm/flow_graph_builder.cc |
@@ -0,0 +1,893 @@ |
+// 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 and false bodies to the test if they are reachable, |
+ // and if so record their exits (if any). |
+ if (test_fragment.can_be_true()) { |
+ Instruction* true_exit = NULL; |
+ Instruction* false_exit = NULL; |
+ 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(); |
+ |
+ 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(); |
+ |
+ 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); |
+ } |
+ owner()->Bailout(reason); |
+} |
+ |
+ |
+// 'bailout' is a statement (without a semicolon), typically a return. |
+#define CHECK_ALIVE(bailout) \ |
+ do { \ |
+ if (owner()->HasBailedOut() || !is_open()) { \ |
+ 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( |
+ const 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( |
+ const 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( |
+ const ComparisonNode& node) { |
+ if (Token::IsInstanceofOperator(node.kind()) || |
+ Token::IsEqualityOperator(node.kind())) { |
+ 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); |
+ // 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( |
+ const 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( |
+ const 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 && HasBailedOut()) { |
+ OS::Print("Failed: %s in %s\n", |
+ bailout_reason_, |
+ parsed_function().function().ToFullyQualifiedCString()); |
+ } |
+} |
+ |
+ |
+void FlowGraphBuilder::PrintGraph() const { |
+ if (!FLAG_print_flow_graph || HasBailedOut()) 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 (!HasBailedOut() && (for_effect.entry() != NULL)) { |
+ for_effect.entry()->Postorder(&postorder_); |
+ } |
+ PrintGraph(); |
+} |
+ |
+} // namespace dart |