diff options
Diffstat (limited to 'deps/v8/src/x87/code-stubs-x87.cc')
-rw-r--r-- | deps/v8/src/x87/code-stubs-x87.cc | 488 |
1 files changed, 409 insertions, 79 deletions
diff --git a/deps/v8/src/x87/code-stubs-x87.cc b/deps/v8/src/x87/code-stubs-x87.cc index 1264dd9b2d..58200bca82 100644 --- a/deps/v8/src/x87/code-stubs-x87.cc +++ b/deps/v8/src/x87/code-stubs-x87.cc @@ -419,6 +419,7 @@ void LoadIndexedStringStub::Generate(MacroAssembler* masm) { void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { + CHECK(!has_new_target()); // The key is in edx and the parameter count is in eax. DCHECK(edx.is(ArgumentsAccessReadDescriptor::index())); DCHECK(eax.is(ArgumentsAccessReadDescriptor::parameter_count())); @@ -485,6 +486,8 @@ void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { // esp[8] : receiver displacement // esp[12] : function + CHECK(!has_new_target()); + // Check if the calling frame is an arguments adaptor frame. Label runtime; __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); @@ -513,6 +516,8 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { // ebx = parameter count (tagged) __ mov(ebx, Operand(esp, 1 * kPointerSize)); + CHECK(!has_new_target()); + // Check if the calling frame is an arguments adaptor frame. // TODO(rossberg): Factor out some of the bits that are shared with the other // Generate* functions. @@ -752,9 +757,15 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { // Patch the arguments.length and the parameters pointer. __ bind(&adaptor_frame); __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); - __ mov(Operand(esp, 1 * kPointerSize), ecx); + + if (has_new_target()) { + // Subtract 1 from smi-tagged arguments count. + __ sub(ecx, Immediate(2)); + } + __ lea(edx, Operand(edx, ecx, times_2, StandardFrameConstants::kCallerSPOffset)); + __ mov(Operand(esp, 1 * kPointerSize), ecx); __ mov(Operand(esp, 2 * kPointerSize), edx); // Try the new space allocation. Start out with computing the size of @@ -829,6 +840,31 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { } +void RestParamAccessStub::GenerateNew(MacroAssembler* masm) { + // esp[0] : return address + // esp[4] : index of rest parameter + // esp[8] : number of parameters + // esp[12] : receiver displacement + + // Check if the calling frame is an arguments adaptor frame. + Label runtime; + __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); + __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); + __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); + __ j(not_equal, &runtime); + + // Patch the arguments.length and the parameters pointer. + __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); + __ mov(Operand(esp, 2 * kPointerSize), ecx); + __ lea(edx, Operand(edx, ecx, times_2, + StandardFrameConstants::kCallerSPOffset)); + __ mov(Operand(esp, 3 * kPointerSize), edx); + + __ bind(&runtime); + __ TailCallRuntime(Runtime::kNewRestParam, 3, 1); +} + + void RegExpExecStub::Generate(MacroAssembler* masm) { // Just jump directly to runtime if native RegExp is not selected at compile // time or if regexp entry in generated code is turned off runtime switch or @@ -1381,7 +1417,7 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) { // If either is a Smi (we know that not both are), then they can only // be equal if the other is a HeapNumber. If so, use the slow case. STATIC_ASSERT(kSmiTag == 0); - DCHECK_EQ(0, Smi::FromInt(0)); + DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0)); __ mov(ecx, Immediate(kSmiTagMask)); __ and_(ecx, eax); __ test(ecx, edx); @@ -1836,6 +1872,13 @@ void CallConstructStub::Generate(MacroAssembler* masm) { __ AssertUndefinedOrAllocationSite(ebx); } + if (IsSuperConstructorCall()) { + __ mov(edx, Operand(esp, eax, times_pointer_size, 2 * kPointerSize)); + } else { + // Pass original constructor to construct stub. + __ mov(edx, edi); + } + // Jump to the function-specific construct stub. Register jmp_reg = ecx; __ mov(jmp_reg, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); @@ -1876,12 +1919,11 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { void CallIC_ArrayStub::Generate(MacroAssembler* masm) { // edi - function // edx - slot id + // ebx - vector Label miss; int argc = arg_count(); ParameterCount actual(argc); - EmitLoadTypeFeedbackVector(masm, ebx); - __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx); __ cmp(edi, ecx); __ j(not_equal, &miss); @@ -1897,6 +1939,7 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) { __ j(not_equal, &miss); __ mov(ebx, ecx); + __ mov(edx, edi); ArrayConstructorStub stub(masm->isolate(), arg_count()); __ TailCallStub(&stub); @@ -1917,6 +1960,7 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) { void CallICStub::Generate(MacroAssembler* masm) { // edi - function // edx - slot id + // ebx - vector Isolate* isolate = masm->isolate(); const int with_types_offset = FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); @@ -1928,13 +1972,31 @@ void CallICStub::Generate(MacroAssembler* masm) { int argc = arg_count(); ParameterCount actual(argc); - EmitLoadTypeFeedbackVector(masm, ebx); - // The checks. First, does edi match the recorded monomorphic target? - __ cmp(edi, FieldOperand(ebx, edx, times_half_pointer_size, + __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size, FixedArray::kHeaderSize)); + + // We don't know that we have a weak cell. We might have a private symbol + // or an AllocationSite, but the memory is safe to examine. + // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to + // FixedArray. + // WeakCell::kValueOffset - contains a JSFunction or Smi(0) + // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not + // computed, meaning that it can't appear to be a pointer. If the low bit is + // 0, then hash is computed, but the 0 bit prevents the field from appearing + // to be a pointer. + STATIC_ASSERT(WeakCell::kSize >= kPointerSize); + STATIC_ASSERT(AllocationSite::kTransitionInfoOffset == + WeakCell::kValueOffset && + WeakCell::kValueOffset == Symbol::kHashFieldSlot); + + __ cmp(edi, FieldOperand(ecx, WeakCell::kValueOffset)); __ j(not_equal, &extra_checks_or_miss); + // The compare above could have been a SMI/SMI comparison. Guard against this + // convincing us that we have a monomorphic JSFunction. + __ JumpIfSmi(edi, &extra_checks_or_miss); + __ bind(&have_js_function); if (CallAsMethod()) { EmitContinueIfStrictOrNative(masm, &cont); @@ -1963,8 +2025,6 @@ void CallICStub::Generate(MacroAssembler* masm) { __ bind(&extra_checks_or_miss); Label uninitialized, miss; - __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size, - FixedArray::kHeaderSize)); __ cmp(ecx, Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); __ j(equal, &slow_start); @@ -2008,15 +2068,18 @@ void CallICStub::Generate(MacroAssembler* masm) { // Update stats. __ add(FieldOperand(ebx, with_types_offset), Immediate(Smi::FromInt(1))); - // Store the function. - __ mov( - FieldOperand(ebx, edx, times_half_pointer_size, FixedArray::kHeaderSize), - edi); + // Store the function. Use a stub since we need a frame for allocation. + // ebx - vector + // edx - slot + // edi - function + { + FrameScope scope(masm, StackFrame::INTERNAL); + CreateWeakCellStub create_stub(isolate); + __ push(edi); + __ CallStub(&create_stub); + __ pop(edi); + } - // Update the write barrier. - __ mov(eax, edi); - __ RecordWriteArray(ebx, eax, edx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, - OMIT_SMI_CHECK); __ jmp(&have_js_function); // We are here because tracing is on or we encountered a MISS case we can't @@ -2041,29 +2104,22 @@ void CallICStub::Generate(MacroAssembler* masm) { void CallICStub::GenerateMiss(MacroAssembler* masm) { - // Get the receiver of the function from the stack; 1 ~ return address. - __ mov(ecx, Operand(esp, (arg_count() + 1) * kPointerSize)); - - { - FrameScope scope(masm, StackFrame::INTERNAL); + FrameScope scope(masm, StackFrame::INTERNAL); - // Push the receiver and the function and feedback info. - __ push(ecx); - __ push(edi); - __ push(ebx); - __ push(edx); + // Push the receiver and the function and feedback info. + __ push(edi); + __ push(ebx); + __ push(edx); - // Call the entry. - IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss - : IC::kCallIC_Customization_Miss; + // Call the entry. + IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss + : IC::kCallIC_Customization_Miss; - ExternalReference miss = ExternalReference(IC_Utility(id), - masm->isolate()); - __ CallExternalReference(miss, 4); + ExternalReference miss = ExternalReference(IC_Utility(id), masm->isolate()); + __ CallExternalReference(miss, 3); - // Move result to edi and exit the internal frame. - __ mov(edi, eax); - } + // Move result to edi and exit the internal frame. + __ mov(edi, eax); } @@ -2079,6 +2135,7 @@ void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { // It is important that the store buffer overflow stubs are generated first. ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); CreateAllocationSiteStub::GenerateAheadOfTime(isolate); + CreateWeakCellStub::GenerateAheadOfTime(isolate); BinaryOpICStub::GenerateAheadOfTime(isolate); BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); } @@ -3437,15 +3494,17 @@ void CompareICStub::GenerateObjects(MacroAssembler* masm) { void CompareICStub::GenerateKnownObjects(MacroAssembler* masm) { Label miss; + Handle<WeakCell> cell = Map::WeakCellForMap(known_map_); __ mov(ecx, edx); __ and_(ecx, eax); __ JumpIfSmi(ecx, &miss, Label::kNear); + __ GetWeakValue(edi, cell); __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); - __ cmp(ecx, known_map_); + __ cmp(ecx, edi); __ j(not_equal, &miss, Label::kNear); - __ cmp(ebx, known_map_); + __ cmp(ebx, edi); __ j(not_equal, &miss, Label::kNear); __ sub(eax, edx); @@ -3994,6 +4053,20 @@ void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) { } +void CallICTrampolineStub::Generate(MacroAssembler* masm) { + EmitLoadTypeFeedbackVector(masm, ebx); + CallICStub stub(isolate(), state()); + __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); +} + + +void CallIC_ArrayTrampolineStub::Generate(MacroAssembler* masm) { + EmitLoadTypeFeedbackVector(masm, ebx); + CallIC_ArrayStub stub(isolate(), state()); + __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); +} + + void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { if (masm->isolate()->function_entry_hook() != NULL) { ProfileEntryHookStub stub(masm->isolate()); @@ -4215,9 +4288,10 @@ void ArrayConstructorStub::GenerateDispatchToArrayStub( void ArrayConstructorStub::Generate(MacroAssembler* masm) { // ----------- S t a t e ------------- - // -- eax : argc (only if argument_count() == ANY) + // -- eax : argc (only if argument_count() is ANY or MORE_THAN_ONE) // -- ebx : AllocationSite or undefined // -- edi : constructor + // -- edx : Original constructor // -- esp[0] : return address // -- esp[4] : last argument // ----------------------------------- @@ -4237,6 +4311,11 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) { __ AssertUndefinedOrAllocationSite(ebx); } + Label subclassing; + + __ cmp(edx, edi); + __ j(not_equal, &subclassing); + Label no_info; // If the feedback vector is the undefined value call an array constructor // that doesn't use AllocationSites. @@ -4252,6 +4331,30 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) { __ bind(&no_info); GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); + + // Subclassing. + __ bind(&subclassing); + __ pop(ecx); // return address. + __ push(edi); + __ push(edx); + + // Adjust argc. + switch (argument_count()) { + case ANY: + case MORE_THAN_ONE: + __ add(eax, Immediate(2)); + break; + case NONE: + __ mov(eax, Immediate(2)); + break; + case ONE: + __ mov(eax, Immediate(3)); + break; + } + + __ push(ecx); + __ JumpToExternalReference( + ExternalReference(Runtime::kArrayConstructorWithSubclassing, isolate())); } @@ -4341,13 +4444,204 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { } -void CallApiFunctionStub::Generate(MacroAssembler* masm) { +// Generates an Operand for saving parameters after PrepareCallApiFunction. +static Operand ApiParameterOperand(int index) { + return Operand(esp, index * kPointerSize); +} + + +// 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. +static void PrepareCallApiFunction(MacroAssembler* masm, int argc) { + __ EnterApiExitFrame(argc); + if (__ emit_debug_code()) { + __ mov(esi, Immediate(bit_cast<int32_t>(kZapValue))); + } +} + + +// Calls an API function. Allocates HandleScope, extracts returned value +// from handle and propagates exceptions. Clobbers ebx, edi and +// caller-save registers. Restores context. On return removes +// stack_space * kPointerSize (GCed). +static void CallApiFunctionAndReturn(MacroAssembler* masm, + Register function_address, + ExternalReference thunk_ref, + Operand thunk_last_arg, int stack_space, + Operand* stack_space_operand, + Operand return_value_operand, + Operand* context_restore_operand) { + Isolate* isolate = masm->isolate(); + + ExternalReference next_address = + ExternalReference::handle_scope_next_address(isolate); + ExternalReference limit_address = + ExternalReference::handle_scope_limit_address(isolate); + ExternalReference level_address = + ExternalReference::handle_scope_level_address(isolate); + + DCHECK(edx.is(function_address)); + // 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)); + + if (FLAG_log_timer_events) { + FrameScope frame(masm, StackFrame::MANUAL); + __ PushSafepointRegisters(); + __ PrepareCallCFunction(1, eax); + __ mov(Operand(esp, 0), + Immediate(ExternalReference::isolate_address(isolate))); + __ CallCFunction(ExternalReference::log_enter_external_function(isolate), + 1); + __ PopSafepointRegisters(); + } + + + Label profiler_disabled; + Label end_profiler_check; + __ mov(eax, Immediate(ExternalReference::is_profiling_address(isolate))); + __ cmpb(Operand(eax, 0), 0); + __ j(zero, &profiler_disabled); + + // Additional parameter is the address of the actual getter function. + __ mov(thunk_last_arg, function_address); + // Call the api function. + __ mov(eax, Immediate(thunk_ref)); + __ call(eax); + __ jmp(&end_profiler_check); + + __ bind(&profiler_disabled); + // Call the api function. + __ call(function_address); + __ bind(&end_profiler_check); + + if (FLAG_log_timer_events) { + FrameScope frame(masm, StackFrame::MANUAL); + __ PushSafepointRegisters(); + __ PrepareCallCFunction(1, eax); + __ mov(Operand(esp, 0), + Immediate(ExternalReference::isolate_address(isolate))); + __ CallCFunction(ExternalReference::log_leave_external_function(isolate), + 1); + __ PopSafepointRegisters(); + } + + Label prologue; + // Load the value from ReturnValue + __ mov(eax, return_value_operand); + + Label promote_scheduled_exception; + Label exception_handled; + Label delete_allocated_handles; + Label leave_exit_frame; + + __ bind(&prologue); + // No more valid handles (the result handle was the last one). Restore + // previous handle scope. + __ mov(Operand::StaticVariable(next_address), ebx); + __ sub(Operand::StaticVariable(level_address), Immediate(1)); + __ Assert(above_equal, kInvalidHandleScopeLevel); + __ cmp(edi, Operand::StaticVariable(limit_address)); + __ j(not_equal, &delete_allocated_handles); + __ bind(&leave_exit_frame); + + // Check if the function scheduled an exception. + ExternalReference scheduled_exception_address = + ExternalReference::scheduled_exception_address(isolate); + __ cmp(Operand::StaticVariable(scheduled_exception_address), + Immediate(isolate->factory()->the_hole_value())); + __ j(not_equal, &promote_scheduled_exception); + __ bind(&exception_handled); + +#if DEBUG + // Check if the function returned a valid JavaScript value. + Label ok; + Register return_value = eax; + Register map = ecx; + + __ JumpIfSmi(return_value, &ok, Label::kNear); + __ mov(map, FieldOperand(return_value, HeapObject::kMapOffset)); + + __ CmpInstanceType(map, LAST_NAME_TYPE); + __ j(below_equal, &ok, Label::kNear); + + __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); + __ j(above_equal, &ok, Label::kNear); + + __ cmp(map, isolate->factory()->heap_number_map()); + __ j(equal, &ok, Label::kNear); + + __ cmp(return_value, isolate->factory()->undefined_value()); + __ j(equal, &ok, Label::kNear); + + __ cmp(return_value, isolate->factory()->true_value()); + __ j(equal, &ok, Label::kNear); + + __ cmp(return_value, isolate->factory()->false_value()); + __ j(equal, &ok, Label::kNear); + + __ cmp(return_value, isolate->factory()->null_value()); + __ j(equal, &ok, Label::kNear); + + __ Abort(kAPICallReturnedInvalidObject); + + __ bind(&ok); +#endif + + bool restore_context = context_restore_operand != NULL; + if (restore_context) { + __ mov(esi, *context_restore_operand); + } + if (stack_space_operand != nullptr) { + __ mov(ebx, *stack_space_operand); + } + __ LeaveApiExitFrame(!restore_context); + if (stack_space_operand != nullptr) { + DCHECK_EQ(0, stack_space); + __ pop(ecx); + __ add(esp, ebx); + __ jmp(ecx); + } else { + __ ret(stack_space * kPointerSize); + } + + __ bind(&promote_scheduled_exception); + { + FrameScope frame(masm, StackFrame::INTERNAL); + __ CallRuntime(Runtime::kPromoteScheduledException, 0); + } + __ jmp(&exception_handled); + + // HandleScope limit has changed. Delete allocated extensions. + ExternalReference delete_extensions = + ExternalReference::delete_handle_scope_extensions(isolate); + __ bind(&delete_allocated_handles); + __ mov(Operand::StaticVariable(limit_address), edi); + __ mov(edi, eax); + __ mov(Operand(esp, 0), + Immediate(ExternalReference::isolate_address(isolate))); + __ mov(eax, Immediate(delete_extensions)); + __ call(eax); + __ mov(eax, edi); + __ jmp(&leave_exit_frame); +} + + +static void CallApiFunctionStubHelper(MacroAssembler* masm, + const ParameterCount& argc, + bool return_first_arg, + bool call_data_undefined) { // ----------- S t a t e ------------- - // -- eax : callee + // -- edi : callee // -- ebx : call_data // -- ecx : holder // -- edx : api_function_address // -- esi : context + // -- eax : number of arguments if argc is a register // -- // -- esp[0] : return address // -- esp[4] : last argument @@ -4356,16 +4650,12 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) { // -- esp[(argc + 1) * 4] : receiver // ----------------------------------- - Register callee = eax; + Register callee = edi; Register call_data = ebx; Register holder = ecx; Register api_function_address = edx; - Register return_address = edi; Register context = esi; - - int argc = this->argc(); - bool is_store = this->is_store(); - bool call_data_undefined = this->call_data_undefined(); + Register return_address = eax; typedef FunctionCallbackArguments FCA; @@ -4378,12 +4668,17 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) { STATIC_ASSERT(FCA::kHolderIndex == 0); STATIC_ASSERT(FCA::kArgsLength == 7); - __ pop(return_address); + DCHECK(argc.is_immediate() || eax.is(argc.reg())); - // context save - __ push(context); - // load context from callee - __ mov(context, FieldOperand(callee, JSFunction::kContextOffset)); + if (argc.is_immediate()) { + __ pop(return_address); + // context save. + __ push(context); + } else { + // pop return address and save context + __ xchg(context, Operand(esp, 0)); + return_address = context; + } // callee __ push(callee); @@ -4394,9 +4689,9 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) { Register scratch = call_data; if (!call_data_undefined) { // return value - __ push(Immediate(isolate()->factory()->undefined_value())); + __ push(Immediate(masm->isolate()->factory()->undefined_value())); // return value default - __ push(Immediate(isolate()->factory()->undefined_value())); + __ push(Immediate(masm->isolate()->factory()->undefined_value())); } else { // return value __ push(scratch); @@ -4404,15 +4699,18 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) { __ push(scratch); } // isolate - __ push(Immediate(reinterpret_cast<int>(isolate()))); + __ push(Immediate(reinterpret_cast<int>(masm->isolate()))); // holder __ push(holder); __ mov(scratch, esp); - // return address + // push return address __ push(return_address); + // load context from callee + __ mov(context, FieldOperand(callee, JSFunction::kContextOffset)); + // 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 @@ -4423,41 +4721,76 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) { // it's not controlled by GC. const int kApiStackSpace = 4; - __ PrepareCallApiFunction(kApiArgc + kApiStackSpace); + PrepareCallApiFunction(masm, kApiArgc + kApiStackSpace); // FunctionCallbackInfo::implicit_args_. __ mov(ApiParameterOperand(2), scratch); - __ add(scratch, Immediate((argc + FCA::kArgsLength - 1) * kPointerSize)); - // FunctionCallbackInfo::values_. - __ mov(ApiParameterOperand(3), scratch); - // FunctionCallbackInfo::length_. - __ Move(ApiParameterOperand(4), Immediate(argc)); - // FunctionCallbackInfo::is_construct_call_. - __ Move(ApiParameterOperand(5), Immediate(0)); + if (argc.is_immediate()) { + __ add(scratch, + Immediate((argc.immediate() + FCA::kArgsLength - 1) * kPointerSize)); + // FunctionCallbackInfo::values_. + __ mov(ApiParameterOperand(3), scratch); + // FunctionCallbackInfo::length_. + __ Move(ApiParameterOperand(4), Immediate(argc.immediate())); + // FunctionCallbackInfo::is_construct_call_. + __ Move(ApiParameterOperand(5), Immediate(0)); + } else { + __ lea(scratch, Operand(scratch, argc.reg(), times_pointer_size, + (FCA::kArgsLength - 1) * kPointerSize)); + // FunctionCallbackInfo::values_. + __ mov(ApiParameterOperand(3), scratch); + // FunctionCallbackInfo::length_. + __ mov(ApiParameterOperand(4), argc.reg()); + // FunctionCallbackInfo::is_construct_call_. + __ lea(argc.reg(), Operand(argc.reg(), times_pointer_size, + (FCA::kArgsLength + 1) * kPointerSize)); + __ mov(ApiParameterOperand(5), argc.reg()); + } // v8::InvocationCallback's argument. __ lea(scratch, ApiParameterOperand(2)); __ mov(ApiParameterOperand(0), scratch); ExternalReference thunk_ref = - ExternalReference::invoke_function_callback(isolate()); + ExternalReference::invoke_function_callback(masm->isolate()); Operand context_restore_operand(ebp, (2 + FCA::kContextSaveIndex) * kPointerSize); // Stores return the first js argument int return_value_offset = 0; - if (is_store) { + if (return_first_arg) { return_value_offset = 2 + FCA::kArgsLength; } else { return_value_offset = 2 + FCA::kReturnValueOffset; } Operand return_value_operand(ebp, return_value_offset * kPointerSize); - __ CallApiFunctionAndReturn(api_function_address, - thunk_ref, - ApiParameterOperand(1), - argc + FCA::kArgsLength + 1, - return_value_operand, - &context_restore_operand); + int stack_space = 0; + Operand is_construct_call_operand = ApiParameterOperand(5); + Operand* stack_space_operand = &is_construct_call_operand; + if (argc.is_immediate()) { + stack_space = argc.immediate() + FCA::kArgsLength + 1; + stack_space_operand = nullptr; + } + CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, + ApiParameterOperand(1), stack_space, + stack_space_operand, return_value_operand, + &context_restore_operand); +} + + +void CallApiFunctionStub::Generate(MacroAssembler* masm) { + bool call_data_undefined = this->call_data_undefined(); + CallApiFunctionStubHelper(masm, ParameterCount(eax), false, + call_data_undefined); +} + + +void CallApiAccessorStub::Generate(MacroAssembler* masm) { + bool is_store = this->is_store(); + int argc = this->argc(); + bool call_data_undefined = this->call_data_undefined(); + CallApiFunctionStubHelper(masm, ParameterCount(argc), is_store, + call_data_undefined); } @@ -4484,7 +4817,7 @@ void CallApiGetterStub::Generate(MacroAssembler* masm) { // load address of name __ lea(scratch, Operand(esp, 1 * kPointerSize)); - __ PrepareCallApiFunction(kApiArgc); + PrepareCallApiFunction(masm, kApiArgc); __ mov(ApiParameterOperand(0), scratch); // name. __ add(scratch, Immediate(kPointerSize)); __ mov(ApiParameterOperand(1), scratch); // arguments pointer. @@ -4492,12 +4825,9 @@ void CallApiGetterStub::Generate(MacroAssembler* masm) { ExternalReference thunk_ref = ExternalReference::invoke_accessor_getter_callback(isolate()); - __ CallApiFunctionAndReturn(api_function_address, - thunk_ref, - ApiParameterOperand(2), - kStackSpace, - Operand(ebp, 7 * kPointerSize), - NULL); + CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, + ApiParameterOperand(2), kStackSpace, nullptr, + Operand(ebp, 7 * kPointerSize), NULL); } |