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
This commit is contained in:
whesse@chromium.org 2010-02-12 08:53:13 +00:00
parent 29776256ab
commit 4831b79421
7 changed files with 157 additions and 133 deletions

View File

@ -276,43 +276,47 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ bind(&done);
}
// 4. Shift stuff one slot down the stack.
// 4. Check that the function really is a function.
{ Label real_function;
__ testq(rdi, rdi);
__ 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);
__ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
RelocInfo::CODE_TARGET);
__ bind(&real_function);
}
// 5. Shift arguments and return address one slot down on the stack
// (overwriting the receiver).
{ Label loop;
__ lea(rcx, Operand(rax, +1)); // +1 ~ copy receiver too
__ 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_zero, &loop);
__ j(not_sign, &loop);
__ pop(rbx); // Discard copy of return address.
__ decq(rax); // One fewer argument (first argument is new receiver).
}
// 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;
__ testq(rdi, rdi);
__ j(not_zero, &invoke);
__ xor_(rbx, rbx);
__ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
__ bind(&trampoline);
__ Jump(Handle<Code>(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);
}
// 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<Code>(builtin(ArgumentsAdaptorTrampoline)),
RelocInfo::CODE_TARGET);
// 7. Jump (tail-call) to the code in register edx without checking arguments.
ParameterCount expected(0);

View File

@ -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);

View File

@ -1200,7 +1200,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
void FullCodeGenerator::EmitCallWithIC(Call* expr,
Handle<Object> ignored,
Handle<Object> name,
RelocInfo::Mode mode) {
// Code common for calls using the IC.
ZoneList<Expression*>* 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<Code> 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<Code> 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);
}

View File

@ -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);

View File

@ -133,11 +133,10 @@ void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
}
template <typename Pushable>
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 <class Pushable>
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<JSGlobalPropertyCell>(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<SharedFunctionInfo>(function->shared()));
__ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rcx);
__ Move(rax, Handle<SharedFunctionInfo>(function->shared()));
__ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax);
__ j(not_equal, &miss);
} else {
__ Cmp(rdi, Handle<JSFunction>(function));

View File

@ -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<Code> 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);
}

View File

@ -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,