Pass IC data and arguments descriptor to IC miss runtime functions.
Before, we obtained them by pattern matching backwards on the machine instructions at the call site. This previous approach becomes unwieldy when we need to use to use multiple instance call patterns. R=vegorov@google.com BUG= Review URL: https://codereview.chromium.org//11438017 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@15737 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
@@ -790,20 +790,13 @@ DEFINE_RUNTIME_ENTRY(PatchStaticCall, 0) {
|
||||
// Resolves and compiles the target function of an instance call, updates
|
||||
// function cache of the receiver's class and returns the compiled code or null.
|
||||
// Only the number of named arguments is checked, but not the actual names.
|
||||
RawCode* ResolveCompileInstanceCallTarget(Isolate* isolate,
|
||||
const Instance& receiver) {
|
||||
int num_arguments = -1;
|
||||
int num_named_arguments = -1;
|
||||
uword target = 0;
|
||||
String& function_name = String::Handle();
|
||||
DartFrameIterator iterator;
|
||||
StackFrame* caller_frame = iterator.NextFrame();
|
||||
ASSERT(caller_frame != NULL);
|
||||
CodePatcher::GetInstanceCallAt(caller_frame->pc(),
|
||||
&function_name,
|
||||
&num_arguments,
|
||||
&num_named_arguments,
|
||||
&target);
|
||||
RawCode* ResolveCompileInstanceCallTarget(
|
||||
const Instance& receiver,
|
||||
const ICData& ic_data,
|
||||
const ArgumentsDescriptor& arguments_descriptor) {
|
||||
intptr_t num_arguments = arguments_descriptor.Count();
|
||||
int num_named_arguments = arguments_descriptor.NamedCount();
|
||||
String& function_name = String::Handle(ic_data.target_name());
|
||||
ASSERT(function_name.IsSymbol());
|
||||
|
||||
Function& function = Function::Handle();
|
||||
@@ -836,16 +829,22 @@ static void CheckResultError(const Object& result) {
|
||||
|
||||
// Resolves an instance function and compiles it if necessary.
|
||||
// Arg0: receiver object.
|
||||
// Arg1: IC data object.
|
||||
// Arg2: Arguments descriptor array.
|
||||
// Returns: RawCode object or NULL (method not found or not compileable).
|
||||
// This is called by the megamorphic stub when instance call does not need to be
|
||||
// patched.
|
||||
// Used by megamorphic lookup/no-such-method-handling.
|
||||
DEFINE_RUNTIME_ENTRY(ResolveCompileInstanceFunction, 1) {
|
||||
DEFINE_RUNTIME_ENTRY(ResolveCompileInstanceFunction, 3) {
|
||||
ASSERT(arguments.ArgCount() ==
|
||||
kResolveCompileInstanceFunctionRuntimeEntry.argument_count());
|
||||
const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
|
||||
const Code& code = Code::Handle(
|
||||
ResolveCompileInstanceCallTarget(isolate, receiver));
|
||||
const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
|
||||
ArgumentsDescriptor arg_descriptor(arguments.ArgAt(2));
|
||||
const Code& code =
|
||||
Code::Handle(ResolveCompileInstanceCallTarget(receiver,
|
||||
ic_data,
|
||||
arg_descriptor));
|
||||
arguments.SetReturn(code);
|
||||
}
|
||||
|
||||
@@ -896,10 +895,14 @@ DEFINE_RUNTIME_ENTRY(BreakpointDynamicHandler, 0) {
|
||||
|
||||
|
||||
static RawFunction* InlineCacheMissHandler(
|
||||
Isolate* isolate, const GrowableArray<const Instance*>& args) {
|
||||
const GrowableArray<const Instance*>& args,
|
||||
const ICData& ic_data,
|
||||
const ArgumentsDescriptor& arg_descriptor) {
|
||||
const Instance& receiver = *args[0];
|
||||
const Code& target_code =
|
||||
Code::Handle(ResolveCompileInstanceCallTarget(isolate, receiver));
|
||||
Code::Handle(ResolveCompileInstanceCallTarget(receiver,
|
||||
ic_data,
|
||||
arg_descriptor));
|
||||
if (target_code.IsNull()) {
|
||||
// Let the megamorphic stub handle special cases: NoSuchMethod,
|
||||
// closure calls.
|
||||
@@ -915,8 +918,6 @@ static RawFunction* InlineCacheMissHandler(
|
||||
DartFrameIterator iterator;
|
||||
StackFrame* caller_frame = iterator.NextFrame();
|
||||
ASSERT(caller_frame != NULL);
|
||||
ICData& ic_data = ICData::Handle(
|
||||
CodePatcher::GetInstanceCallIcDataAt(caller_frame->pc()));
|
||||
if (args.length() == 1) {
|
||||
ic_data.AddReceiverCheck(Class::Handle(args[0]->clazz()).id(),
|
||||
target_function);
|
||||
@@ -952,16 +953,20 @@ static RawFunction* InlineCacheMissHandler(
|
||||
// Handles inline cache misses by updating the IC data array of the call
|
||||
// site.
|
||||
// Arg0: Receiver object.
|
||||
// Arg1: IC data object.
|
||||
// Arg2: Arguments descriptor array.
|
||||
// Returns: target function with compiled code or null.
|
||||
// Modifies the instance call to hold the updated IC data array.
|
||||
DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerOneArg, 1) {
|
||||
DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerOneArg, 3) {
|
||||
ASSERT(arguments.ArgCount() ==
|
||||
kInlineCacheMissHandlerOneArgRuntimeEntry.argument_count());
|
||||
const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
|
||||
const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
|
||||
ArgumentsDescriptor arg_descriptor(arguments.ArgAt(2));
|
||||
GrowableArray<const Instance*> args(1);
|
||||
args.Add(&receiver);
|
||||
const Function& result =
|
||||
Function::Handle(InlineCacheMissHandler(isolate, args));
|
||||
Function::Handle(InlineCacheMissHandler(args, ic_data, arg_descriptor));
|
||||
arguments.SetReturn(result);
|
||||
}
|
||||
|
||||
@@ -970,18 +975,22 @@ DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerOneArg, 1) {
|
||||
// site.
|
||||
// Arg0: Receiver object.
|
||||
// Arg1: Argument after receiver.
|
||||
// Arg2: IC data object.
|
||||
// Arg3: Arguments descriptor array.
|
||||
// Returns: target function with compiled code or null.
|
||||
// Modifies the instance call to hold the updated IC data array.
|
||||
DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerTwoArgs, 2) {
|
||||
DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerTwoArgs, 4) {
|
||||
ASSERT(arguments.ArgCount() ==
|
||||
kInlineCacheMissHandlerTwoArgsRuntimeEntry.argument_count());
|
||||
const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
|
||||
const Instance& other = Instance::CheckedHandle(arguments.ArgAt(1));
|
||||
const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(2));
|
||||
ArgumentsDescriptor arg_descriptor(arguments.ArgAt(3));
|
||||
GrowableArray<const Instance*> args(2);
|
||||
args.Add(&receiver);
|
||||
args.Add(&other);
|
||||
const Function& result =
|
||||
Function::Handle(InlineCacheMissHandler(isolate, args));
|
||||
Function::Handle(InlineCacheMissHandler(args, ic_data, arg_descriptor));
|
||||
arguments.SetReturn(result);
|
||||
}
|
||||
|
||||
@@ -991,20 +1000,24 @@ DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerTwoArgs, 2) {
|
||||
// Arg0: Receiver object.
|
||||
// Arg1: Argument after receiver.
|
||||
// Arg2: Second argument after receiver.
|
||||
// Arg3: IC data object.
|
||||
// Arg4: Arguments descriptor array.
|
||||
// Returns: target function with compiled code or null.
|
||||
// Modifies the instance call to hold the updated IC data array.
|
||||
DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerThreeArgs, 3) {
|
||||
DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerThreeArgs, 5) {
|
||||
ASSERT(arguments.ArgCount() ==
|
||||
kInlineCacheMissHandlerThreeArgsRuntimeEntry.argument_count());
|
||||
const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
|
||||
const Instance& arg1 = Instance::CheckedHandle(arguments.ArgAt(1));
|
||||
const Instance& arg2 = Instance::CheckedHandle(arguments.ArgAt(2));
|
||||
const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(3));
|
||||
ArgumentsDescriptor arg_descriptor(arguments.ArgAt(4));
|
||||
GrowableArray<const Instance*> args(3);
|
||||
args.Add(&receiver);
|
||||
args.Add(&arg1);
|
||||
args.Add(&arg2);
|
||||
const Function& result =
|
||||
Function::Handle(InlineCacheMissHandler(isolate, args));
|
||||
Function::Handle(InlineCacheMissHandler(args, ic_data, arg_descriptor));
|
||||
arguments.SetReturn(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,11 @@
|
||||
|
||||
namespace dart {
|
||||
|
||||
class ArgumentsDescriptor;
|
||||
template <typename T> class GrowableArray;
|
||||
class ICData;
|
||||
class Instance;
|
||||
|
||||
// Declaration of runtime entries called from stub or generated code.
|
||||
DECLARE_RUNTIME_ENTRY(AllocateArray);
|
||||
DECLARE_RUNTIME_ENTRY(AllocateClosure);
|
||||
@@ -80,8 +85,10 @@ DEOPT_REASONS(DEFINE_ENUM_LIST)
|
||||
const char* DeoptReasonToText(intptr_t deopt_id);
|
||||
|
||||
|
||||
RawCode* ResolveCompileInstanceCallTarget(Isolate* isolate,
|
||||
const Instance& receiver);
|
||||
RawCode* ResolveCompileInstanceCallTarget(
|
||||
const Instance& receiver,
|
||||
const ICData& ic_data,
|
||||
const ArgumentsDescriptor& arguments_descriptor);
|
||||
|
||||
void DeoptimizeAll();
|
||||
void DeoptimizeIfOwner(const GrowableArray<intptr_t>& classes);
|
||||
|
||||
@@ -15,6 +15,7 @@ class Array;
|
||||
class Code;
|
||||
class ExternalLabel;
|
||||
class Function;
|
||||
class ICData;
|
||||
class RawArray;
|
||||
class RawICData;
|
||||
class String;
|
||||
@@ -45,14 +46,12 @@ class CodePatcher : public AllStatic {
|
||||
|
||||
static uword GetStaticCallTargetAt(uword return_address);
|
||||
|
||||
// Get instance call information.
|
||||
static void GetInstanceCallAt(uword return_address,
|
||||
String* function_name,
|
||||
int* num_arguments,
|
||||
int* num_named_arguments,
|
||||
uword* target);
|
||||
|
||||
static RawICData* GetInstanceCallIcDataAt(uword return_address);
|
||||
// Get instance call information. Returns the call target and sets each
|
||||
// of the output parameters ic_data and arguments_descriptor if they are
|
||||
// non-NULL.
|
||||
static uword GetInstanceCallAt(uword return_address,
|
||||
ICData* ic_data,
|
||||
Array* arguments_descriptor);
|
||||
|
||||
static intptr_t InstanceCallSizeInBytes();
|
||||
|
||||
|
||||
@@ -53,26 +53,10 @@ class DartCallPattern : public ValueObject {
|
||||
return *reinterpret_cast<RawObject**>(start_ + 1);
|
||||
}
|
||||
|
||||
void set_immediate_one(uint32_t value) {
|
||||
uint32_t* target_addr = reinterpret_cast<uint32_t*>(start_ + 1);
|
||||
*target_addr = value;
|
||||
CPU::FlushICache(start_, kInstructionSize);
|
||||
}
|
||||
|
||||
RawObject* immediate_two() const {
|
||||
return *reinterpret_cast<RawObject**>(start_ + kInstructionSize + 1);
|
||||
}
|
||||
|
||||
intptr_t argument_count() const {
|
||||
ArgumentsDescriptor args_desc(immediate_two());
|
||||
return args_desc.Count();
|
||||
}
|
||||
|
||||
intptr_t named_argument_count() const {
|
||||
ArgumentsDescriptor args_desc(immediate_two());
|
||||
return args_desc.NamedCount();
|
||||
}
|
||||
|
||||
static const int kNumInstructions = 3;
|
||||
static const int kInstructionSize = 5; // All instructions have same length.
|
||||
|
||||
@@ -100,11 +84,8 @@ class InstanceCall : public DartCallPattern {
|
||||
explicit InstanceCall(uword return_address)
|
||||
: DartCallPattern(return_address) {}
|
||||
|
||||
RawICData* ic_data() const {
|
||||
ICData& ic_data = ICData::Handle();
|
||||
ic_data ^= immediate_one();
|
||||
return ic_data.raw();
|
||||
}
|
||||
RawObject* ic_data() const { return immediate_one(); }
|
||||
RawObject* arguments_descriptor() const { return immediate_two(); }
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCall);
|
||||
@@ -247,28 +228,17 @@ bool CodePatcher::IsDartCall(uword return_address) {
|
||||
}
|
||||
|
||||
|
||||
void CodePatcher::GetInstanceCallAt(uword return_address,
|
||||
String* function_name,
|
||||
int* num_arguments,
|
||||
int* num_named_arguments,
|
||||
uword* target) {
|
||||
ASSERT(num_arguments != NULL);
|
||||
ASSERT(num_named_arguments != NULL);
|
||||
ASSERT(target != NULL);
|
||||
uword CodePatcher::GetInstanceCallAt(uword return_address,
|
||||
ICData* ic_data,
|
||||
Array* arguments_descriptor) {
|
||||
InstanceCall call(return_address);
|
||||
*num_arguments = call.argument_count();
|
||||
*num_named_arguments = call.named_argument_count();
|
||||
*target = call.target();
|
||||
const ICData& ic_data = ICData::Handle(call.ic_data());
|
||||
if (function_name != NULL) {
|
||||
*function_name = ic_data.target_name();
|
||||
if (ic_data != NULL) {
|
||||
*ic_data ^= call.ic_data();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RawICData* CodePatcher::GetInstanceCallIcDataAt(uword return_address) {
|
||||
InstanceCall call(return_address);
|
||||
return call.ic_data();
|
||||
if (arguments_descriptor != NULL) {
|
||||
*arguments_descriptor ^= call.arguments_descriptor();
|
||||
}
|
||||
return call.target();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -72,8 +72,8 @@ ASSEMBLER_TEST_GENERATE(IcDataAccess, assembler) {
|
||||
|
||||
ASSEMBLER_TEST_RUN(IcDataAccess, entry) {
|
||||
uword return_address = entry + CodePatcher::InstanceCallSizeInBytes();
|
||||
const ICData& ic_data = ICData::Handle(
|
||||
CodePatcher::GetInstanceCallIcDataAt(return_address));
|
||||
ICData& ic_data = ICData::Handle();
|
||||
CodePatcher::GetInstanceCallAt(return_address, &ic_data, NULL);
|
||||
EXPECT_STREQ("targetFunction",
|
||||
String::Handle(ic_data.target_name()).ToCString());
|
||||
EXPECT_EQ(1, ic_data.num_args_tested());
|
||||
|
||||
@@ -55,26 +55,11 @@ class DartCallPattern : public ValueObject {
|
||||
return *reinterpret_cast<RawObject**>(start_ + 0 + 2);
|
||||
}
|
||||
|
||||
void set_immediate_one(uint64_t value) {
|
||||
uint64_t* target_addr = reinterpret_cast<uint64_t*>(start_ + 0 + 2);
|
||||
*target_addr = value;
|
||||
CPU::FlushICache(start_ + 0, 2 + 8);
|
||||
}
|
||||
|
||||
RawObject* immediate_two() const {
|
||||
return *reinterpret_cast<RawObject**>(start_ + 10 + 2);
|
||||
}
|
||||
|
||||
intptr_t argument_count() const {
|
||||
ArgumentsDescriptor args_desc(immediate_two());
|
||||
return args_desc.Count();
|
||||
}
|
||||
|
||||
intptr_t named_argument_count() const {
|
||||
ArgumentsDescriptor args_desc(immediate_two());
|
||||
return args_desc.NamedCount();
|
||||
}
|
||||
|
||||
private:
|
||||
uword start_;
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(DartCallPattern);
|
||||
};
|
||||
@@ -92,11 +77,8 @@ class InstanceCall : public DartCallPattern {
|
||||
explicit InstanceCall(uword return_address)
|
||||
: DartCallPattern(return_address) {}
|
||||
|
||||
RawICData* ic_data() const {
|
||||
ICData& ic_data = ICData::Handle();
|
||||
ic_data ^= immediate_one();
|
||||
return ic_data.raw();
|
||||
}
|
||||
RawObject* ic_data() const { return immediate_one(); }
|
||||
RawObject* arguments_descriptor() const { return immediate_two(); }
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCall);
|
||||
@@ -230,28 +212,17 @@ bool CodePatcher::IsDartCall(uword return_address) {
|
||||
}
|
||||
|
||||
|
||||
void CodePatcher::GetInstanceCallAt(uword return_address,
|
||||
String* function_name,
|
||||
int* num_arguments,
|
||||
int* num_named_arguments,
|
||||
uword* target) {
|
||||
ASSERT(num_arguments != NULL);
|
||||
ASSERT(num_named_arguments != NULL);
|
||||
ASSERT(target != NULL);
|
||||
uword CodePatcher::GetInstanceCallAt(uword return_address,
|
||||
ICData* ic_data,
|
||||
Array* arguments_descriptor) {
|
||||
InstanceCall call(return_address);
|
||||
*num_arguments = call.argument_count();
|
||||
*num_named_arguments = call.named_argument_count();
|
||||
*target = call.target();
|
||||
const ICData& ic_data = ICData::Handle(call.ic_data());
|
||||
if (function_name != NULL) {
|
||||
*function_name = ic_data.target_name();
|
||||
if (ic_data != NULL) {
|
||||
*ic_data ^= call.ic_data();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RawICData* CodePatcher::GetInstanceCallIcDataAt(uword return_address) {
|
||||
InstanceCall call(return_address);
|
||||
return call.ic_data();
|
||||
if (arguments_descriptor != NULL) {
|
||||
*arguments_descriptor ^= call.arguments_descriptor();
|
||||
}
|
||||
return call.target();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -72,8 +72,8 @@ ASSEMBLER_TEST_GENERATE(IcDataAccess, assembler) {
|
||||
|
||||
ASSEMBLER_TEST_RUN(IcDataAccess, entry) {
|
||||
uword return_address = entry + CodePatcher::InstanceCallSizeInBytes();
|
||||
const ICData& ic_data = ICData::Handle(
|
||||
CodePatcher::GetInstanceCallIcDataAt(return_address));
|
||||
ICData& ic_data = ICData::Handle();
|
||||
CodePatcher::GetInstanceCallAt(return_address, &ic_data, NULL);
|
||||
EXPECT_STREQ("targetFunction",
|
||||
String::Handle(ic_data.target_name()).ToCString());
|
||||
EXPECT_EQ(1, ic_data.num_args_tested());
|
||||
|
||||
+15
-14
@@ -566,12 +566,10 @@ void CodeBreakpoint::PatchCode() {
|
||||
ASSERT(!is_enabled_);
|
||||
switch (breakpoint_kind_) {
|
||||
case PcDescriptors::kIcCall: {
|
||||
int num_args, num_named_args;
|
||||
CodePatcher::GetInstanceCallAt(pc_,
|
||||
NULL, &num_args, &num_named_args,
|
||||
&saved_bytes_.target_address_);
|
||||
CodePatcher::PatchInstanceCallAt(
|
||||
pc_, StubCode::BreakpointDynamicEntryPoint());
|
||||
saved_bytes_.target_address_ =
|
||||
CodePatcher::GetInstanceCallAt(pc_, NULL, NULL);
|
||||
CodePatcher::PatchInstanceCallAt(pc_,
|
||||
StubCode::BreakpointDynamicEntryPoint());
|
||||
break;
|
||||
}
|
||||
case PcDescriptors::kFuncCall: {
|
||||
@@ -1385,15 +1383,18 @@ void Debugger::SignalBpReached() {
|
||||
// a StepOver, that is we instrument the current function.
|
||||
if (bpt->breakpoint_kind_ == PcDescriptors::kIcCall) {
|
||||
func_to_instrument = bpt->function();
|
||||
int num_args, num_named_args;
|
||||
uword target;
|
||||
CodePatcher::GetInstanceCallAt(bpt->pc_, NULL,
|
||||
&num_args, &num_named_args, &target);
|
||||
ICData& ic_data = ICData::Handle();
|
||||
Array& descriptor = Array::Handle();
|
||||
CodePatcher::GetInstanceCallAt(bpt->pc_, &ic_data, &descriptor);
|
||||
ArgumentsDescriptor arg_descriptor(descriptor.raw());
|
||||
ActivationFrame* top_frame = stack_trace->ActivationFrameAt(0);
|
||||
Instance& receiver = Instance::Handle(
|
||||
top_frame->GetInstanceCallReceiver(num_args));
|
||||
Code& code = Code::Handle(
|
||||
ResolveCompileInstanceCallTarget(isolate_, receiver));
|
||||
intptr_t num_args = arg_descriptor.Count();
|
||||
Instance& receiver =
|
||||
Instance::Handle(top_frame->GetInstanceCallReceiver(num_args));
|
||||
Code& code =
|
||||
Code::Handle(ResolveCompileInstanceCallTarget(receiver,
|
||||
ic_data,
|
||||
arg_descriptor));
|
||||
if (!code.IsNull()) {
|
||||
Function& callee = Function::Handle(code.function());
|
||||
if (IsDebuggable(callee)) {
|
||||
|
||||
@@ -265,8 +265,8 @@ class DeoptRetBeforeAddressInstr : public DeoptInstr {
|
||||
if (pc != 0) {
|
||||
// If the deoptimization happened at an IC call, update the IC data
|
||||
// to avoid repeated deoptimization at the same site next time around.
|
||||
const ICData& ic_data = ICData::Handle(
|
||||
CodePatcher::GetInstanceCallIcDataAt(pc));
|
||||
ICData& ic_data = ICData::Handle();
|
||||
CodePatcher::GetInstanceCallAt(pc, &ic_data, NULL);
|
||||
if (!ic_data.IsNull()) {
|
||||
ic_data.set_deopt_reason(deopt_context->deopt_reason());
|
||||
}
|
||||
|
||||
@@ -7199,7 +7199,7 @@ intptr_t Code::ExtractIcDataArraysAtCalls(
|
||||
max_id = deopt_id;
|
||||
}
|
||||
node_ids->Add(deopt_id);
|
||||
ic_data_obj = CodePatcher::GetInstanceCallIcDataAt(descriptors.PC(i));
|
||||
CodePatcher::GetInstanceCallAt(descriptors.PC(i), &ic_data_obj, NULL);
|
||||
ic_data_objs.Add(ic_data_obj);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,11 +286,15 @@ void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) {
|
||||
// First resolve the function to get the function object.
|
||||
|
||||
__ pushl(raw_null); // Setup space on stack for return value.
|
||||
__ pushl(EAX); // Push receiver.
|
||||
__ pushl(EAX); // Pass receiver.
|
||||
__ pushl(ECX); // Pass IC data object.
|
||||
__ pushl(EDX); // Pass arguments descriptor array.
|
||||
__ CallRuntime(kResolveCompileInstanceFunctionRuntimeEntry);
|
||||
__ popl(EAX); // Remove receiver pushed earlier.
|
||||
__ popl(EAX); // Remove arguments pushed earlier.
|
||||
__ popl(EAX);
|
||||
__ popl(EAX);
|
||||
__ popl(ECX); // Pop returned code object into ECX.
|
||||
// Pop preserved values
|
||||
// Pop preserved values.
|
||||
__ popl(EDX); // Restore ic-data.
|
||||
__ popl(EAX); // Restore receiver.
|
||||
__ popl(EDI); // Restore arguments descriptor array.
|
||||
@@ -1640,13 +1644,15 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler,
|
||||
// calling into the runtime.
|
||||
AssemblerMacros::EnterStubFrame(assembler);
|
||||
__ pushl(EDX); // Preserve arguments descriptor array.
|
||||
__ pushl(ECX); // Preserve IC data array
|
||||
__ pushl(ECX); // Preserve IC data object.
|
||||
__ pushl(raw_null); // Setup space on stack for result (target code object).
|
||||
// Push call arguments.
|
||||
for (intptr_t i = 0; i < num_args; i++) {
|
||||
__ movl(EDX, Address(EAX, -kWordSize * i));
|
||||
__ pushl(EDX);
|
||||
__ movl(EBX, Address(EAX, -kWordSize * i));
|
||||
__ pushl(EBX);
|
||||
}
|
||||
__ pushl(ECX); // Pass IC data object.
|
||||
__ pushl(EDX); // Pass arguments descriptor array.
|
||||
if (num_args == 1) {
|
||||
__ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry);
|
||||
} else if (num_args == 2) {
|
||||
@@ -1656,8 +1662,9 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler,
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
// Remove call arguments pushed earlier.
|
||||
for (intptr_t i = 0; i < num_args; i++) {
|
||||
// Remove the call arguments pushed earlier, including the IC data object
|
||||
// and the arguments descriptor array.
|
||||
for (intptr_t i = 0; i < num_args + 2; i++) {
|
||||
__ popl(EAX);
|
||||
}
|
||||
__ popl(EAX); // Pop returned code object into EAX (null if not found).
|
||||
|
||||
@@ -281,9 +281,13 @@ void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) {
|
||||
// First resolve the function to get the function object.
|
||||
|
||||
__ pushq(raw_null); // Setup space on stack for return value.
|
||||
__ pushq(RAX); // Push receiver.
|
||||
__ pushq(RAX); // Pass receiver.
|
||||
__ pushq(RBX); // Pass IC data object.
|
||||
__ pushq(R10); // Pass arguments descriptor array.
|
||||
__ CallRuntime(kResolveCompileInstanceFunctionRuntimeEntry);
|
||||
__ popq(RAX); // Remove receiver pushed earlier.
|
||||
__ popq(RAX); // Remove arguments pushed earlier.
|
||||
__ popq(RAX);
|
||||
__ popq(RAX);
|
||||
__ popq(RBX); // Pop returned code object into RBX.
|
||||
// Pop preserved values
|
||||
__ popq(R10); // Restore ic-data.
|
||||
@@ -1618,13 +1622,15 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler,
|
||||
__ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi.
|
||||
AssemblerMacros::EnterStubFrame(assembler);
|
||||
__ pushq(R10); // Preserve arguments descriptor array.
|
||||
__ pushq(RBX); // Preserve IC data array
|
||||
__ pushq(RBX); // Preserve IC data object.
|
||||
__ pushq(raw_null); // Setup space on stack for result (target code object).
|
||||
// Push call arguments.
|
||||
for (intptr_t i = 0; i < num_args; i++) {
|
||||
__ movq(R10, Address(RAX, -kWordSize * i));
|
||||
__ pushq(R10);
|
||||
__ movq(RCX, Address(RAX, -kWordSize * i));
|
||||
__ pushq(RCX);
|
||||
}
|
||||
__ pushq(RBX); // Pass IC data object.
|
||||
__ pushq(R10); // Pass arguments descriptor array.
|
||||
if (num_args == 1) {
|
||||
__ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry);
|
||||
} else if (num_args == 2) {
|
||||
@@ -1634,8 +1640,9 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler,
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
// Remove call arguments pushed earlier.
|
||||
for (intptr_t i = 0; i < num_args; i++) {
|
||||
// Remove the call arguments pushed earlier, including the IC data object
|
||||
// and the arguments descriptor array.
|
||||
for (intptr_t i = 0; i < num_args + 2; i++) {
|
||||
__ popq(RAX);
|
||||
}
|
||||
__ popq(RAX); // Pop returned code object into RAX (null if not found).
|
||||
|
||||
Reference in New Issue
Block a user