| Index: runtime/vm/flow_graph_builder.cc
|
| diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
|
| index 4fe69647020c2baa94af0f83b25581f242d3d1b2..5c7ef5def99bbc76a36a3faf2e6732e281e838f9 100644
|
| --- a/runtime/vm/flow_graph_builder.cc
|
| +++ b/runtime/vm/flow_graph_builder.cc
|
| @@ -129,6 +129,15 @@ void TestGraphVisitor::BranchOnValue(Value* value) {
|
| }
|
|
|
|
|
| +void ArgumentGraphVisitor::ReturnValue(Value* value) {
|
| + value_ = value;
|
| + if (value->IsConstant()) {
|
| + AddInstruction(new BindInstr(temp_index(), value));
|
| + value_ = new TempVal(AllocateTempIndex());
|
| + }
|
| +}
|
| +
|
| +
|
| void EffectGraphVisitor::Bailout(const char* reason) {
|
| owner()->Bailout(reason);
|
| }
|
| @@ -222,18 +231,18 @@ void EffectGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) {
|
| if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) {
|
| Bailout("EffectGraphVisitor::VisitBinaryOpNode AND/OR");
|
| }
|
| - ValueGraphVisitor for_left_value(owner(), temp_index());
|
| + ArgumentGraphVisitor for_left_value(owner(), temp_index());
|
| node->left()->Visit(&for_left_value);
|
| Append(for_left_value);
|
| - CHECK_ALIVE(return);
|
| - ValueGraphVisitor for_right_value(owner(), for_left_value.temp_index());
|
| + ArgumentGraphVisitor for_right_value(owner(), for_left_value.temp_index());
|
| node->right()->Visit(&for_right_value);
|
| Append(for_right_value);
|
| - CHECK_ALIVE(return);
|
| ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2);
|
| arguments->Add(for_left_value.value());
|
| arguments->Add(for_right_value.value());
|
| - InstanceCallComp* call = new InstanceCallComp(node->Name(), arguments);
|
| + const String& name = String::ZoneHandle(String::NewSymbol(node->Name()));
|
| + InstanceCallComp* call =
|
| + new InstanceCallComp(node, name, arguments, Array::ZoneHandle(), 2);
|
| ReturnComputation(call);
|
| }
|
|
|
| @@ -252,25 +261,33 @@ void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) {
|
| } else if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) {
|
| Bailout("'==' or '!=' comparison not yet implemented");
|
| }
|
| - ValueGraphVisitor for_left_value(owner(), temp_index());
|
| - node->left()->Visit(&for_left_value);
|
| - Append(for_left_value);
|
| - CHECK_ALIVE(return);
|
| - ValueGraphVisitor for_right_value(owner(), for_left_value.temp_index());
|
| - node->right()->Visit(&for_right_value);
|
| - Append(for_right_value);
|
| - CHECK_ALIVE(return);
|
| +
|
| if ((node->kind() == Token::kEQ_STRICT) ||
|
| (node->kind() == Token::kNE_STRICT)) {
|
| + ValueGraphVisitor for_left_value(owner(), temp_index());
|
| + node->left()->Visit(&for_left_value);
|
| + Append(for_left_value);
|
| + ValueGraphVisitor for_right_value(owner(), for_left_value.temp_index());
|
| + node->right()->Visit(&for_right_value);
|
| + Append(for_right_value);
|
| StrictCompareComp* comp = new StrictCompareComp(
|
| node->kind(), for_left_value.value(), for_right_value.value());
|
| ReturnComputation(comp);
|
| return;
|
| }
|
| +
|
| + ArgumentGraphVisitor for_left_value(owner(), temp_index());
|
| + node->left()->Visit(&for_left_value);
|
| + Append(for_left_value);
|
| + ArgumentGraphVisitor for_right_value(owner(), for_left_value.temp_index());
|
| + node->right()->Visit(&for_right_value);
|
| + Append(for_right_value);
|
| ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2);
|
| arguments->Add(for_left_value.value());
|
| arguments->Add(for_right_value.value());
|
| - InstanceCallComp* call = new InstanceCallComp(node->Name(), arguments);
|
| + const String& name = String::ZoneHandle(String::NewSymbol(node->Name()));
|
| + InstanceCallComp* call =
|
| + new InstanceCallComp(node, name, arguments, Array::ZoneHandle(), 2);
|
| ReturnComputation(call);
|
| }
|
|
|
| @@ -280,12 +297,17 @@ void EffectGraphVisitor::VisitUnaryOpNode(UnaryOpNode* node) {
|
| if (node->kind() == Token::kNOT) {
|
| Bailout("EffectGraphVisitor::VisitUnaryOpNode NOT");
|
| }
|
| - ValueGraphVisitor for_value(owner(), temp_index());
|
| + ArgumentGraphVisitor for_value(owner(), temp_index());
|
| node->operand()->Visit(&for_value);
|
| Append(for_value);
|
| - ZoneGrowableArray<Value*>* argument = new ZoneGrowableArray<Value*>(1);
|
| - argument->Add(for_value.value());
|
| - InstanceCallComp* call = new InstanceCallComp(node->Name(), argument);
|
| + ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(1);
|
| + arguments->Add(for_value.value());
|
| + const String& name =
|
| + String::ZoneHandle(String::NewSymbol((node->kind() == Token::kSUB)
|
| + ? Token::Str(Token::kNEGATE)
|
| + : node->Name()));
|
| + InstanceCallComp* call =
|
| + new InstanceCallComp(node, name, arguments, Array::ZoneHandle(), 1);
|
| ReturnComputation(call);
|
| }
|
|
|
| @@ -390,57 +412,44 @@ void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) {
|
| }
|
|
|
|
|
| +void EffectGraphVisitor::TranslateArgumentList(
|
| + const ArgumentListNode& node,
|
| + intptr_t next_temp_index,
|
| + ZoneGrowableArray<Value*>* values) {
|
| + for (intptr_t i = 0; i < node.length(); ++i) {
|
| + ArgumentGraphVisitor for_argument(owner(), next_temp_index);
|
| + node.NodeAt(i)->Visit(&for_argument);
|
| + Append(for_argument);
|
| + next_temp_index = for_argument.temp_index();
|
| + values->Add(for_argument.value());
|
| + }
|
| +}
|
| +
|
| void EffectGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) {
|
| ArgumentListNode* arguments = node->arguments();
|
| int length = arguments->length();
|
| ZoneGrowableArray<Value*>* values = new ZoneGrowableArray<Value*>(length + 1);
|
|
|
| - ValueGraphVisitor for_receiver(owner(), temp_index());
|
| + ArgumentGraphVisitor for_receiver(owner(), temp_index());
|
| node->receiver()->Visit(&for_receiver);
|
| Append(for_receiver);
|
| - CHECK_ALIVE(return);
|
| - Value* receiver_value = for_receiver.value();
|
| - temp_index_ = for_receiver.temp_index();
|
| - if (receiver_value->IsConstant()) {
|
| - AddInstruction(new BindInstr(temp_index(), receiver_value));
|
| - receiver_value = new TempVal(AllocateTempIndex());
|
| - }
|
| - values->Add(receiver_value);
|
| + values->Add(for_receiver.value());
|
|
|
| - TranslateArgumentList(*arguments, values);
|
| - CHECK_ALIVE(return);
|
| + TranslateArgumentList(*arguments, for_receiver.temp_index(), values);
|
| InstanceCallComp* call =
|
| - new InstanceCallComp(node->function_name().ToCString(), values);
|
| + new InstanceCallComp(node, node->function_name(), values,
|
| + arguments->names(), 1);
|
| ReturnComputation(call);
|
| }
|
|
|
|
|
| -void EffectGraphVisitor::TranslateArgumentList(
|
| - const ArgumentListNode& node, ZoneGrowableArray<Value*>* values) {
|
| - int index = temp_index();
|
| - for (intptr_t i = 0; i < node.length(); ++i) {
|
| - ValueGraphVisitor for_value(owner(), index);
|
| - node.NodeAt(i)->Visit(&for_value);
|
| - Append(for_value);
|
| - CHECK_ALIVE(return);
|
| - Value* argument_value = for_value.value();
|
| - index = for_value.temp_index();
|
| - if (argument_value->IsConstant()) {
|
| - AddInstruction(new BindInstr(index, argument_value));
|
| - argument_value = new TempVal(index++);
|
| - }
|
| - values->Add(argument_value);
|
| - }
|
| -}
|
| -
|
| // <Expression> ::= StaticCall { function: Function
|
| // arguments: <ArgumentList> }
|
| void EffectGraphVisitor::VisitStaticCallNode(StaticCallNode* node) {
|
| int length = node->arguments()->length();
|
| ZoneGrowableArray<Value*>* values = new ZoneGrowableArray<Value*>(length);
|
| - TranslateArgumentList(*node->arguments(), values);
|
| - CHECK_ALIVE(return);
|
| - StaticCallComp* call = new StaticCallComp(node->function(), values);
|
| + TranslateArgumentList(*node->arguments(), temp_index(), values);
|
| + StaticCallComp* call = new StaticCallComp(node, values);
|
| ReturnComputation(call);
|
| }
|
|
|
| @@ -461,12 +470,35 @@ void EffectGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) {
|
|
|
|
|
| void EffectGraphVisitor::VisitInstanceGetterNode(InstanceGetterNode* node) {
|
| - Bailout("EffectGraphVisitor::VisitInstanceGetterNode");
|
| + ArgumentGraphVisitor for_receiver(owner(), temp_index());
|
| + node->receiver()->Visit(&for_receiver);
|
| + Append(for_receiver);
|
| + ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(1);
|
| + arguments->Add(for_receiver.value());
|
| + const String& name =
|
| + String::ZoneHandle(Field::GetterSymbol(node->field_name()));
|
| + InstanceCallComp* call =
|
| + new InstanceCallComp(node, name, arguments, Array::ZoneHandle(), 1);
|
| + ReturnComputation(call);
|
| }
|
|
|
|
|
| void EffectGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) {
|
| - Bailout("EffectGraphVisitor::VisitInstanceSetterNode");
|
| + // We preallocate a temporary to overlap with the value of the assignment.
|
| + const Smi& zero = Smi::ZoneHandle(Smi::New(0));
|
| + AddInstruction(new BindInstr(temp_index(), new ConstantVal(zero)));
|
| + TempVal* placeholder = new TempVal(temp_index());
|
| + ArgumentGraphVisitor for_receiver(owner(), temp_index() + 1);
|
| + node->receiver()->Visit(&for_receiver);
|
| + Append(for_receiver);
|
| + ArgumentGraphVisitor for_value(owner(), for_receiver.temp_index());
|
| + node->value()->Visit(&for_value);
|
| + Append(for_value);
|
| + InstanceSetterComp* setter = new InstanceSetterComp(node,
|
| + placeholder,
|
| + for_receiver.value(),
|
| + for_value.value());
|
| + ReturnComputation(setter);
|
| }
|
|
|
|
|
| @@ -512,8 +544,16 @@ void EffectGraphVisitor::VisitStoreLocalNode(StoreLocalNode* node) {
|
| ValueGraphVisitor for_value(owner(), temp_index());
|
| node->value()->Visit(&for_value);
|
| Append(for_value);
|
| - CHECK_ALIVE(return);
|
| - StoreLocalComp* store = new StoreLocalComp(node->local(), for_value.value());
|
| +
|
| + Value* value = for_value.value();
|
| + if (FLAG_enable_type_checks) {
|
| + AssertAssignableComp* assert =
|
| + new AssertAssignableComp(value, node->local().type());
|
| + AddInstruction(new BindInstr(temp_index(), assert));
|
| + value = new TempVal(temp_index());
|
| + }
|
| +
|
| + StoreLocalComp* store = new StoreLocalComp(node->local(), value);
|
| ReturnComputation(store);
|
| }
|
|
|
| @@ -541,12 +581,49 @@ void EffectGraphVisitor::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) {
|
|
|
|
|
| void EffectGraphVisitor::VisitLoadIndexedNode(LoadIndexedNode* node) {
|
| - Bailout("EffectGraphVisitor::VisitLoadIndexedNode");
|
| + ArgumentGraphVisitor for_array(owner(), temp_index());
|
| + node->array()->Visit(&for_array);
|
| + Append(for_array);
|
| + ArgumentGraphVisitor for_index(owner(), for_array.temp_index());
|
| + node->index_expr()->Visit(&for_index);
|
| + Append(for_index);
|
| + ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2);
|
| + arguments->Add(for_array.value());
|
| + arguments->Add(for_index.value());
|
| + const String& name =
|
| + String::ZoneHandle(String::NewSymbol(Token::Str(Token::kINDEX)));
|
| + InstanceCallComp* call =
|
| + new InstanceCallComp(node, name, arguments, Array::ZoneHandle(), 1);
|
| + ReturnComputation(call);
|
| }
|
|
|
|
|
| void EffectGraphVisitor::VisitStoreIndexedNode(StoreIndexedNode* node) {
|
| - Bailout("EffectGraphVisitor::VisitStoreIndexedNode");
|
| + // This is not a straight instance call to e0.[]=(e1, e2), it is a
|
| + // call to
|
| + //
|
| + // (a, i, v) { a.[]=(i, v); return v; }(e0, e1, e2)
|
| + //
|
| + // Without constructing that function, we simulate it at the IL
|
| + // level by preallocating a slot for the return value.
|
| + const Smi& zero = Smi::ZoneHandle(Smi::New(0));
|
| + AddInstruction(new BindInstr(temp_index(), new ConstantVal(zero)));
|
| + TempVal* placeholder = new TempVal(temp_index());
|
| + ArgumentGraphVisitor for_array(owner(), temp_index() + 1);
|
| + node->array()->Visit(&for_array);
|
| + Append(for_array);
|
| + ArgumentGraphVisitor for_index(owner(), for_array.temp_index());
|
| + node->index_expr()->Visit(&for_index);
|
| + Append(for_index);
|
| + ArgumentGraphVisitor for_value(owner(), for_index.temp_index());
|
| + node->value()->Visit(&for_value);
|
| + Append(for_value);
|
| + StoreIndexedComp* store = new StoreIndexedComp(node,
|
| + placeholder,
|
| + for_array.value(),
|
| + for_index.value(),
|
| + for_value.value());
|
| + ReturnComputation(store);
|
| }
|
|
|
|
|
| @@ -660,7 +737,7 @@ void FlowGraphPrinter::VisitAssertAssignable(AssertAssignableComp* comp) {
|
|
|
|
|
| void FlowGraphPrinter::VisitInstanceCall(InstanceCallComp* comp) {
|
| - OS::Print("InstanceCall(%s", comp->name());
|
| + OS::Print("InstanceCall(%s", comp->function_name().ToCString());
|
| for (int i = 0; i < comp->ArgumentCount(); ++i) {
|
| OS::Print(", ");
|
| comp->ArgumentAt(i)->Accept(this);
|
| @@ -702,6 +779,30 @@ void FlowGraphPrinter::VisitStoreLocal(StoreLocalComp* comp) {
|
| }
|
|
|
|
|
| +void FlowGraphPrinter::VisitStoreIndexed(StoreIndexedComp* comp) {
|
| + OS::Print("StoreIndexed(");
|
| + comp->placeholder()->Accept(this);
|
| + OS::Print(", ");
|
| + comp->array()->Accept(this);
|
| + OS::Print(", ");
|
| + comp->index()->Accept(this);
|
| + OS::Print(", ");
|
| + comp->value()->Accept(this);
|
| + OS::Print(")");
|
| +}
|
| +
|
| +
|
| +void FlowGraphPrinter::VisitInstanceSetter(InstanceSetterComp* comp) {
|
| + OS::Print("InstanceSetter(");
|
| + comp->placeholder()->Accept(this);
|
| + OS::Print(", ");
|
| + comp->receiver()->Accept(this);
|
| + OS::Print(", ");
|
| + comp->value()->Accept(this);
|
| + OS::Print(")");
|
| +}
|
| +
|
| +
|
| void FlowGraphPrinter::VisitJoinEntry(JoinEntryInstr* instr) {
|
| OS::Print("%2d: [join]", instr->block_number());
|
| }
|
|
|