mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 01:59:38 +00:00
[VM] Make our NativeCallInstr work similar to all other call instructions
This CL makes NativeCallInstr instructions use PushArgument()s when calling instead of directly using a pointer to the caller-provided arguments (for functions without optional parameters) or relying on copy arguments prologue (for functions with optional parameters). Issue https://github.com/dart-lang/sdk/issues/31495 Change-Id: I36d4bf1b7dd10f48c7e40b0cafe37f8698aacb71 Reviewed-on: https://dart-review.googlesource.com/24961 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
This commit is contained in:
parent
83cabf36e3
commit
3c0422e6a6
|
@ -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<PushArgumentInstr*>* 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)
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<PushArgumentInstr*>& args =
|
||||
*new (Z) ZoneGrowableArray<PushArgumentInstr*>(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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<intptr_t>(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<SimulatorBootstrapNativeCall>(SP[-1]);
|
||||
intptr_t argc_tag = reinterpret_cast<intptr_t>(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<intptr_t>(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<Dart_NativeFunction>(SP[-1]);
|
||||
intptr_t argc_tag = reinterpret_cast<intptr_t>(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<intptr_t>(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<Dart_NativeFunction>(SP[-1]);
|
||||
intptr_t argc_tag = reinterpret_cast<intptr_t>(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();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue