| Index: src/builtins/ia32/builtins-ia32.cc | 
| diff --git a/src/builtins/ia32/builtins-ia32.cc b/src/builtins/ia32/builtins-ia32.cc | 
| index c907fa8dfe9e941688f912f5bab84e3313ed24fb..9390e312492ff89e8132ab5046de949d9325fb6c 100644 | 
| --- a/src/builtins/ia32/builtins-ia32.cc | 
| +++ b/src/builtins/ia32/builtins-ia32.cc | 
| @@ -4,6 +4,7 @@ | 
|  | 
| #if V8_TARGET_ARCH_IA32 | 
|  | 
| +#include "src/api-arguments.h" | 
| #include "src/code-factory.h" | 
| #include "src/codegen.h" | 
| #include "src/deoptimizer.h" | 
| @@ -2875,6 +2876,167 @@ void Builtins::Generate_CallWithSpread(MacroAssembler* masm) { | 
| RelocInfo::CODE_TARGET); | 
| } | 
|  | 
| +namespace { | 
| + | 
| +// Prepares stack to put arguments (aligns and so on). Reserves | 
| +// space for return value if needed (assumes the return value is a handle). | 
| +// Arguments must be stored in ApiParameterOperand(0), ApiParameterOperand(1) | 
| +// etc. Saves context (esi). If space was reserved for return value then | 
| +// stores the pointer to the reserved slot into esi. | 
| +void PrepareCallApiFunction(MacroAssembler* masm, int argc) { | 
| +  __ EnterApiExitFrame(argc); | 
| +  if (__ emit_debug_code()) { | 
| +    __ mov(esi, Immediate(bit_cast<int32_t>(kZapValue))); | 
| +  } | 
| +} | 
| + | 
| +// Generates an Operand for saving parameters after PrepareCallApiFunction. | 
| +Operand ApiParameterOperand(int index) { | 
| +  return MemOperand(esp, index * kPointerSize); | 
| +} | 
| + | 
| +}  // namespace | 
| + | 
| +// static | 
| +void Builtins::Generate_CallFunctionCallback(MacroAssembler* masm) { | 
| +  // ----------- S t a t e ------------- | 
| +  //  -- eax                : the number of arguments (not incl. the receiver) | 
| +  //  -- edx                : api function address | 
| +  //  -- esp[0]             : return address | 
| +  //  -- esp[4]             : holder | 
| +  //  -- esp[8]             : isolate | 
| +  //  -- esp[12]            : return value default | 
| +  //  -- esp[16]            : return value | 
| +  //  -- esp[20]            : call data | 
| +  //  -- esp[24]            : target | 
| +  //  -- esp[28]            : context save | 
| +  //  -- esp[32]            : new.target | 
| +  //  -- esp[36]            : last argument | 
| +  //  -- esp[32 + argc * 4] : first argument | 
| +  //  -- esp[36 + argc * 4] : 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. | 
| +  __ lea(ebx, MemOperand(esp, kPCOnStackSize)); | 
| + | 
| +  // API function gets reference to the v8::Arguments. If CPU profiler | 
| +  // is enabled wrapper function will be called and we need to pass | 
| +  // address of the callback as additional parameter, always allocate | 
| +  // space for it. | 
| +  const int kApiArgc = 1 + 1; | 
| + | 
| +  // Allocate the v8::FunctionCallbackInfo structure in the arguments' space | 
| +  // since it's not controlled by the GC. | 
| +  const int kApiStackSpace = 3; | 
| +  PrepareCallApiFunction(masm, kApiArgc + kApiStackSpace); | 
| +  // Initialize FunctionCallbackInfo::implicit_args_. | 
| +  __ mov(ApiParameterOperand(2), ebx); | 
| +  // Initialize FunctionCallbackInfo::values_. | 
| +  __ lea(ebx, MemOperand(ebx, eax, times_pointer_size, | 
| +                         (FCA::kArgsLength - 1) * kPointerSize)); | 
| +  __ mov(ApiParameterOperand(3), ebx); | 
| +  // Initialize FunctionCallbackInfo::length_. | 
| +  __ mov(ApiParameterOperand(4), eax); | 
| + | 
| +  // Load first argument with pointer to FunctionCallbackInfo. | 
| +  __ lea(ebx, ApiParameterOperand(2)); | 
| +  __ mov(ApiParameterOperand(0), ebx); | 
| + | 
| +  ExternalReference const next_address = | 
| +      ExternalReference::handle_scope_next_address(masm->isolate()); | 
| +  ExternalReference const limit_address = | 
| +      ExternalReference::handle_scope_limit_address(masm->isolate()); | 
| +  ExternalReference const level_address = | 
| +      ExternalReference::handle_scope_level_address(masm->isolate()); | 
| + | 
| +  // Allocate HandleScope in callee-save registers. | 
| +  __ mov(ebx, Operand::StaticVariable(next_address)); | 
| +  __ mov(edi, Operand::StaticVariable(limit_address)); | 
| +  __ add(Operand::StaticVariable(level_address), 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; | 
| +  __ cmpb(Operand::StaticVariable( | 
| +              ExternalReference::is_profiling_address(masm->isolate())), | 
| +          Immediate(0)); | 
| +  __ j(not_zero, &call_indirect, Label::kNear); | 
| +  { | 
| +    // Call the API function directly. | 
| +    __ call(edx); | 
| +  } | 
| +  __ jmp(&done_call, Label::kNear); | 
| +  __ bind(&call_indirect); | 
| +  { | 
| +    // Call the API function indirectly when profiling is on. | 
| +    __ mov(ApiParameterOperand(1), edx); | 
| +    __ mov(eax, Immediate(ExternalReference::invoke_function_callback( | 
| +                    masm->isolate()))); | 
| +    __ call(eax); | 
| +  } | 
| +  __ bind(&done_call); | 
| + | 
| +  // No more valid handles (the result handle was the last one). Restore | 
| +  // previous handle scope. | 
| +  Label delete_allocated_handles; | 
| +  __ mov(Operand::StaticVariable(next_address), ebx); | 
| +  __ sub(Operand::StaticVariable(level_address), Immediate(1)); | 
| +  __ cmp(edi, Operand::StaticVariable(limit_address)); | 
| +  __ j(not_equal, &delete_allocated_handles); | 
| + | 
| +  // Leave the API exit frame. | 
| +  Label leave_exit_frame; | 
| +  __ bind(&leave_exit_frame); | 
| +  __ mov(eax, MemOperand(ebp, (2 + FCA::kReturnValueOffset) * kPointerSize)); | 
| +  __ mov(esi, MemOperand(ebp, (2 + FCA::kContextSaveIndex) * kPointerSize)); | 
| +  __ mov(ebx, ApiParameterOperand(4)); | 
| +  __ LeaveApiExitFrame(false); | 
| + | 
| +  // Check if the function scheduled an exception. | 
| +  Label promote_scheduled_exception; | 
| +  __ cmp(Operand::StaticVariable( | 
| +             ExternalReference::scheduled_exception_address(masm->isolate())), | 
| +         Immediate(masm->isolate()->factory()->the_hole_value())); | 
| +  __ j(not_equal, &promote_scheduled_exception); | 
| + | 
| +  // Check if the function returned a valid JavaScript value. | 
| +  __ AssertApiCallResult(eax); | 
| + | 
| +  // Drop the arguments and return. | 
| +  __ PopReturnAddressTo(ecx); | 
| +  __ lea(esp, MemOperand(esp, ebx, times_pointer_size, | 
| +                         (FCA::kArgsLength + 1) * kPointerSize)); | 
| +  __ PushReturnAddressFrom(ecx); | 
| +  __ 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); | 
| +  { | 
| +    __ mov(Operand::StaticVariable(limit_address), edi); | 
| +    __ mov(Operand(esp, 0), | 
| +           Immediate(ExternalReference::isolate_address(masm->isolate()))); | 
| +    __ mov(eax, Immediate(ExternalReference::delete_handle_scope_extensions( | 
| +                    masm->isolate()))); | 
| +    __ call(eax); | 
| +  } | 
| +  __ jmp(&leave_exit_frame); | 
| +} | 
| + | 
| // static | 
| void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { | 
| // ----------- S t a t e ------------- | 
|  |