Commit 4831b794 authored by whesse@chromium.org's avatar whesse@chromium.org

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
parent 29776256
...@@ -276,44 +276,48 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { ...@@ -276,44 +276,48 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ bind(&done); __ bind(&done);
} }
// 4. Shift stuff one slot down the stack. // 4. Check that the function really is a function.
{ Label loop; { Label real_function;
__ 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;
__ testq(rdi, rdi); __ testq(rdi, rdi);
__ j(not_zero, &invoke); __ j(not_zero, &real_function);
__ xor_(rbx, rbx); __ 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); __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
__ bind(&trampoline);
__ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
__ bind(&invoke); __ bind(&real_function);
__ 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);
} }
// 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<Code>(builtin(ArgumentsAdaptorTrampoline)),
RelocInfo::CODE_TARGET);
// 7. Jump (tail-call) to the code in register edx without checking arguments. // 7. Jump (tail-call) to the code in register edx without checking arguments.
ParameterCount expected(0); ParameterCount expected(0);
__ InvokeCode(rdx, expected, expected, JUMP_FUNCTION); __ InvokeCode(rdx, expected, expected, JUMP_FUNCTION);
......
...@@ -2757,9 +2757,6 @@ void CodeGenerator::VisitCall(Call* node) { ...@@ -2757,9 +2757,6 @@ void CodeGenerator::VisitCall(Call* node) {
// JavaScript example: 'foo(1, 2, 3)' // foo is global // 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 // Pass the global object as the receiver and let the IC stub
// patch the stack to use the global proxy as 'this' in the // patch the stack to use the global proxy as 'this' in the
// invoked function. // invoked function.
...@@ -2771,6 +2768,9 @@ void CodeGenerator::VisitCall(Call* node) { ...@@ -2771,6 +2768,9 @@ void CodeGenerator::VisitCall(Call* node) {
Load(args->at(i)); Load(args->at(i));
} }
// Push the name of the function on the frame.
frame_->Push(var->name());
// Call the IC initialization code. // Call the IC initialization code.
CodeForSourcePosition(node->position()); CodeForSourcePosition(node->position());
Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT, Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT,
...@@ -2778,7 +2778,7 @@ void CodeGenerator::VisitCall(Call* node) { ...@@ -2778,7 +2778,7 @@ void CodeGenerator::VisitCall(Call* node) {
loop_nesting()); loop_nesting());
frame_->RestoreContextRegister(); frame_->RestoreContextRegister();
// Replace the function on the stack with the result. // Replace the function on the stack with the result.
frame_->SetElementAt(0, &result); frame_->Push(&result);
} else if (var != NULL && var->slot() != NULL && } else if (var != NULL && var->slot() != NULL &&
var->slot()->type() == Slot::LOOKUP) { var->slot()->type() == Slot::LOOKUP) {
...@@ -2831,8 +2831,7 @@ void CodeGenerator::VisitCall(Call* node) { ...@@ -2831,8 +2831,7 @@ void CodeGenerator::VisitCall(Call* node) {
node->position()); node->position());
} else { } else {
// Push the name of the function and the receiver onto the stack. // Push the receiver onto the frame.
frame_->Push(name);
Load(property->obj()); Load(property->obj());
// Load the arguments. // Load the arguments.
...@@ -2841,14 +2840,16 @@ void CodeGenerator::VisitCall(Call* node) { ...@@ -2841,14 +2840,16 @@ void CodeGenerator::VisitCall(Call* node) {
Load(args->at(i)); Load(args->at(i));
} }
// Push the name of the function onto the frame.
frame_->Push(name);
// Call the IC initialization code. // Call the IC initialization code.
CodeForSourcePosition(node->position()); CodeForSourcePosition(node->position());
Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET, Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET,
arg_count, arg_count,
loop_nesting()); loop_nesting());
frame_->RestoreContextRegister(); frame_->RestoreContextRegister();
// Replace the function on the stack with the result. frame_->Push(&result);
frame_->SetElementAt(0, &result);
} }
} else { } else {
...@@ -2939,8 +2940,6 @@ void CodeGenerator::VisitCallRuntime(CallRuntime* node) { ...@@ -2939,8 +2940,6 @@ void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
Runtime::Function* function = node->function(); Runtime::Function* function = node->function();
if (function == NULL) { if (function == NULL) {
// Prepare stack for calling JS runtime function.
frame_->Push(node->name());
// Push the builtins object found in the current global object. // Push the builtins object found in the current global object.
Result temp = allocator()->Allocate(); Result temp = allocator()->Allocate();
ASSERT(temp.is_valid()); ASSERT(temp.is_valid());
...@@ -2958,11 +2957,12 @@ void CodeGenerator::VisitCallRuntime(CallRuntime* node) { ...@@ -2958,11 +2957,12 @@ void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
if (function == NULL) { if (function == NULL) {
// Call the JS runtime function. // Call the JS runtime function.
frame_->Push(node->name());
Result answer = frame_->CallCallIC(RelocInfo::CODE_TARGET, Result answer = frame_->CallCallIC(RelocInfo::CODE_TARGET,
arg_count, arg_count,
loop_nesting_); loop_nesting_);
frame_->RestoreContextRegister(); frame_->RestoreContextRegister();
frame_->SetElementAt(0, &answer); frame_->Push(&answer);
} else { } else {
// Call the C runtime function. // Call the C runtime function.
Result answer = frame_->CallRuntime(function, arg_count); Result answer = frame_->CallRuntime(function, arg_count);
......
...@@ -1200,7 +1200,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) { ...@@ -1200,7 +1200,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
void FullCodeGenerator::EmitCallWithIC(Call* expr, void FullCodeGenerator::EmitCallWithIC(Call* expr,
Handle<Object> ignored, Handle<Object> name,
RelocInfo::Mode mode) { RelocInfo::Mode mode) {
// Code common for calls using the IC. // Code common for calls using the IC.
ZoneList<Expression*>* args = expr->arguments(); ZoneList<Expression*>* args = expr->arguments();
...@@ -1208,6 +1208,7 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, ...@@ -1208,6 +1208,7 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr,
for (int i = 0; i < arg_count; i++) { for (int i = 0; i < arg_count; i++) {
VisitForValue(args->at(i), kStack); VisitForValue(args->at(i), kStack);
} }
__ Move(rcx, name);
// Record source position for debugger. // Record source position for debugger.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position());
// Call the IC initialization code. // Call the IC initialization code.
...@@ -1217,8 +1218,7 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, ...@@ -1217,8 +1218,7 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr,
__ Call(ic, mode); __ Call(ic, mode);
// Restore context register. // Restore context register.
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
// Discard the function left on TOS. Apply(context_, rax);
DropAndApply(1, context_, rax);
} }
...@@ -1250,7 +1250,6 @@ void FullCodeGenerator::VisitCall(Call* expr) { ...@@ -1250,7 +1250,6 @@ void FullCodeGenerator::VisitCall(Call* expr) {
UNREACHABLE(); UNREACHABLE();
} else if (var != NULL && !var->is_this() && var->is_global()) { } else if (var != NULL && !var->is_this() && var->is_global()) {
// Call to a global variable. // Call to a global variable.
__ Push(var->name());
// Push global object as receiver for the call IC lookup. // Push global object as receiver for the call IC lookup.
__ push(CodeGenerator::GlobalObject()); __ push(CodeGenerator::GlobalObject());
EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
...@@ -1264,7 +1263,6 @@ void FullCodeGenerator::VisitCall(Call* expr) { ...@@ -1264,7 +1263,6 @@ void FullCodeGenerator::VisitCall(Call* expr) {
Literal* key = prop->key()->AsLiteral(); Literal* key = prop->key()->AsLiteral();
if (key != NULL && key->handle()->IsSymbol()) { if (key != NULL && key->handle()->IsSymbol()) {
// Call to a named property, use call IC. // Call to a named property, use call IC.
__ Push(key->handle());
VisitForValue(prop->obj(), kStack); VisitForValue(prop->obj(), kStack);
EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
} else { } else {
...@@ -1355,7 +1353,6 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { ...@@ -1355,7 +1353,6 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
if (expr->is_jsruntime()) { if (expr->is_jsruntime()) {
// Prepare for calling JS runtime function. // Prepare for calling JS runtime function.
__ Push(expr->name());
__ movq(rax, CodeGenerator::GlobalObject()); __ movq(rax, CodeGenerator::GlobalObject());
__ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
} }
...@@ -1367,18 +1364,17 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { ...@@ -1367,18 +1364,17 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
} }
if (expr->is_jsruntime()) { if (expr->is_jsruntime()) {
// Call the JS runtime function. // Call the JS runtime function using a call IC.
Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, __ Move(rcx, expr->name());
NOT_IN_LOOP); 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); __ call(ic, RelocInfo::CODE_TARGET);
// Restore context register. // Restore context register.
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
// Discard the function left on TOS.
DropAndApply(1, context_, rax);
} else { } else {
__ CallRuntime(expr->function(), arg_count); __ CallRuntime(expr->function(), arg_count);
Apply(context_, rax);
} }
Apply(context_, rax);
} }
......
...@@ -930,18 +930,24 @@ void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, ...@@ -930,18 +930,24 @@ void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { 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. // Get the receiver of the function from the stack; 1 ~ return address.
__ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); __ 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. // Enter an internal frame.
__ EnterInternalFrame(); __ EnterInternalFrame();
// Push the receiver and the name of the function. // Push the receiver and the name of the function.
__ push(rdx); __ push(rdx);
__ push(rbx); __ push(rcx);
// Call the entry. // Call the entry.
CEntryStub stub(1); CEntryStub stub(1);
...@@ -979,20 +985,18 @@ Object* CallIC_Miss(Arguments args); ...@@ -979,20 +985,18 @@ Object* CallIC_Miss(Arguments args);
void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// rsp[0] return address // rcx : function name
// rsp[8] argument argc // rsp[0] : return address
// rsp[16] argument argc - 1 // rsp[8] : argument argc
// rsp[16] : argument argc - 1
// ... // ...
// rsp[argc * 8] argument 1 // rsp[argc * 8] : argument 1
// rsp[(argc + 1) * 8] argument 0 = receiver // rsp[(argc + 1) * 8] : argument 0 = receiver
// rsp[(argc + 2) * 8] function name
// ----------------------------------- // -----------------------------------
Label number, non_number, non_string, boolean, probe, miss; Label number, non_number, non_string, boolean, probe, miss;
// Get the receiver of the function from the stack; 1 ~ return address. // Get the receiver of the function from the stack; 1 ~ return address.
__ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); __ 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. // Probe the stub cache.
Code::Flags flags = Code::Flags flags =
...@@ -1045,6 +1049,16 @@ static void GenerateNormalHelper(MacroAssembler* masm, ...@@ -1045,6 +1049,16 @@ static void GenerateNormalHelper(MacroAssembler* masm,
int argc, int argc,
bool is_global_object, bool is_global_object,
Label* miss) { 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. // Search dictionary - put result in register rdx.
GenerateDictionaryLoad(masm, miss, rax, rdx, rbx, rcx, CHECK_DICTIONARY); GenerateDictionaryLoad(masm, miss, rax, rdx, rbx, rcx, CHECK_DICTIONARY);
...@@ -1075,20 +1089,18 @@ static void GenerateNormalHelper(MacroAssembler* masm, ...@@ -1075,20 +1089,18 @@ static void GenerateNormalHelper(MacroAssembler* masm,
void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// rsp[0] return address // rcx : function name
// rsp[8] argument argc // rsp[0] : return address
// rsp[16] argument argc - 1 // rsp[8] : argument argc
// rsp[16] : argument argc - 1
// ... // ...
// rsp[argc * 8] argument 1 // rsp[argc * 8] : argument 1
// rsp[(argc + 1) * 8] argument 0 = receiver // rsp[(argc + 1) * 8] : argument 0 = receiver
// rsp[(argc + 2) * 8] function name
// ----------------------------------- // -----------------------------------
Label miss, global_object, non_global_object; Label miss, global_object, non_global_object;
// Get the receiver of the function from the stack. // Get the receiver of the function from the stack.
__ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); __ 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. // Check that the receiver isn't a smi.
__ JumpIfSmi(rdx, &miss); __ JumpIfSmi(rdx, &miss);
......
...@@ -133,11 +133,10 @@ void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, ...@@ -133,11 +133,10 @@ void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
} }
template <typename Pushable>
static void PushInterceptorArguments(MacroAssembler* masm, static void PushInterceptorArguments(MacroAssembler* masm,
Register receiver, Register receiver,
Register holder, Register holder,
Pushable name, Register name,
JSObject* holder_obj) { JSObject* holder_obj) {
__ push(receiver); __ push(receiver);
__ push(holder); __ push(holder);
...@@ -348,11 +347,10 @@ void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, ...@@ -348,11 +347,10 @@ void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
} }
template <class Pushable>
static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm,
Register receiver, Register receiver,
Register holder, Register holder,
Pushable name, Register name,
JSObject* holder_obj) { JSObject* holder_obj) {
PushInterceptorArguments(masm, receiver, holder, name, holder_obj); PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
...@@ -560,8 +558,8 @@ class LoadInterceptorCompiler BASE_EMBEDDED { ...@@ -560,8 +558,8 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
class CallInterceptorCompiler BASE_EMBEDDED { class CallInterceptorCompiler BASE_EMBEDDED {
public: public:
explicit CallInterceptorCompiler(const ParameterCount& arguments) CallInterceptorCompiler(const ParameterCount& arguments, Register name)
: arguments_(arguments), argc_(arguments.immediate()) {} : arguments_(arguments), argc_(arguments.immediate()), name_(name) {}
void CompileCacheable(MacroAssembler* masm, void CompileCacheable(MacroAssembler* masm,
StubCompiler* stub_compiler, StubCompiler* stub_compiler,
...@@ -592,17 +590,17 @@ class CallInterceptorCompiler BASE_EMBEDDED { ...@@ -592,17 +590,17 @@ class CallInterceptorCompiler BASE_EMBEDDED {
} }
__ EnterInternalFrame(); __ EnterInternalFrame();
__ push(holder); // save the holder __ push(holder); // Save the holder.
__ push(name_); // Save the name.
CompileCallLoadPropertyWithInterceptor( CompileCallLoadPropertyWithInterceptor(masm,
masm, receiver,
receiver, holder,
holder, name_,
// Under EnterInternalFrame this refers to name. holder_obj);
Operand(rbp, (argc_ + 3) * kPointerSize),
holder_obj);
__ pop(receiver); // restore holder __ pop(name_); // Restore the name.
__ pop(receiver); // Restore the holder.
__ LeaveInternalFrame(); __ LeaveInternalFrame();
__ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
...@@ -641,11 +639,13 @@ class CallInterceptorCompiler BASE_EMBEDDED { ...@@ -641,11 +639,13 @@ class CallInterceptorCompiler BASE_EMBEDDED {
JSObject* holder_obj, JSObject* holder_obj,
Label* miss_label) { Label* miss_label) {
__ EnterInternalFrame(); __ EnterInternalFrame();
// Save the name_ register across the call.
__ push(name_);
PushInterceptorArguments(masm, PushInterceptorArguments(masm,
receiver, receiver,
holder, holder,
Operand(rbp, (argc_ + 3) * kPointerSize), name_,
holder_obj); holder_obj);
ExternalReference ref = ExternalReference( ExternalReference ref = ExternalReference(
...@@ -656,12 +656,14 @@ class CallInterceptorCompiler BASE_EMBEDDED { ...@@ -656,12 +656,14 @@ class CallInterceptorCompiler BASE_EMBEDDED {
CEntryStub stub(1); CEntryStub stub(1);
__ CallStub(&stub); __ CallStub(&stub);
__ pop(name_);
__ LeaveInternalFrame(); __ LeaveInternalFrame();
} }
private: private:
const ParameterCount& arguments_; const ParameterCount& arguments_;
int argc_; int argc_;
Register name_;
}; };
...@@ -676,14 +678,14 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -676,14 +678,14 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
String* name, String* name,
StubCompiler::CheckType check) { StubCompiler::CheckType check) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// ----------------------------------- // rcx : function name
// rsp[0] return address // rsp[0] : return address
// rsp[8] argument argc // rsp[8] : argument argc
// rsp[16] argument argc - 1 // rsp[16] : argument argc - 1
// ... // ...
// rsp[argc * 8] argument 1 // rsp[argc * 8] : argument 1
// rsp[(argc + 1) * 8] argument 0 = receiver // rsp[(argc + 1) * 8] : argument 0 = receiver
// rsp[(argc + 2) * 8] function name // -----------------------------------
Label miss; Label miss;
...@@ -704,7 +706,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -704,7 +706,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
case RECEIVER_MAP_CHECK: case RECEIVER_MAP_CHECK:
// Check that the maps haven't changed. // Check that the maps haven't changed.
CheckPrototypes(JSObject::cast(object), rdx, holder, 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 // Patch the receiver on the stack with the global proxy if
// necessary. // necessary.
...@@ -720,13 +722,13 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -720,13 +722,13 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
__ jmp(&miss); __ jmp(&miss);
} else { } else {
// Check that the object is a two-byte string or a symbol. // 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); __ j(above_equal, &miss);
// Check that the maps starting from the prototype haven't changed. // Check that the maps starting from the prototype haven't changed.
GenerateLoadGlobalFunctionPrototype(masm(), GenerateLoadGlobalFunctionPrototype(masm(),
Context::STRING_FUNCTION_INDEX, Context::STRING_FUNCTION_INDEX,
rcx); rax);
CheckPrototypes(JSObject::cast(object->GetPrototype()), rcx, holder, CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
rbx, rdx, name, &miss); rbx, rdx, name, &miss);
} }
break; break;
...@@ -739,14 +741,14 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -739,14 +741,14 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
Label fast; Label fast;
// Check that the object is a smi or a heap number. // Check that the object is a smi or a heap number.
__ JumpIfSmi(rdx, &fast); __ JumpIfSmi(rdx, &fast);
__ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx); __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax);
__ j(not_equal, &miss); __ j(not_equal, &miss);
__ bind(&fast); __ bind(&fast);
// Check that the maps starting from the prototype haven't changed. // Check that the maps starting from the prototype haven't changed.
GenerateLoadGlobalFunctionPrototype(masm(), GenerateLoadGlobalFunctionPrototype(masm(),
Context::NUMBER_FUNCTION_INDEX, Context::NUMBER_FUNCTION_INDEX,
rcx); rax);
CheckPrototypes(JSObject::cast(object->GetPrototype()), rcx, holder, CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
rbx, rdx, name, &miss); rbx, rdx, name, &miss);
} }
break; break;
...@@ -767,8 +769,8 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -767,8 +769,8 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
// Check that the maps starting from the prototype haven't changed. // Check that the maps starting from the prototype haven't changed.
GenerateLoadGlobalFunctionPrototype(masm(), GenerateLoadGlobalFunctionPrototype(masm(),
Context::BOOLEAN_FUNCTION_INDEX, Context::BOOLEAN_FUNCTION_INDEX,
rcx); rax);
CheckPrototypes(JSObject::cast(object->GetPrototype()), rcx, holder, CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
rbx, rdx, name, &miss); rbx, rdx, name, &miss);
} }
break; break;
...@@ -776,7 +778,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -776,7 +778,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
case JSARRAY_HAS_FAST_ELEMENTS_CHECK: case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
CheckPrototypes(JSObject::cast(object), rdx, holder, CheckPrototypes(JSObject::cast(object), rdx, holder,
rbx, rcx, name, &miss); rbx, rax, name, &miss);
// Make sure object->HasFastElements(). // Make sure object->HasFastElements().
// Get the elements array of the object. // Get the elements array of the object.
__ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
...@@ -820,14 +822,14 @@ Object* CallStubCompiler::CompileCallField(Object* object, ...@@ -820,14 +822,14 @@ Object* CallStubCompiler::CompileCallField(Object* object,
int index, int index,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// ----------------------------------- // rcx : function name
// rsp[0] return address // rsp[0] : return address
// rsp[8] argument argc // rsp[8] : argument argc
// rsp[16] argument argc - 1 // rsp[16] : argument argc - 1
// ... // ...
// rsp[argc * 8] argument 1 // rsp[argc * 8] : argument 1
// rsp[(argc + 1) * 8] argument 0 = receiver // rsp[(argc + 1) * 8] : argument 0 = receiver
// rsp[(argc + 2) * 8] function name // -----------------------------------
Label miss; Label miss;
// Get the receiver from the stack. // Get the receiver from the stack.
...@@ -840,7 +842,7 @@ Object* CallStubCompiler::CompileCallField(Object* object, ...@@ -840,7 +842,7 @@ Object* CallStubCompiler::CompileCallField(Object* object,
// Do the right check and compute the holder register. // Do the right check and compute the holder register.
Register reg = Register reg =
CheckPrototypes(JSObject::cast(object), rdx, holder, CheckPrototypes(JSObject::cast(object), rdx, holder,
rbx, rcx, name, &miss); rbx, rax, name, &miss);
GenerateFastPropertyLoad(masm(), rdi, reg, holder, index); GenerateFastPropertyLoad(masm(), rdi, reg, holder, index);
...@@ -873,6 +875,13 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* object, ...@@ -873,6 +875,13 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* object,
JSObject* holder, JSObject* holder,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- 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; Label miss;
...@@ -885,7 +894,7 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* object, ...@@ -885,7 +894,7 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* object,
// Get the receiver from the stack. // Get the receiver from the stack.
__ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
CallInterceptorCompiler compiler(arguments()); CallInterceptorCompiler compiler(arguments(), rcx);
CompileLoadInterceptor(&compiler, CompileLoadInterceptor(&compiler,
this, this,
masm(), masm(),
...@@ -895,7 +904,7 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* object, ...@@ -895,7 +904,7 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* object,
&lookup, &lookup,
rdx, rdx,
rbx, rbx,
rcx, rdi,
&miss); &miss);
// Restore receiver. // Restore receiver.
...@@ -935,13 +944,13 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object, ...@@ -935,13 +944,13 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// ----------------------------------- // -----------------------------------
// rsp[0] return address // rcx : function name
// rsp[8] argument argc // rsp[0] : return address
// rsp[16] argument argc - 1 // rsp[8] : argument argc
// rsp[16] : argument argc - 1
// ... // ...
// rsp[argc * 8] argument 1 // rsp[argc * 8] : argument 1
// rsp[(argc + 1) * 8] argument 0 = receiver // rsp[(argc + 1) * 8] : argument 0 = receiver
// rsp[(argc + 2) * 8] function name
Label miss; Label miss;
// Get the number of arguments. // Get the number of arguments.
...@@ -958,7 +967,7 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object, ...@@ -958,7 +967,7 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object,
} }
// Check that the maps haven't changed. // 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. // Get the value from the cell.
__ Move(rdi, Handle<JSGlobalPropertyCell>(cell)); __ Move(rdi, Handle<JSGlobalPropertyCell>(cell));
...@@ -972,12 +981,12 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object, ...@@ -972,12 +981,12 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object,
// function can all use this call IC. Before we load through the // function can all use this call IC. Before we load through the
// function, we have to verify that it still is a function. // function, we have to verify that it still is a function.
__ JumpIfSmi(rdi, &miss); __ JumpIfSmi(rdi, &miss);
__ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax);
__ j(not_equal, &miss); __ j(not_equal, &miss);
// Check the shared function info. Make sure it hasn't changed. // Check the shared function info. Make sure it hasn't changed.
__ Move(rcx, Handle<SharedFunctionInfo>(function->shared())); __ Move(rax, Handle<SharedFunctionInfo>(function->shared()));
__ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rcx); __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax);
__ j(not_equal, &miss); __ j(not_equal, &miss);
} else { } else {
__ Cmp(rdi, Handle<JSFunction>(function)); __ Cmp(rdi, Handle<JSFunction>(function));
......
...@@ -1019,14 +1019,17 @@ Result VirtualFrame::CallKeyedStoreIC() { ...@@ -1019,14 +1019,17 @@ Result VirtualFrame::CallKeyedStoreIC() {
Result VirtualFrame::CallCallIC(RelocInfo::Mode mode, Result VirtualFrame::CallCallIC(RelocInfo::Mode mode,
int arg_count, int arg_count,
int loop_nesting) { int loop_nesting) {
// Arguments, receiver, and function name are on top of the frame. // Function name, arguments, and receiver are found on top of the frame
// The IC expects them on the stack. It does not drop the function // and dropped by the call. The IC expects the name in rcx and the rest
// name slot (but it does drop the rest). // on the stack, and drops them all.
InLoopFlag in_loop = loop_nesting > 0 ? IN_LOOP : NOT_IN_LOOP; InLoopFlag in_loop = loop_nesting > 0 ? IN_LOOP : NOT_IN_LOOP;
Handle<Code> ic = cgen()->ComputeCallInitialize(arg_count, 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 // Spill args, receiver, and function. The call will drop args and
// receiver. // receiver.
PrepareForCall(arg_count + 2, arg_count + 1); PrepareForCall(arg_count + 1, arg_count + 1);
name.ToRegister(rcx);
name.Unuse();
return RawCallCodeObject(ic, mode); return RawCallCodeObject(ic, mode);
} }
......
...@@ -347,9 +347,9 @@ class VirtualFrame : public ZoneObject { ...@@ -347,9 +347,9 @@ class VirtualFrame : public ZoneObject {
// of the frame. Key and receiver are not dropped. // of the frame. Key and receiver are not dropped.
Result CallKeyedStoreIC(); Result CallKeyedStoreIC();
// Call call IC. Arguments, receiver, and function name are found // Call call IC. Function name, arguments, and receiver are found on top
// on top of the frame. Function name slot is not dropped. The // of the frame and dropped by the call.
// argument count does not include the receiver. // The argument count does not include the receiver.
Result CallCallIC(RelocInfo::Mode mode, int arg_count, int loop_nesting); Result CallCallIC(RelocInfo::Mode mode, int arg_count, int loop_nesting);
// Allocate and call JS function as constructor. Arguments, // Allocate and call JS function as constructor. Arguments,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment