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