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).