diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h index cee6c4d08c0..808bee5208e 100644 --- a/runtime/vm/compiler/backend/il.h +++ b/runtime/vm/compiler/backend/il.h @@ -3516,27 +3516,28 @@ class StoreLocalInstr : public TemplateDefinition<1, NoThrow> { DISALLOW_COPY_AND_ASSIGN(StoreLocalInstr); }; -class NativeCallInstr : public TemplateDefinition<0, Throws> { +class NativeCallInstr : public TemplateDartCall<0> { public: - explicit NativeCallInstr(NativeBodyNode* node) - : native_name_(&node->native_c_function_name()), - function_(&node->function()), - native_c_function_(NULL), - is_bootstrap_native_(false), - link_lazily_(node->link_lazily()), - token_pos_(node->token_pos()) {} - NativeCallInstr(const String* name, const Function* function, bool link_lazily, - TokenPosition position) - : native_name_(name), + TokenPosition position, + ZoneGrowableArray* args) + : TemplateDartCall(Thread::kNoDeoptId, + 0, + Array::null_array(), + args, + position), + native_name_(name), function_(function), native_c_function_(NULL), is_bootstrap_native_(false), is_auto_scope_(true), link_lazily_(link_lazily), - token_pos_(position) {} + token_pos_(position) { + ASSERT(name->IsZoneHandle()); + ASSERT(function->IsZoneHandle()); + } DECLARE_INSTRUCTION(NativeCall) diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc index e3c164741ff..d87335e1894 100644 --- a/runtime/vm/compiler/backend/il_arm.cc +++ b/runtime/vm/compiler/backend/il_arm.cc @@ -805,15 +805,15 @@ void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { SetupNative(); const Register result = locs()->out(0).reg(); + // All arguments are already @SP due to preceding PushArgument()s. + ASSERT(ArgumentCount() == function().NumParameters()); + // Push the result place holder initialized to NULL. __ PushObject(Object::null_object()); + // Pass a pointer to the first argument in R2. - if (!function().HasOptionalParameters()) { - __ AddImmediate( - R2, FP, (kParamEndSlotFromFp + function().NumParameters()) * kWordSize); - } else { - __ AddImmediate(R2, FP, kFirstLocalSlotFromFp * kWordSize); - } + __ add(R2, SP, Operand(ArgumentCount() * kWordSize)); + // Compute the effective address. When running under the simulator, // this is a redirection address that forces the simulator to call // into the runtime system. @@ -854,6 +854,8 @@ void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { locs()); } __ Pop(result); + + __ Drop(ArgumentCount()); // Drop the arguments. } LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc index 2f85c2f74ae..b53ed9490eb 100644 --- a/runtime/vm/compiler/backend/il_arm64.cc +++ b/runtime/vm/compiler/backend/il_arm64.cc @@ -664,15 +664,15 @@ void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { SetupNative(); const Register result = locs()->out(0).reg(); + // All arguments are already @SP due to preceding PushArgument()s. + ASSERT(ArgumentCount() == function().NumParameters()); + // Push the result place holder initialized to NULL. __ PushObject(Object::null_object()); + // Pass a pointer to the first argument in R2. - if (!function().HasOptionalParameters()) { - __ AddImmediate( - R2, FP, (kParamEndSlotFromFp + function().NumParameters()) * kWordSize); - } else { - __ AddImmediate(R2, FP, kFirstLocalSlotFromFp * kWordSize); - } + __ AddImmediate(R2, SP, ArgumentCount() * kWordSize); + // Compute the effective address. When running under the simulator, // this is a redirection address that forces the simulator to call // into the runtime system. @@ -713,6 +713,8 @@ void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { locs()); } __ Pop(result); + + __ Drop(ArgumentCount()); // Drop the arguments. } LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc index 3e253874698..286dce48375 100644 --- a/runtime/vm/compiler/backend/il_ia32.cc +++ b/runtime/vm/compiler/backend/il_ia32.cc @@ -737,16 +737,15 @@ void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { Register result = locs()->out(0).reg(); const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); + // All arguments are already @ESP due to preceding PushArgument()s. + ASSERT(ArgumentCount() == function().NumParameters()); + // Push the result place holder initialized to NULL. __ PushObject(Object::null_object()); + // Pass a pointer to the first argument in EAX. - if (!function().HasOptionalParameters()) { - __ leal(EAX, - Address(EBP, (kParamEndSlotFromFp + function().NumParameters()) * - kWordSize)); - } else { - __ leal(EAX, Address(EBP, kFirstLocalSlotFromFp * kWordSize)); - } + __ leal(EAX, Address(ESP, ArgumentCount() * kWordSize)); + __ movl(EDX, Immediate(argc_tag)); const StubEntry* stub_entry; @@ -766,6 +765,8 @@ void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { locs()); __ popl(result); + + __ Drop(ArgumentCount()); // Drop the arguments. } static bool CanBeImmediateIndex(Value* value, intptr_t cid) { diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc index 4ca18288ca2..f7f6bd71597 100644 --- a/runtime/vm/compiler/backend/il_x64.cc +++ b/runtime/vm/compiler/backend/il_x64.cc @@ -708,16 +708,15 @@ void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { Register result = locs()->out(0).reg(); const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); + // All arguments are already @RSP due to preceding PushArgument()s. + ASSERT(ArgumentCount() == function().NumParameters()); + // Push the result place holder initialized to NULL. __ PushObject(Object::null_object()); + // Pass a pointer to the first argument in RAX. - if (!function().HasOptionalParameters()) { - __ leaq(RAX, - Address(RBP, (kParamEndSlotFromFp + function().NumParameters()) * - kWordSize)); - } else { - __ leaq(RAX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); - } + __ leaq(RAX, Address(RSP, ArgumentCount() * kWordSize)); + __ LoadImmediate(R10, Immediate(argc_tag)); const StubEntry* stub_entry; if (link_lazily()) { @@ -740,6 +739,8 @@ void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { locs()); } __ popq(result); + + __ Drop(ArgumentCount()); // Drop the arguments. } static bool CanBeImmediateIndex(Value* index, intptr_t cid) { diff --git a/runtime/vm/compiler/frontend/flow_graph_builder.cc b/runtime/vm/compiler/frontend/flow_graph_builder.cc index fb4748982ba..5fcd49007db 100644 --- a/runtime/vm/compiler/frontend/flow_graph_builder.cc +++ b/runtime/vm/compiler/frontend/flow_graph_builder.cc @@ -3320,7 +3320,18 @@ void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) { } } InlineBailout("EffectGraphVisitor::VisitNativeBodyNode"); - NativeCallInstr* native_call = new (Z) NativeCallInstr(node); + + const ParsedFunction& pf = owner_->parsed_function(); + const String& name = String::ZoneHandle(Z, function.native_name()); + ZoneGrowableArray& args = + *new (Z) ZoneGrowableArray(function.NumParameters()); + for (intptr_t i = 0; i < function.NumParameters(); ++i) { + LocalVariable* parameter = pf.node_sequence()->scope()->VariableAt(i); + Value* value = Bind(new (Z) LoadLocalInstr(*parameter, node->token_pos())); + args.Add(PushArgument(value)); + } + NativeCallInstr* native_call = new (Z) NativeCallInstr( + &name, &function, FLAG_link_natives_lazily, node->token_pos(), &args); ReturnDefinition(native_call); } diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc index ecee2a81319..231b8b96123 100644 --- a/runtime/vm/compiler/frontend/kernel_to_il.cc +++ b/runtime/vm/compiler/frontend/kernel_to_il.cc @@ -1389,8 +1389,10 @@ Fragment BaseFlowGraphBuilder::NullConstant() { Fragment FlowGraphBuilder::NativeCall(const String* name, const Function* function) { InlineBailout("kernel::FlowGraphBuilder::NativeCall"); - NativeCallInstr* call = new (Z) NativeCallInstr( - name, function, FLAG_link_natives_lazily, TokenPosition::kNoSource); + ArgumentArray arguments = GetArguments(function->NumParameters()); + NativeCallInstr* call = + new (Z) NativeCallInstr(name, function, FLAG_link_natives_lazily, + TokenPosition::kNoSource, arguments); Push(call); return Fragment(call); } @@ -2005,6 +2007,11 @@ Fragment FlowGraphBuilder::NativeFunctionBody(intptr_t first_positional_offset, break; default: { String& name = String::ZoneHandle(Z, function.native_name()); + for (intptr_t i = 0; i < function.NumParameters(); ++i) { + body += LoadLocal( + parsed_function_->node_sequence()->scope()->VariableAt(i)); + body += PushArgument(); + } body += NativeCall(&name, &function); break; } diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc index 2acecce6739..5d21b6d45d1 100644 --- a/runtime/vm/simulator_dbc.cc +++ b/runtime/vm/simulator_dbc.cc @@ -1954,61 +1954,59 @@ RawObject* Simulator::Call(const Code& code, { BYTECODE(NativeBootstrapCall, 0); - RawFunction* function = FrameFunction(FP); - RawObject** incoming_args = - (function->ptr()->num_optional_parameters_ == 0) - ? FrameArguments(FP, function->ptr()->num_fixed_parameters_) - : FP; + intptr_t argc_tag = reinterpret_cast(SP[-0]); + const intptr_t num_arguments = NativeArguments::ArgcBits::decode(argc_tag); + RawObject** incoming_args = SP - 1 - num_arguments; + RawObject** return_slot = SP - 1; SimulatorBootstrapNativeCall native_target = reinterpret_cast(SP[-1]); - intptr_t argc_tag = reinterpret_cast(SP[-0]); SP[-0] = 0; // Note: argc_tag is not smi-tagged. SP[-1] = null_value; Exit(thread, FP, SP + 1, pc); - NativeArguments args(thread, argc_tag, incoming_args, SP - 1); + NativeArguments args(thread, argc_tag, incoming_args, return_slot); INVOKE_BOOTSTRAP_NATIVE(native_target, args); - SP -= 1; + + *(SP - 1 - num_arguments) = *return_slot; + SP -= 1 + num_arguments; DISPATCH(); } { BYTECODE(NativeNoScopeCall, 0); - RawFunction* function = FrameFunction(FP); - RawObject** incoming_args = - (function->ptr()->num_optional_parameters_ == 0) - ? FrameArguments(FP, function->ptr()->num_fixed_parameters_) - : FP; + intptr_t argc_tag = reinterpret_cast(SP[-0]); + const intptr_t num_arguments = NativeArguments::ArgcBits::decode(argc_tag); + RawObject** incoming_args = SP - 1 - num_arguments; + RawObject** return_slot = SP - 1; Dart_NativeFunction native_target = reinterpret_cast(SP[-1]); - intptr_t argc_tag = reinterpret_cast(SP[-0]); SP[-0] = 0; // argc_tag is not smi tagged! SP[-1] = null_value; Exit(thread, FP, SP + 1, pc); - NativeArguments args(thread, argc_tag, incoming_args, SP - 1); + NativeArguments args(thread, argc_tag, incoming_args, return_slot); INVOKE_NATIVE_NO_SCOPE(native_target, args); - SP -= 1; + *(SP - 1 - num_arguments) = *return_slot; + SP -= 1 + num_arguments; DISPATCH(); } { BYTECODE(NativeAutoScopeCall, 0); - RawFunction* function = FrameFunction(FP); - RawObject** incoming_args = - (function->ptr()->num_optional_parameters_ == 0) - ? FrameArguments(FP, function->ptr()->num_fixed_parameters_) - : FP; + intptr_t argc_tag = reinterpret_cast(SP[-0]); + const intptr_t num_arguments = NativeArguments::ArgcBits::decode(argc_tag); + RawObject** incoming_args = SP - 1 - num_arguments; + RawObject** return_slot = SP - 1; Dart_NativeFunction native_target = reinterpret_cast(SP[-1]); - intptr_t argc_tag = reinterpret_cast(SP[-0]); SP[-0] = 0; // argc_tag is not smi tagged! SP[-1] = null_value; Exit(thread, FP, SP + 1, pc); - NativeArguments args(thread, argc_tag, incoming_args, SP - 1); + NativeArguments args(thread, argc_tag, incoming_args, return_slot); INVOKE_NATIVE_AUTO_SCOPE(native_target, args); - SP -= 1; + *(SP - 1 - num_arguments) = *return_slot; + SP -= 1 + num_arguments; DISPATCH(); }