From 4831b79421b5a3d98001495a67785db492303b93 Mon Sep 17 00:00:00 2001 From: "whesse@chromium.org" Date: Fri, 12 Feb 2010 08:53:13 +0000 Subject: [PATCH] Port change in CallIC interface to x64 platform. Name of called function is now passed in rcx. Review URL: http://codereview.chromium.org/596036 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3838 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/x64/builtins-x64.cc | 64 +++++++++++++----------- src/x64/codegen-x64.cc | 22 ++++----- src/x64/full-codegen-x64.cc | 20 +++----- src/x64/ic-x64.cc | 52 +++++++++++-------- src/x64/stub-cache-x64.cc | 115 +++++++++++++++++++++++-------------------- src/x64/virtual-frame-x64.cc | 11 +++-- src/x64/virtual-frame-x64.h | 6 +-- 7 files changed, 157 insertions(+), 133 deletions(-) diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc index 0b95bba..0b7c90e 100644 --- a/src/x64/builtins-x64.cc +++ b/src/x64/builtins-x64.cc @@ -276,44 +276,48 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { __ bind(&done); } - // 4. Shift stuff one slot down the stack. - { Label loop; - __ lea(rcx, Operand(rax, +1)); // +1 ~ copy receiver too - __ bind(&loop); - __ movq(rbx, Operand(rsp, rcx, times_pointer_size, 0)); - __ movq(Operand(rsp, rcx, times_pointer_size, 1 * kPointerSize), rbx); - __ decq(rcx); - __ j(not_zero, &loop); - } - - // 5. Remove TOS (copy of last arguments), but keep return address. - __ pop(rbx); - __ pop(rcx); - __ push(rbx); - __ decq(rax); - - // 6. Check that function really was a function and get the code to - // call from the function and check that the number of expected - // arguments matches what we're providing. - { Label invoke, trampoline; + // 4. Check that the function really is a function. + { Label real_function; __ testq(rdi, rdi); - __ j(not_zero, &invoke); + __ j(not_zero, &real_function); __ xor_(rbx, rbx); + // CALL_NON_FUNCTION will expect to find the non-function callee on the + // expression stack of the caller. Transfer it from receiver to the + // caller's expression stack (and make the first argument the receiver + // for CALL_NON_FUNCTION) by decrementing the argument count. + __ decq(rax); __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); - __ bind(&trampoline); __ Jump(Handle(builtin(ArgumentsAdaptorTrampoline)), RelocInfo::CODE_TARGET); - __ bind(&invoke); - __ movq(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); - __ movsxlq(rbx, - FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset)); - __ movq(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset)); - __ lea(rdx, FieldOperand(rdx, Code::kHeaderSize)); - __ cmpq(rax, rbx); - __ j(not_equal, &trampoline); + __ bind(&real_function); } + // 5. Shift arguments and return address one slot down on the stack + // (overwriting the receiver). + { Label loop; + __ movq(rcx, rax); + __ bind(&loop); + __ movq(rbx, Operand(rsp, rcx, times_pointer_size, 0)); + __ movq(Operand(rsp, rcx, times_pointer_size, 1 * kPointerSize), rbx); + __ decq(rcx); + __ j(not_sign, &loop); + __ pop(rbx); // Discard copy of return address. + __ decq(rax); // One fewer argument (first argument is new receiver). + } + + // 6. Get the code to call from the function and check that the number of + // expected arguments matches what we're providing. + __ movq(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); + __ movsxlq(rbx, + FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset)); + __ movq(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset)); + __ lea(rdx, FieldOperand(rdx, Code::kHeaderSize)); + __ cmpq(rax, rbx); + __ j(not_equal, + Handle(builtin(ArgumentsAdaptorTrampoline)), + RelocInfo::CODE_TARGET); + // 7. Jump (tail-call) to the code in register edx without checking arguments. ParameterCount expected(0); __ InvokeCode(rdx, expected, expected, JUMP_FUNCTION); diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index a50381f..3002452 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -2757,9 +2757,6 @@ void CodeGenerator::VisitCall(Call* node) { // JavaScript example: 'foo(1, 2, 3)' // foo is global // ---------------------------------- - // Push the name of the function and the receiver onto the stack. - frame_->Push(var->name()); - // Pass the global object as the receiver and let the IC stub // patch the stack to use the global proxy as 'this' in the // invoked function. @@ -2771,6 +2768,9 @@ void CodeGenerator::VisitCall(Call* node) { Load(args->at(i)); } + // Push the name of the function on the frame. + frame_->Push(var->name()); + // Call the IC initialization code. CodeForSourcePosition(node->position()); Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT, @@ -2778,7 +2778,7 @@ void CodeGenerator::VisitCall(Call* node) { loop_nesting()); frame_->RestoreContextRegister(); // Replace the function on the stack with the result. - frame_->SetElementAt(0, &result); + frame_->Push(&result); } else if (var != NULL && var->slot() != NULL && var->slot()->type() == Slot::LOOKUP) { @@ -2831,8 +2831,7 @@ void CodeGenerator::VisitCall(Call* node) { node->position()); } else { - // Push the name of the function and the receiver onto the stack. - frame_->Push(name); + // Push the receiver onto the frame. Load(property->obj()); // Load the arguments. @@ -2841,14 +2840,16 @@ void CodeGenerator::VisitCall(Call* node) { Load(args->at(i)); } + // Push the name of the function onto the frame. + frame_->Push(name); + // Call the IC initialization code. CodeForSourcePosition(node->position()); Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET, arg_count, loop_nesting()); frame_->RestoreContextRegister(); - // Replace the function on the stack with the result. - frame_->SetElementAt(0, &result); + frame_->Push(&result); } } else { @@ -2939,8 +2940,6 @@ void CodeGenerator::VisitCallRuntime(CallRuntime* node) { Runtime::Function* function = node->function(); if (function == NULL) { - // Prepare stack for calling JS runtime function. - frame_->Push(node->name()); // Push the builtins object found in the current global object. Result temp = allocator()->Allocate(); ASSERT(temp.is_valid()); @@ -2958,11 +2957,12 @@ void CodeGenerator::VisitCallRuntime(CallRuntime* node) { if (function == NULL) { // Call the JS runtime function. + frame_->Push(node->name()); Result answer = frame_->CallCallIC(RelocInfo::CODE_TARGET, arg_count, loop_nesting_); frame_->RestoreContextRegister(); - frame_->SetElementAt(0, &answer); + frame_->Push(&answer); } else { // Call the C runtime function. Result answer = frame_->CallRuntime(function, arg_count); diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index 2e95c68..b14cb85 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -1200,7 +1200,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) { void FullCodeGenerator::EmitCallWithIC(Call* expr, - Handle ignored, + Handle name, RelocInfo::Mode mode) { // Code common for calls using the IC. ZoneList* args = expr->arguments(); @@ -1208,6 +1208,7 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, for (int i = 0; i < arg_count; i++) { VisitForValue(args->at(i), kStack); } + __ Move(rcx, name); // Record source position for debugger. SetSourcePosition(expr->position()); // Call the IC initialization code. @@ -1217,8 +1218,7 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, __ Call(ic, mode); // Restore context register. __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); - // Discard the function left on TOS. - DropAndApply(1, context_, rax); + Apply(context_, rax); } @@ -1250,7 +1250,6 @@ void FullCodeGenerator::VisitCall(Call* expr) { UNREACHABLE(); } else if (var != NULL && !var->is_this() && var->is_global()) { // Call to a global variable. - __ Push(var->name()); // Push global object as receiver for the call IC lookup. __ push(CodeGenerator::GlobalObject()); EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); @@ -1264,7 +1263,6 @@ void FullCodeGenerator::VisitCall(Call* expr) { Literal* key = prop->key()->AsLiteral(); if (key != NULL && key->handle()->IsSymbol()) { // Call to a named property, use call IC. - __ Push(key->handle()); VisitForValue(prop->obj(), kStack); EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); } else { @@ -1355,7 +1353,6 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { if (expr->is_jsruntime()) { // Prepare for calling JS runtime function. - __ Push(expr->name()); __ movq(rax, CodeGenerator::GlobalObject()); __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); } @@ -1367,18 +1364,17 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { } if (expr->is_jsruntime()) { - // Call the JS runtime function. - Handle ic = CodeGenerator::ComputeCallInitialize(arg_count, - NOT_IN_LOOP); + // Call the JS runtime function using a call IC. + __ Move(rcx, expr->name()); + InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; + Handle ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); __ call(ic, RelocInfo::CODE_TARGET); // Restore context register. __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); - // Discard the function left on TOS. - DropAndApply(1, context_, rax); } else { __ CallRuntime(expr->function(), arg_count); - Apply(context_, rax); } + Apply(context_, rax); } diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc index d670a1f..7ca42a6 100644 --- a/src/x64/ic-x64.cc +++ b/src/x64/ic-x64.cc @@ -930,18 +930,24 @@ void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { + // ----------- S t a t e ------------- + // rcx : function name + // rsp[0] : return address + // rsp[8] : argument argc + // rsp[16] : argument argc - 1 + // ... + // rsp[argc * 8] : argument 1 + // rsp[(argc + 1) * 8] : argument 0 = receiver + // ----------------------------------- // Get the receiver of the function from the stack; 1 ~ return address. __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); - // Get the name of the function to call from the stack. - // 2 ~ receiver, return address. - __ movq(rbx, Operand(rsp, (argc + 2) * kPointerSize)); // Enter an internal frame. __ EnterInternalFrame(); // Push the receiver and the name of the function. __ push(rdx); - __ push(rbx); + __ push(rcx); // Call the entry. CEntryStub stub(1); @@ -979,20 +985,18 @@ Object* CallIC_Miss(Arguments args); void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { // ----------- S t a t e ------------- - // rsp[0] return address - // rsp[8] argument argc - // rsp[16] argument argc - 1 + // rcx : function name + // rsp[0] : return address + // rsp[8] : argument argc + // rsp[16] : argument argc - 1 // ... - // rsp[argc * 8] argument 1 - // rsp[(argc + 1) * 8] argument 0 = receiver - // rsp[(argc + 2) * 8] function name + // rsp[argc * 8] : argument 1 + // rsp[(argc + 1) * 8] : argument 0 = receiver // ----------------------------------- Label number, non_number, non_string, boolean, probe, miss; // Get the receiver of the function from the stack; 1 ~ return address. __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); - // Get the name of the function from the stack; 2 ~ return address, receiver - __ movq(rcx, Operand(rsp, (argc + 2) * kPointerSize)); // Probe the stub cache. Code::Flags flags = @@ -1045,6 +1049,16 @@ static void GenerateNormalHelper(MacroAssembler* masm, int argc, bool is_global_object, Label* miss) { + // ----------- S t a t e ------------- + // rcx : function name + // rdx : receiver + // rsp[0] : return address + // rsp[8] : argument argc + // rsp[16] : argument argc - 1 + // ... + // rsp[argc * 8] : argument 1 + // rsp[(argc + 1) * 8] : argument 0 = receiver + // ----------------------------------- // Search dictionary - put result in register rdx. GenerateDictionaryLoad(masm, miss, rax, rdx, rbx, rcx, CHECK_DICTIONARY); @@ -1075,20 +1089,18 @@ static void GenerateNormalHelper(MacroAssembler* masm, void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { // ----------- S t a t e ------------- - // rsp[0] return address - // rsp[8] argument argc - // rsp[16] argument argc - 1 + // rcx : function name + // rsp[0] : return address + // rsp[8] : argument argc + // rsp[16] : argument argc - 1 // ... - // rsp[argc * 8] argument 1 - // rsp[(argc + 1) * 8] argument 0 = receiver - // rsp[(argc + 2) * 8] function name + // rsp[argc * 8] : argument 1 + // rsp[(argc + 1) * 8] : argument 0 = receiver // ----------------------------------- Label miss, global_object, non_global_object; // Get the receiver of the function from the stack. __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); - // Get the name of the function from the stack. - __ movq(rcx, Operand(rsp, (argc + 2) * kPointerSize)); // Check that the receiver isn't a smi. __ JumpIfSmi(rdx, &miss); diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc index be8641c..8dab38e 100644 --- a/src/x64/stub-cache-x64.cc +++ b/src/x64/stub-cache-x64.cc @@ -133,11 +133,10 @@ void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, } -template static void PushInterceptorArguments(MacroAssembler* masm, Register receiver, Register holder, - Pushable name, + Register name, JSObject* holder_obj) { __ push(receiver); __ push(holder); @@ -348,11 +347,10 @@ void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, } -template static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, Register receiver, Register holder, - Pushable name, + Register name, JSObject* holder_obj) { PushInterceptorArguments(masm, receiver, holder, name, holder_obj); @@ -560,8 +558,8 @@ class LoadInterceptorCompiler BASE_EMBEDDED { class CallInterceptorCompiler BASE_EMBEDDED { public: - explicit CallInterceptorCompiler(const ParameterCount& arguments) - : arguments_(arguments), argc_(arguments.immediate()) {} + CallInterceptorCompiler(const ParameterCount& arguments, Register name) + : arguments_(arguments), argc_(arguments.immediate()), name_(name) {} void CompileCacheable(MacroAssembler* masm, StubCompiler* stub_compiler, @@ -592,17 +590,17 @@ class CallInterceptorCompiler BASE_EMBEDDED { } __ EnterInternalFrame(); - __ push(holder); // save the holder + __ push(holder); // Save the holder. + __ push(name_); // Save the name. - CompileCallLoadPropertyWithInterceptor( - masm, - receiver, - holder, - // Under EnterInternalFrame this refers to name. - Operand(rbp, (argc_ + 3) * kPointerSize), - holder_obj); + CompileCallLoadPropertyWithInterceptor(masm, + receiver, + holder, + name_, + holder_obj); - __ pop(receiver); // restore holder + __ pop(name_); // Restore the name. + __ pop(receiver); // Restore the holder. __ LeaveInternalFrame(); __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); @@ -641,11 +639,13 @@ class CallInterceptorCompiler BASE_EMBEDDED { JSObject* holder_obj, Label* miss_label) { __ EnterInternalFrame(); + // Save the name_ register across the call. + __ push(name_); PushInterceptorArguments(masm, receiver, holder, - Operand(rbp, (argc_ + 3) * kPointerSize), + name_, holder_obj); ExternalReference ref = ExternalReference( @@ -656,12 +656,14 @@ class CallInterceptorCompiler BASE_EMBEDDED { CEntryStub stub(1); __ CallStub(&stub); + __ pop(name_); __ LeaveInternalFrame(); } private: const ParameterCount& arguments_; int argc_; + Register name_; }; @@ -676,14 +678,14 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, String* name, StubCompiler::CheckType check) { // ----------- S t a t e ------------- - // ----------------------------------- - // rsp[0] return address - // rsp[8] argument argc - // rsp[16] argument argc - 1 + // rcx : function name + // rsp[0] : return address + // rsp[8] : argument argc + // rsp[16] : argument argc - 1 // ... - // rsp[argc * 8] argument 1 - // rsp[(argc + 1) * 8] argument 0 = receiver - // rsp[(argc + 2) * 8] function name + // rsp[argc * 8] : argument 1 + // rsp[(argc + 1) * 8] : argument 0 = receiver + // ----------------------------------- Label miss; @@ -704,7 +706,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, case RECEIVER_MAP_CHECK: // Check that the maps haven't changed. CheckPrototypes(JSObject::cast(object), rdx, holder, - rbx, rcx, name, &miss); + rbx, rax, name, &miss); // Patch the receiver on the stack with the global proxy if // necessary. @@ -720,13 +722,13 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, __ jmp(&miss); } else { // Check that the object is a two-byte string or a symbol. - __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rcx); + __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax); __ j(above_equal, &miss); // Check that the maps starting from the prototype haven't changed. GenerateLoadGlobalFunctionPrototype(masm(), Context::STRING_FUNCTION_INDEX, - rcx); - CheckPrototypes(JSObject::cast(object->GetPrototype()), rcx, holder, + rax); + CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, rbx, rdx, name, &miss); } break; @@ -739,14 +741,14 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, Label fast; // Check that the object is a smi or a heap number. __ JumpIfSmi(rdx, &fast); - __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx); + __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax); __ j(not_equal, &miss); __ bind(&fast); // Check that the maps starting from the prototype haven't changed. GenerateLoadGlobalFunctionPrototype(masm(), Context::NUMBER_FUNCTION_INDEX, - rcx); - CheckPrototypes(JSObject::cast(object->GetPrototype()), rcx, holder, + rax); + CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, rbx, rdx, name, &miss); } break; @@ -767,8 +769,8 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, // Check that the maps starting from the prototype haven't changed. GenerateLoadGlobalFunctionPrototype(masm(), Context::BOOLEAN_FUNCTION_INDEX, - rcx); - CheckPrototypes(JSObject::cast(object->GetPrototype()), rcx, holder, + rax); + CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, rbx, rdx, name, &miss); } break; @@ -776,7 +778,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, case JSARRAY_HAS_FAST_ELEMENTS_CHECK: CheckPrototypes(JSObject::cast(object), rdx, holder, - rbx, rcx, name, &miss); + rbx, rax, name, &miss); // Make sure object->HasFastElements(). // Get the elements array of the object. __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); @@ -820,14 +822,14 @@ Object* CallStubCompiler::CompileCallField(Object* object, int index, String* name) { // ----------- S t a t e ------------- - // ----------------------------------- - // rsp[0] return address - // rsp[8] argument argc - // rsp[16] argument argc - 1 + // rcx : function name + // rsp[0] : return address + // rsp[8] : argument argc + // rsp[16] : argument argc - 1 // ... - // rsp[argc * 8] argument 1 - // rsp[(argc + 1) * 8] argument 0 = receiver - // rsp[(argc + 2) * 8] function name + // rsp[argc * 8] : argument 1 + // rsp[(argc + 1) * 8] : argument 0 = receiver + // ----------------------------------- Label miss; // Get the receiver from the stack. @@ -840,7 +842,7 @@ Object* CallStubCompiler::CompileCallField(Object* object, // Do the right check and compute the holder register. Register reg = CheckPrototypes(JSObject::cast(object), rdx, holder, - rbx, rcx, name, &miss); + rbx, rax, name, &miss); GenerateFastPropertyLoad(masm(), rdi, reg, holder, index); @@ -873,6 +875,13 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* object, JSObject* holder, String* name) { // ----------- S t a t e ------------- + // rcx : function name + // rsp[0] : return address + // rsp[8] : argument argc + // rsp[16] : argument argc - 1 + // ... + // rsp[argc * 8] : argument 1 + // rsp[(argc + 1) * 8] : argument 0 = receiver // ----------------------------------- Label miss; @@ -885,7 +894,7 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* object, // Get the receiver from the stack. __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); - CallInterceptorCompiler compiler(arguments()); + CallInterceptorCompiler compiler(arguments(), rcx); CompileLoadInterceptor(&compiler, this, masm(), @@ -895,7 +904,7 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* object, &lookup, rdx, rbx, - rcx, + rdi, &miss); // Restore receiver. @@ -935,13 +944,13 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object, String* name) { // ----------- S t a t e ------------- // ----------------------------------- - // rsp[0] return address - // rsp[8] argument argc - // rsp[16] argument argc - 1 + // rcx : function name + // rsp[0] : return address + // rsp[8] : argument argc + // rsp[16] : argument argc - 1 // ... - // rsp[argc * 8] argument 1 - // rsp[(argc + 1) * 8] argument 0 = receiver - // rsp[(argc + 2) * 8] function name + // rsp[argc * 8] : argument 1 + // rsp[(argc + 1) * 8] : argument 0 = receiver Label miss; // Get the number of arguments. @@ -958,7 +967,7 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object, } // Check that the maps haven't changed. - CheckPrototypes(object, rdx, holder, rbx, rcx, name, &miss); + CheckPrototypes(object, rdx, holder, rbx, rax, name, &miss); // Get the value from the cell. __ Move(rdi, Handle(cell)); @@ -972,12 +981,12 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object, // function can all use this call IC. Before we load through the // function, we have to verify that it still is a function. __ JumpIfSmi(rdi, &miss); - __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); + __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax); __ j(not_equal, &miss); // Check the shared function info. Make sure it hasn't changed. - __ Move(rcx, Handle(function->shared())); - __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rcx); + __ Move(rax, Handle(function->shared())); + __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); __ j(not_equal, &miss); } else { __ Cmp(rdi, Handle(function)); diff --git a/src/x64/virtual-frame-x64.cc b/src/x64/virtual-frame-x64.cc index 5551ed9..291596b 100644 --- a/src/x64/virtual-frame-x64.cc +++ b/src/x64/virtual-frame-x64.cc @@ -1019,14 +1019,17 @@ Result VirtualFrame::CallKeyedStoreIC() { Result VirtualFrame::CallCallIC(RelocInfo::Mode mode, int arg_count, int loop_nesting) { - // Arguments, receiver, and function name are on top of the frame. - // The IC expects them on the stack. It does not drop the function - // name slot (but it does drop the rest). + // Function name, arguments, and receiver are found on top of the frame + // and dropped by the call. The IC expects the name in rcx and the rest + // on the stack, and drops them all. InLoopFlag in_loop = loop_nesting > 0 ? IN_LOOP : NOT_IN_LOOP; Handle ic = cgen()->ComputeCallInitialize(arg_count, in_loop); + Result name = Pop(); // Spill args, receiver, and function. The call will drop args and // receiver. - PrepareForCall(arg_count + 2, arg_count + 1); + PrepareForCall(arg_count + 1, arg_count + 1); + name.ToRegister(rcx); + name.Unuse(); return RawCallCodeObject(ic, mode); } diff --git a/src/x64/virtual-frame-x64.h b/src/x64/virtual-frame-x64.h index cecb3b0..9cb4d06 100644 --- a/src/x64/virtual-frame-x64.h +++ b/src/x64/virtual-frame-x64.h @@ -347,9 +347,9 @@ class VirtualFrame : public ZoneObject { // of the frame. Key and receiver are not dropped. Result CallKeyedStoreIC(); - // Call call IC. Arguments, receiver, and function name are found - // on top of the frame. Function name slot is not dropped. The - // argument count does not include the receiver. + // Call call IC. Function name, arguments, and receiver are found on top + // of the frame and dropped by the call. + // The argument count does not include the receiver. Result CallCallIC(RelocInfo::Mode mode, int arg_count, int loop_nesting); // Allocate and call JS function as constructor. Arguments, -- 2.7.4