From 8c4e2147225eea35b61de2d53c6a69ed40dfdee6 Mon Sep 17 00:00:00 2001 From: "kmillikin@google.com" Date: Wed, 5 Dec 2012 15:35:18 +0000 Subject: [PATCH] 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 --- runtime/vm/code_generator.cc | 67 +++++++++++++++++----------- runtime/vm/code_generator.h | 11 ++++- runtime/vm/code_patcher.h | 15 +++---- runtime/vm/code_patcher_ia32.cc | 52 +++++---------------- runtime/vm/code_patcher_ia32_test.cc | 4 +- runtime/vm/code_patcher_x64.cc | 53 +++++----------------- runtime/vm/code_patcher_x64_test.cc | 4 +- runtime/vm/debugger.cc | 29 ++++++------ runtime/vm/deopt_instructions.cc | 4 +- runtime/vm/object.cc | 2 +- runtime/vm/stub_code_ia32.cc | 23 ++++++---- runtime/vm/stub_code_x64.cc | 21 ++++++--- 12 files changed, 130 insertions(+), 155 deletions(-) diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc index 201e45e5216..575e04c6cf5 100644 --- a/runtime/vm/code_generator.cc +++ b/runtime/vm/code_generator.cc @@ -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& args) { + const GrowableArray& 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 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 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 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); } diff --git a/runtime/vm/code_generator.h b/runtime/vm/code_generator.h index 1bd96325dae..dd85de19723 100644 --- a/runtime/vm/code_generator.h +++ b/runtime/vm/code_generator.h @@ -10,6 +10,11 @@ namespace dart { +class ArgumentsDescriptor; +template 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& classes); diff --git a/runtime/vm/code_patcher.h b/runtime/vm/code_patcher.h index 8377692fbfc..ce9945f4b74 100644 --- a/runtime/vm/code_patcher.h +++ b/runtime/vm/code_patcher.h @@ -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(); diff --git a/runtime/vm/code_patcher_ia32.cc b/runtime/vm/code_patcher_ia32.cc index 0456d9b3f2b..ad3281f7a0d 100644 --- a/runtime/vm/code_patcher_ia32.cc +++ b/runtime/vm/code_patcher_ia32.cc @@ -53,26 +53,10 @@ class DartCallPattern : public ValueObject { return *reinterpret_cast(start_ + 1); } - void set_immediate_one(uint32_t value) { - uint32_t* target_addr = reinterpret_cast(start_ + 1); - *target_addr = value; - CPU::FlushICache(start_, kInstructionSize); - } - RawObject* immediate_two() const { return *reinterpret_cast(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(); } diff --git a/runtime/vm/code_patcher_ia32_test.cc b/runtime/vm/code_patcher_ia32_test.cc index 72b44dd925a..9845ab0148b 100644 --- a/runtime/vm/code_patcher_ia32_test.cc +++ b/runtime/vm/code_patcher_ia32_test.cc @@ -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()); diff --git a/runtime/vm/code_patcher_x64.cc b/runtime/vm/code_patcher_x64.cc index f4c1f9c249a..a5e635f41a8 100644 --- a/runtime/vm/code_patcher_x64.cc +++ b/runtime/vm/code_patcher_x64.cc @@ -55,26 +55,11 @@ class DartCallPattern : public ValueObject { return *reinterpret_cast(start_ + 0 + 2); } - void set_immediate_one(uint64_t value) { - uint64_t* target_addr = reinterpret_cast(start_ + 0 + 2); - *target_addr = value; - CPU::FlushICache(start_ + 0, 2 + 8); - } - RawObject* immediate_two() const { return *reinterpret_cast(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(); } diff --git a/runtime/vm/code_patcher_x64_test.cc b/runtime/vm/code_patcher_x64_test.cc index 5476ec48666..eef51c7f88d 100644 --- a/runtime/vm/code_patcher_x64_test.cc +++ b/runtime/vm/code_patcher_x64_test.cc @@ -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()); diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc index 5d5cf7138c5..c49f7e6b5a4 100644 --- a/runtime/vm/debugger.cc +++ b/runtime/vm/debugger.cc @@ -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)) { diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc index 70a77c5c27d..92eda81fc23 100644 --- a/runtime/vm/deopt_instructions.cc +++ b/runtime/vm/deopt_instructions.cc @@ -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()); } diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 9c9c29f36a8..f63f20c9102 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -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); } } diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc index 289f1c04fbb..c56dc4b6f47 100644 --- a/runtime/vm/stub_code_ia32.cc +++ b/runtime/vm/stub_code_ia32.cc @@ -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). diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc index 8b183ac4dab..e754305d336 100644 --- a/runtime/vm/stub_code_x64.cc +++ b/runtime/vm/stub_code_x64.cc @@ -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).