Chromium Code Reviews| Index: runtime/vm/flow_graph_compiler_x64.cc |
| diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc |
| index 1a2ce75b591e3bd89505fa9e548c53706300e13a..05f21eb426556f9aa1f87108046ed1fb4a85e682 100644 |
| --- a/runtime/vm/flow_graph_compiler_x64.cc |
| +++ b/runtime/vm/flow_graph_compiler_x64.cc |
| @@ -52,12 +52,12 @@ void FlowGraphCompiler::LoadValue(Value* value) { |
| void FlowGraphCompiler::VisitTemp(TempVal* val) { |
| - Bailout("TempVal"); |
| + LoadValue(val); |
| } |
| void FlowGraphCompiler::VisitConstant(ConstantVal* val) { |
| - Bailout("ConstantVal"); |
| + LoadValue(val); |
| } |
| @@ -66,8 +66,68 @@ void FlowGraphCompiler::VisitAssertAssignable(AssertAssignableComp* comp) { |
| } |
| +// True iff. the arguments to a call will be properly pushed and can |
| +// be popped after the call. |
| +template <typename T> static bool VerifyCallComputation(T* comp) { |
| + // Argument values should be consecutive temps. |
| + // |
| + // TODO(kmillikin): implement stack height tracking so we can also assert |
| + // they are on top of the stack. |
| + intptr_t previous = -1; |
| + for (int i = 0; i < comp->ArgumentCount(); ++i) { |
| + TempVal* temp = comp->ArgumentAt(i)->AsTemp(); |
| + if (temp == NULL) return false; |
| + if (i != 0) { |
| + if (temp->index() != previous + 1) return false; |
| + } |
| + previous = temp->index(); |
| + } |
| + return true; |
|
srdjan
2012/03/01 23:19:31
Can you check that last temp is on TOS, i.e., with
Kevin Millikin (Google)
2012/03/02 09:01:28
We can't easily check that it's actually on top of
|
| +} |
| + |
| + |
| +void FlowGraphCompiler::EmitInstanceCall(intptr_t node_id, |
| + intptr_t token_index, |
| + const String& function_name, |
| + intptr_t argument_count, |
| + const Array& argument_names, |
| + intptr_t checked_argument_count) { |
| + ICData& ic_data = |
| + ICData::ZoneHandle(ICData::New(parsed_function_.function(), |
| + function_name, |
| + node_id, |
| + checked_argument_count)); |
| + const Array& arguments_descriptor = |
| + CodeGenerator::ArgumentsDescriptor(argument_count, argument_names); |
| + __ LoadObject(RBX, ic_data); |
| + __ LoadObject(R10, arguments_descriptor); |
| + |
| + uword label_address = 0; |
| + switch (checked_argument_count) { |
| + case 1: |
| + label_address = StubCode::OneArgCheckInlineCacheEntryPoint(); |
| + break; |
| + case 2: |
| + label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint(); |
| + break; |
| + default: |
| + UNIMPLEMENTED(); |
| + } |
| + ExternalLabel target_label("InlineCache", label_address); |
| + __ call(&target_label); |
| + AddCurrentDescriptor(PcDescriptors::kIcCall, node_id, token_index); |
| + __ addq(RSP, Immediate(argument_count * kWordSize)); |
| +} |
| + |
| + |
| void FlowGraphCompiler::VisitInstanceCall(InstanceCallComp* comp) { |
| - Bailout("InstanceCallComp"); |
| + ASSERT(VerifyCallComputation(comp)); |
| + EmitInstanceCall(comp->node_id(), |
| + comp->token_index(), |
| + comp->function_name(), |
| + comp->ArgumentCount(), |
| + comp->argument_names(), |
| + comp->checked_argument_count()); |
| } |
| @@ -78,7 +138,19 @@ void FlowGraphCompiler::VisitStrictCompare(StrictCompareComp* comp) { |
| void FlowGraphCompiler::VisitStaticCall(StaticCallComp* comp) { |
| - Bailout("StaticCallComp"); |
| + ASSERT(VerifyCallComputation(comp)); |
| + |
| + int argument_count = comp->ArgumentCount(); |
| + const Array& arguments_descriptor = |
| + CodeGenerator::ArgumentsDescriptor(argument_count, |
| + comp->argument_names()); |
| + __ LoadObject(RBX, comp->function()); |
| + __ LoadObject(R10, arguments_descriptor); |
| + |
| + GenerateCall(comp->token_index(), |
| + &StubCode::CallStaticFunctionLabel(), |
| + PcDescriptors::kFuncCall); |
| + __ addq(RSP, Immediate(argument_count * kWordSize)); |
| } |
| @@ -99,6 +171,36 @@ void FlowGraphCompiler::VisitStoreLocal(StoreLocalComp* comp) { |
| } |
| +void FlowGraphCompiler::VisitStoreIndexed(StoreIndexedComp* comp) { |
| + // Call operator []= but preserve the third argument value under the |
| + // arguments as the result of the computation. |
| + const String& function_name = |
| + String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); |
| + // Placeholder is under value, index, and receiver. |
| + const int kPlaceholderOffset = 3 * kWordSize; |
| + __ movq(RAX, Address(RSP, 0)); // Value. |
| + __ movq(Address(RSP, kPlaceholderOffset), RAX); |
| + EmitInstanceCall(comp->node_id(), comp->token_index(), function_name, 3, |
| + Array::ZoneHandle(), 1); |
| + __ popq(RAX); |
| +} |
| + |
| + |
| +void FlowGraphCompiler::VisitInstanceSetter(InstanceSetterComp* comp) { |
| + // Preserve the second argument under the arguments as the result of the |
| + // computation, then call the getter. |
|
srdjan
2012/03/01 23:19:31
Can you verify that place holder, value, array and
Kevin Millikin (Google)
2012/03/02 09:01:28
Yes.
|
| + const String& function_name = |
| + String::ZoneHandle(Field::SetterSymbol(comp->field_name())); |
| + // Placeholder is under value and receiver. |
| + const int kPlaceholderOffset = 2 * kWordSize; |
| + __ movq(RAX, Address(RSP, 0)); // Value. |
| + __ movq(Address(RSP, kPlaceholderOffset), RAX); |
| + EmitInstanceCall(comp->node_id(), comp->token_index(), function_name, 2, |
| + Array::ZoneHandle(), 1); |
| + __ popq(RAX); |
| +} |
| + |
| + |
| void FlowGraphCompiler::VisitJoinEntry(JoinEntryInstr* instr) { |
| Bailout("JoinEntryInstr"); |
| } |
| @@ -258,6 +360,14 @@ void FlowGraphCompiler::CompileGraph() { |
| // Infrastructure copied from class CodeGenerator. |
| +void FlowGraphCompiler::GenerateCall(intptr_t token_index, |
| + const ExternalLabel* label, |
| + PcDescriptors::Kind kind) { |
| + __ call(label); |
| + AddCurrentDescriptor(kind, AstNode::kNoId, token_index); |
| +} |
| + |
| + |
| void FlowGraphCompiler::GenerateCallRuntime(intptr_t node_id, |
| intptr_t token_index, |
| const RuntimeEntry& entry) { |