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:
parent
29776256ab
commit
4831b79421
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user