| Index: src/builtins/x64/builtins-x64.cc | 
| diff --git a/src/builtins/x64/builtins-x64.cc b/src/builtins/x64/builtins-x64.cc | 
| index 076cc8596cebf54b9b70be50beaab330660bf122..493036c0af726a86845a64b3ccb0a124a34ac96b 100644 | 
| --- a/src/builtins/x64/builtins-x64.cc | 
| +++ b/src/builtins/x64/builtins-x64.cc | 
| @@ -4,6 +4,7 @@ | 
|  | 
| #if V8_TARGET_ARCH_X64 | 
|  | 
| +#include "src/api-arguments.h" | 
| #include "src/code-factory.h" | 
| #include "src/codegen.h" | 
| #include "src/counters.h" | 
| @@ -2936,6 +2937,139 @@ void Builtins::Generate_CallWithSpread(MacroAssembler* masm) { | 
| } | 
|  | 
| // static | 
| +void Builtins::Generate_CallFunctionCallback(MacroAssembler* masm) { | 
| +  // ----------- S t a t e ------------- | 
| +  //  -- rax                : the number of arguments (not incl. the receiver) | 
| +  //  -- rdx                : api function address | 
| +  //  -- rsp[0]             : return address | 
| +  //  -- rsp[8]             : holder | 
| +  //  -- rsp[16]            : isolate | 
| +  //  -- rsp[24]            : return value default | 
| +  //  -- rsp[32]            : return value | 
| +  //  -- rsp[40]            : call data | 
| +  //  -- rsp[48]            : target | 
| +  //  -- rsp[56]            : context save | 
| +  //  -- rsp[64]            : new.target | 
| +  //  -- rsp[72]            : last argument | 
| +  //  -- rsp[64 + argc * 8] : first argument | 
| +  //  -- rsp[72 + argc * 8] : receiver | 
| +  // ----------------------------------- | 
| +  typedef FunctionCallbackArguments FCA; | 
| + | 
| +  STATIC_ASSERT(FCA::kNewTargetIndex == 7); | 
| +  STATIC_ASSERT(FCA::kContextSaveIndex == 6); | 
| +  STATIC_ASSERT(FCA::kCalleeIndex == 5); | 
| +  STATIC_ASSERT(FCA::kDataIndex == 4); | 
| +  STATIC_ASSERT(FCA::kReturnValueOffset == 3); | 
| +  STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); | 
| +  STATIC_ASSERT(FCA::kIsolateIndex == 1); | 
| +  STATIC_ASSERT(FCA::kHolderIndex == 0); | 
| +  STATIC_ASSERT(FCA::kArgsLength == 8); | 
| + | 
| +  // Compute the pointer to the implicit args on the stack. | 
| +  __ leap(rbx, MemOperand(rsp, kPCOnStackSize)); | 
| + | 
| +  // Allocate the v8::FunctionCallbackInfo structure in the arguments' space | 
| +  // since it's not controlled by the GC. | 
| +  const int kApiStackSpace = 3; | 
| +  __ EnterApiExitFrame(kApiStackSpace); | 
| +  // Initialize FunctionCallbackInfo::implicit_args_. | 
| +  __ movp(StackSpaceOperand(0), rbx); | 
| +  // Initialize FunctionCallbackInfo::values_. | 
| +  __ leap(rbx, MemOperand(rbx, rax, times_pointer_size, | 
| +                          (FCA::kArgsLength - 1) * kPointerSize)); | 
| +  __ movp(StackSpaceOperand(1), rbx); | 
| +  // Initialize FunctionCallbackInfo::length_. | 
| +  __ movp(StackSpaceOperand(2), rax); | 
| + | 
| +  // Load first argument with pointer to FunctionCallbackInfo. | 
| +  __ leap(arg_reg_1, StackSpaceOperand(0)); | 
| + | 
| +  const int kNextOffset = 0; | 
| +  const int kLimitOffset = AddressOffset( | 
| +      ExternalReference::handle_scope_limit_address(masm->isolate()), | 
| +      ExternalReference::handle_scope_next_address(masm->isolate())); | 
| +  const int kLevelOffset = AddressOffset( | 
| +      ExternalReference::handle_scope_level_address(masm->isolate()), | 
| +      ExternalReference::handle_scope_next_address(masm->isolate())); | 
| + | 
| +  // Allocate HandleScope in callee-save registers. | 
| +  Register const prev_next_address_reg = r14; | 
| +  Register const prev_limit_reg = rbx; | 
| +  Register const base_reg = r15; | 
| +  __ Move(base_reg, | 
| +          ExternalReference::handle_scope_next_address(masm->isolate())); | 
| +  __ movp(prev_next_address_reg, Operand(base_reg, kNextOffset)); | 
| +  __ movp(prev_limit_reg, Operand(base_reg, kLimitOffset)); | 
| +  __ addl(Operand(base_reg, kLevelOffset), Immediate(1)); | 
| + | 
| +  // Check if profiling is active, and if so call the function indirectly | 
| +  // via the invoke_function_callback helper. | 
| +  Label call_indirect, done_call; | 
| +  __ Move(rax, ExternalReference::is_profiling_address(masm->isolate())); | 
| +  __ cmpb(MemOperand(rax, 0), Immediate(0)); | 
| +  __ j(not_zero, &call_indirect, Label::kNear); | 
| +  { | 
| +    // Call the API function directly. | 
| +    __ call(rdx); | 
| +  } | 
| +  __ jmp(&done_call, Label::kNear); | 
| +  __ bind(&call_indirect); | 
| +  { | 
| +    // Call the API function indirectly when profiling is on. | 
| +    __ Move(arg_reg_2, rdx); | 
| +    __ Call(ExternalReference::invoke_function_callback(masm->isolate())); | 
| +  } | 
| +  __ bind(&done_call); | 
| + | 
| +  // No more valid handles (the result handle was the last one). Restore | 
| +  // previous handle scope. | 
| +  Label delete_allocated_handles; | 
| +  __ subl(Operand(base_reg, kLevelOffset), Immediate(1)); | 
| +  __ movp(Operand(base_reg, kNextOffset), prev_next_address_reg); | 
| +  __ cmpp(prev_limit_reg, Operand(base_reg, kLimitOffset)); | 
| +  __ j(not_equal, &delete_allocated_handles); | 
| + | 
| +  // Leave the API exit frame. | 
| +  Label leave_exit_frame; | 
| +  __ bind(&leave_exit_frame); | 
| +  __ movp(rax, MemOperand(rbp, (2 + FCA::kReturnValueOffset) * kPointerSize)); | 
| +  __ movp(rsi, MemOperand(rbp, (2 + FCA::kContextSaveIndex) * kPointerSize)); | 
| +  __ movp(rbx, StackSpaceOperand(2)); | 
| +  __ LeaveApiExitFrame(false); | 
| + | 
| +  // Check if the function scheduled an exception. | 
| +  Label promote_scheduled_exception; | 
| +  __ Move(rdi, ExternalReference::scheduled_exception_address(masm->isolate())); | 
| +  __ JumpIfNotRoot(MemOperand(rdi, 0), Heap::kTheHoleValueRootIndex, | 
| +                   &promote_scheduled_exception); | 
| + | 
| +  // Check if the function returned a valid JavaScript value. | 
| +  __ AssertApiCallResult(rax); | 
| + | 
| +  // Drop the arguments and return. | 
| +  __ PopReturnAddressTo(rcx); | 
| +  __ leaq(rsp, MemOperand(rsp, rbx, times_pointer_size, | 
| +                          (FCA::kArgsLength + 1) * kPointerSize)); | 
| +  __ PushReturnAddressFrom(rcx); | 
| +  __ Ret(); | 
| + | 
| +  // Re-throw by promoting a scheduled exception. | 
| +  __ bind(&promote_scheduled_exception); | 
| +  __ TailCallRuntime(Runtime::kPromoteScheduledException); | 
| + | 
| +  // HandleScope limit has changed. Delete allocated extensions. | 
| +  __ bind(&delete_allocated_handles); | 
| +  { | 
| +    __ movp(Operand(base_reg, kLimitOffset), prev_limit_reg); | 
| +    __ LoadAddress(arg_reg_1, | 
| +                   ExternalReference::isolate_address(masm->isolate())); | 
| +    __ Call(ExternalReference::delete_handle_scope_extensions(masm->isolate())); | 
| +  } | 
| +  __ jmp(&leave_exit_frame); | 
| +} | 
| + | 
| +// static | 
| void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { | 
| // ----------- S t a t e ------------- | 
| //  -- rax : the number of arguments (not including the receiver) | 
|  |