Index: src/x64/stub-cache-x64.cc |
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc |
index e85f37e01637f509087c502dd56459c6c0ad7a9e..bc8effe6c151a28f931e5d12a378fef616480a97 100644 |
--- a/src/x64/stub-cache-x64.cc |
+++ b/src/x64/stub-cache-x64.cc |
@@ -1982,6 +1982,65 @@ MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, |
} |
+MaybeObject* CallStubCompiler::CompileFastApiCall( |
+ const CallOptimization& optimization, |
+ Object* object, |
+ JSObject* holder, |
+ JSGlobalPropertyCell* cell, |
+ JSFunction* function, |
+ String* name) { |
+ ASSERT(optimization.is_simple_api_call()); |
+ // Bail out if object is a global object as we don't want to |
+ // repatch it to global receiver. |
+ if (object->IsGlobalObject()) return Heap::undefined_value(); |
+ if (cell != NULL) return Heap::undefined_value(); |
+ int depth = optimization.GetPrototypeDepthOfExpectedType( |
+ JSObject::cast(object), holder); |
+ if (depth == kInvalidProtoDepth) return Heap::undefined_value(); |
+ |
+ Label miss, miss_before_stack_reserved; |
+ |
+ GenerateNameCheck(name, &miss_before_stack_reserved); |
+ |
+ // Get the receiver from the stack. |
+ const int argc = arguments().immediate(); |
+ __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
+ |
+ // Check that the receiver isn't a smi. |
+ __ JumpIfSmi(rdx, &miss_before_stack_reserved); |
+ |
+ __ IncrementCounter(&Counters::call_const, 1); |
+ __ IncrementCounter(&Counters::call_const_fast_api, 1); |
+ |
+ // Allocate space for v8::Arguments implicit values. Must be initialized |
+ // before calling any runtime function. |
+ __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
+ |
+ // Check that the maps haven't changed and find a Holder as a side effect. |
+ CheckPrototypes(JSObject::cast(object), rdx, holder, |
+ rbx, rax, rdi, name, depth, &miss); |
+ |
+ // Move the return address on top of the stack. |
+ __ movq(rax, Operand(rsp, 3 * kPointerSize)); |
+ __ movq(Operand(rsp, 0 * kPointerSize), rax); |
+ |
+ MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); |
+ if (result->IsFailure()) return result; |
+ |
+ __ bind(&miss); |
+ __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
+ |
+ __ bind(&miss_before_stack_reserved); |
+ Object* obj; |
+ { MaybeObject* maybe_obj = GenerateMissBranch(); |
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
+ } |
+ |
+ // Return the generated code. |
+ return GetCode(function); |
+} |
+ |
+ |
MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, |
JSObject* holder, |
JSFunction* function, |
@@ -1997,20 +2056,18 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, |
// rsp[(argc + 1) * 8] : argument 0 = receiver |
// ----------------------------------- |
- SharedFunctionInfo* function_info = function->shared(); |
- if (function_info->HasBuiltinFunctionId()) { |
- BuiltinFunctionId id = function_info->builtin_function_id(); |
+ if (HasCustomCallGenerator(function)) { |
MaybeObject* maybe_result = CompileCustomCall( |
- id, object, holder, NULL, function, name); |
+ object, holder, NULL, function, name); |
Object* result; |
if (!maybe_result->ToObject(&result)) return maybe_result; |
// undefined means bail out to regular compiler. |
if (!result->IsUndefined()) return result; |
} |
- Label miss_in_smi_check; |
+ Label miss; |
- GenerateNameCheck(name, &miss_in_smi_check); |
+ GenerateNameCheck(name, &miss); |
// Get the receiver from the stack. |
const int argc = arguments().immediate(); |
@@ -2018,42 +2075,25 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, |
// Check that the receiver isn't a smi. |
if (check != NUMBER_CHECK) { |
- __ JumpIfSmi(rdx, &miss_in_smi_check); |
+ __ JumpIfSmi(rdx, &miss); |
} |
// Make sure that it's okay not to patch the on stack receiver |
// unless we're doing a receiver map check. |
ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
- CallOptimization optimization(function); |
- int depth = kInvalidProtoDepth; |
- Label miss; |
- |
+ SharedFunctionInfo* function_info = function->shared(); |
switch (check) { |
case RECEIVER_MAP_CHECK: |
__ IncrementCounter(&Counters::call_const, 1); |
- if (optimization.is_simple_api_call() && !object->IsGlobalObject()) { |
- depth = optimization.GetPrototypeDepthOfExpectedType( |
- JSObject::cast(object), holder); |
- } |
- |
- if (depth != kInvalidProtoDepth) { |
- __ IncrementCounter(&Counters::call_const_fast_api, 1); |
- |
- // Allocate space for v8::Arguments implicit values. Must be initialized |
- // before to call any runtime function. |
- __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
- } |
- |
// Check that the maps haven't changed. |
CheckPrototypes(JSObject::cast(object), rdx, holder, |
- rbx, rax, rdi, name, depth, &miss); |
+ rbx, rax, rdi, name, &miss); |
// Patch the receiver on the stack with the global proxy if |
// necessary. |
if (object->IsGlobalObject()) { |
- ASSERT(depth == kInvalidProtoDepth); |
__ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
__ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
} |
@@ -2123,27 +2163,10 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, |
UNREACHABLE(); |
} |
- if (depth != kInvalidProtoDepth) { |
- // Move the return address on top of the stack. |
- __ movq(rax, Operand(rsp, 3 * kPointerSize)); |
- __ movq(Operand(rsp, 0 * kPointerSize), rax); |
- |
- // rsp[2 * kPointerSize] is uninitialized, rsp[3 * kPointerSize] contains |
- // duplicate of return address and will be overwritten. |
- MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); |
- if (result->IsFailure()) return result; |
- } else { |
- __ InvokeFunction(function, arguments(), JUMP_FUNCTION); |
- } |
+ __ InvokeFunction(function, arguments(), JUMP_FUNCTION); |
// Handle call cache miss. |
__ bind(&miss); |
- if (depth != kInvalidProtoDepth) { |
- __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
- } |
- |
- // Handle call cache miss. |
- __ bind(&miss_in_smi_check); |
Object* obj; |
{ MaybeObject* maybe_obj = GenerateMissBranch(); |
if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
@@ -2238,11 +2261,9 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, |
// rsp[(argc + 1) * 8] : argument 0 = receiver |
// ----------------------------------- |
- SharedFunctionInfo* function_info = function->shared(); |
- if (function_info->HasBuiltinFunctionId()) { |
- BuiltinFunctionId id = function_info->builtin_function_id(); |
+ if (HasCustomCallGenerator(function)) { |
MaybeObject* maybe_result = CompileCustomCall( |
- id, object, holder, cell, function, name); |
+ object, holder, cell, function, name); |
Object* result; |
if (!maybe_result->ToObject(&result)) return maybe_result; |
// undefined means bail out to regular compiler. |
@@ -2960,7 +2981,7 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { |
// ----------- S t a t e ------------- |
// -- rax : key |
// -- rdx : receiver |
- // -- esp[0] : return address |
+ // -- rsp[0] : return address |
// ----------------------------------- |
Label miss; |