diff options
Diffstat (limited to 'deps/v8/src/x87/builtins-x87.cc')
-rw-r--r-- | deps/v8/src/x87/builtins-x87.cc | 428 |
1 files changed, 245 insertions, 183 deletions
diff --git a/deps/v8/src/x87/builtins-x87.cc b/deps/v8/src/x87/builtins-x87.cc index 55e648cab1..9acafd2ff8 100644 --- a/deps/v8/src/x87/builtins-x87.cc +++ b/deps/v8/src/x87/builtins-x87.cc @@ -2,14 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" - #if V8_TARGET_ARCH_X87 #include "src/code-factory.h" #include "src/codegen.h" #include "src/deoptimizer.h" -#include "src/full-codegen.h" +#include "src/full-codegen/full-codegen.h" +#include "src/x87/frames-x87.h" namespace v8 { namespace internal { @@ -100,45 +99,8 @@ void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) { } -static void Generate_Runtime_NewObject(MacroAssembler* masm, - bool create_memento, - Register original_constructor, - Label* count_incremented, - Label* allocated) { - int offset = 0; - if (create_memento) { - // Get the cell or allocation site. - __ mov(edi, Operand(esp, kPointerSize * 2)); - __ push(edi); - offset = kPointerSize; - } - - // Must restore esi (context) and edi (constructor) before calling - // runtime. - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); - __ mov(edi, Operand(esp, offset)); - __ push(edi); - __ push(original_constructor); - if (create_memento) { - __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3); - } else { - __ CallRuntime(Runtime::kNewObject, 2); - } - __ mov(ebx, eax); // store result in ebx - - // Runtime_NewObjectWithAllocationSite increments allocation count. - // Skip the increment. - if (create_memento) { - __ jmp(count_incremented); - } else { - __ jmp(allocated); - } -} - - static void Generate_JSConstructStubHelper(MacroAssembler* masm, bool is_api_function, - bool use_new_target, bool create_memento) { // ----------- S t a t e ------------- // -- eax: number of arguments @@ -154,40 +116,27 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, { FrameScope scope(masm, StackFrame::CONSTRUCT); - if (create_memento) { - __ AssertUndefinedOrAllocationSite(ebx); - __ push(ebx); - } - // Preserve the incoming parameters on the stack. + __ AssertUndefinedOrAllocationSite(ebx); + __ push(ebx); __ SmiTag(eax); __ push(eax); __ push(edi); - if (use_new_target) { - __ push(edx); - } - - __ cmp(edx, edi); - Label normal_new; - Label count_incremented; - Label allocated; - __ j(equal, &normal_new); - - // Original constructor and function are different. - Generate_Runtime_NewObject(masm, create_memento, edx, &count_incremented, - &allocated); - __ bind(&normal_new); + __ push(edx); // Try to allocate the object without transitioning into C code. If any of // the preconditions is not met, the code bails out to the runtime call. - Label rt_call; + Label rt_call, allocated; if (FLAG_inline_new) { - Label undo_allocation; ExternalReference debug_step_in_fp = ExternalReference::debug_step_in_fp_address(masm->isolate()); __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0)); __ j(not_equal, &rt_call); + // Fall back to runtime if the original constructor and function differ. + __ cmp(edx, edi); + __ j(not_equal, &rt_call); + // Verified that the constructor is a JSFunction. // Load the initial map and verify that it is in fact a map. // edi: constructor @@ -224,12 +173,14 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, __ j(not_equal, &allocate); __ push(eax); + __ push(edx); __ push(edi); __ push(edi); // constructor __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); __ pop(edi); + __ pop(edx); __ pop(eax); __ mov(esi, Map::kSlackTrackingCounterEnd - 1); @@ -272,8 +223,12 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, __ j(less, &no_inobject_slack_tracking); // Allocate object with a slack. - __ movzx_b(esi, - FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset)); + __ movzx_b( + esi, + FieldOperand( + eax, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset)); + __ movzx_b(eax, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset)); + __ sub(esi, eax); __ lea(esi, Operand(ebx, esi, times_pointer_size, JSObject::kHeaderSize)); // esi: offset of first field after pre-allocated fields @@ -298,7 +253,8 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, __ mov(Operand(esi, AllocationMemento::kMapOffset), factory->allocation_memento_map()); // Get the cell or undefined. - __ mov(edx, Operand(esp, kPointerSize*2)); + __ mov(edx, Operand(esp, 3 * kPointerSize)); + __ AssertUndefinedOrAllocationSite(edx); __ mov(Operand(esi, AllocationMemento::kAllocationSiteOffset), edx); } else { @@ -306,95 +262,52 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, } // Add the object tag to make the JSObject real, so that we can continue - // and jump into the continuation code at any time from now on. Any - // failures need to undo the allocation, so that the heap is in a - // consistent state and verifiable. - // eax: initial map - // ebx: JSObject - // edi: start of next object + // and jump into the continuation code at any time from now on. + // ebx: JSObject (untagged) __ or_(ebx, Immediate(kHeapObjectTag)); - // Check if a non-empty properties array is needed. - // Allocate and initialize a FixedArray if it is. - // eax: initial map - // ebx: JSObject - // edi: start of next object - // Calculate the total number of properties described by the map. - __ movzx_b(edx, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset)); - __ movzx_b(ecx, - FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset)); - __ add(edx, ecx); - // Calculate unused properties past the end of the in-object properties. - __ movzx_b(ecx, FieldOperand(eax, Map::kInObjectPropertiesOffset)); - __ sub(edx, ecx); - // Done if no extra properties are to be allocated. - __ j(zero, &allocated); - __ Assert(positive, kPropertyAllocationCountFailed); - - // Scale the number of elements by pointer size and add the header for - // FixedArrays to the start of the next object calculation from above. - // ebx: JSObject - // edi: start of next object (will be start of FixedArray) - // edx: number of elements in properties array - __ Allocate(FixedArray::kHeaderSize, - times_pointer_size, - edx, - REGISTER_VALUE_IS_INT32, - edi, - ecx, - no_reg, - &undo_allocation, - RESULT_CONTAINS_TOP); - - // Initialize the FixedArray. - // ebx: JSObject - // edi: FixedArray - // edx: number of elements - // ecx: start of next object - __ mov(eax, factory->fixed_array_map()); - __ mov(Operand(edi, FixedArray::kMapOffset), eax); // setup the map - __ SmiTag(edx); - __ mov(Operand(edi, FixedArray::kLengthOffset), edx); // and length - - // Initialize the fields to undefined. - // ebx: JSObject - // edi: FixedArray - // ecx: start of next object - __ mov(edx, factory->undefined_value()); - __ lea(eax, Operand(edi, FixedArray::kHeaderSize)); - __ InitializeFieldsWithFiller(eax, ecx, edx); - - // Store the initialized FixedArray into the properties field of - // the JSObject - // ebx: JSObject - // edi: FixedArray - __ or_(edi, Immediate(kHeapObjectTag)); // add the heap tag - __ mov(FieldOperand(ebx, JSObject::kPropertiesOffset), edi); - - // Continue with JSObject being successfully allocated - // ebx: JSObject + // ebx: JSObject (tagged) __ jmp(&allocated); - - // Undo the setting of the new top so that the heap is verifiable. For - // example, the map's unused properties potentially do not match the - // allocated objects unused properties. - // ebx: JSObject (previous new top) - __ bind(&undo_allocation); - __ UndoAllocationInNewSpace(ebx); } // Allocate the new receiver object using the runtime call. + // edx: original constructor __ bind(&rt_call); - Generate_Runtime_NewObject(masm, create_memento, edi, &count_incremented, - &allocated); + int offset = kPointerSize; + if (create_memento) { + // Get the cell or allocation site. + __ mov(edi, Operand(esp, kPointerSize * 3)); + __ push(edi); // argument 1: allocation site + offset += kPointerSize; + } + + // Must restore esi (context) and edi (constructor) before calling + // runtime. + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); + __ mov(edi, Operand(esp, offset)); + __ push(edi); // argument 2/1: constructor function + __ push(edx); // argument 3/2: original constructor + if (create_memento) { + __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3); + } else { + __ CallRuntime(Runtime::kNewObject, 2); + } + __ mov(ebx, eax); // store result in ebx + + // Runtime_NewObjectWithAllocationSite increments allocation count. + // Skip the increment. + Label count_incremented; + if (create_memento) { + __ jmp(&count_incremented); + } + // New object allocated. // ebx: newly allocated object __ bind(&allocated); if (create_memento) { - int offset = (use_new_target ? 3 : 2) * kPointerSize; - __ mov(ecx, Operand(esp, offset)); + __ mov(ecx, Operand(esp, 3 * kPointerSize)); __ cmp(ecx, masm->isolate()->factory()->undefined_value()); __ j(equal, &count_incremented); // ecx is an AllocationSite. We are creating a memento from it, so we @@ -405,9 +318,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, } // Restore the parameters. - if (use_new_target) { - __ pop(edx); // new.target - } + __ pop(edx); // new.target __ pop(edi); // Constructor function. // Retrieve smi-tagged arguments count from the stack. @@ -416,9 +327,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, // Push new.target onto the construct frame. This is stored just below the // receiver on the stack. - if (use_new_target) { - __ push(edx); - } + __ push(edx); // Push the allocated receiver to the stack. We need two copies // because we may have to return the original one and the calling @@ -452,9 +361,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, } // Store offset of return address for deoptimizer. - // TODO(arv): Remove the "!use_new_target" before supporting optimization - // of functions that reference new.target - if (!is_api_function && !use_new_target) { + if (!is_api_function) { masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); } @@ -482,8 +389,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, // Restore the arguments count and leave the construct frame. The arguments // count is stored below the reciever and the new.target. __ bind(&exit); - int offset = (use_new_target ? 2 : 1) * kPointerSize; - __ mov(ebx, Operand(esp, offset)); + __ mov(ebx, Operand(esp, 2 * kPointerSize)); // Leave construct frame. } @@ -499,17 +405,12 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { - Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new); + Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); } void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { - Generate_JSConstructStubHelper(masm, true, false, false); -} - - -void Builtins::Generate_JSConstructStubNewTarget(MacroAssembler* masm) { - Generate_JSConstructStubHelper(masm, false, true, FLAG_pretenuring_call_new); + Generate_JSConstructStubHelper(masm, true, false); } @@ -521,12 +422,13 @@ void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { // -- edx: original constructor // ----------------------------------- - // TODO(dslomov): support pretenuring - CHECK(!FLAG_pretenuring_call_new); - { FrameScope frame_scope(masm, StackFrame::CONSTRUCT); + // Preserve allocation site. + __ AssertUndefinedOrAllocationSite(ebx); + __ push(ebx); + // Preserve actual arguments count. __ SmiTag(eax); __ push(eax); @@ -705,6 +607,156 @@ void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { } +// Generate code for entering a JS function with the interpreter. +// On entry to the function the receiver and arguments have been pushed on the +// stack left to right. The actual argument count matches the formal parameter +// count expected by the function. +// +// The live registers are: +// o edi: the JS function object being called +// o esi: our context +// o ebp: the caller's frame pointer +// o esp: stack pointer (pointing to return address) +// +// The function builds a JS frame. Please see JavaScriptFrameConstants in +// frames-ia32.h for its layout. +// TODO(rmcilroy): We will need to include the current bytecode pointer in the +// frame. +void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { + // Open a frame scope to indicate that there is a frame on the stack. The + // MANUAL indicates that the scope shouldn't actually generate code to set up + // the frame (that is done below). + FrameScope frame_scope(masm, StackFrame::MANUAL); + __ push(ebp); // Caller's frame pointer. + __ mov(ebp, esp); + __ push(esi); // Callee's context. + __ push(edi); // Callee's JS function. + + // Get the bytecode array from the function object and load the pointer to the + // first entry into edi (InterpreterBytecodeRegister). + __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); + __ mov(kInterpreterBytecodeArrayRegister, + FieldOperand(eax, SharedFunctionInfo::kFunctionDataOffset)); + + if (FLAG_debug_code) { + // Check function data field is actually a BytecodeArray object. + __ AssertNotSmi(kInterpreterBytecodeArrayRegister); + __ CmpObjectType(kInterpreterBytecodeArrayRegister, BYTECODE_ARRAY_TYPE, + eax); + __ Assert(equal, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry); + } + + // Allocate the local and temporary register file on the stack. + { + // Load frame size from the BytecodeArray object. + __ mov(ebx, FieldOperand(kInterpreterBytecodeArrayRegister, + BytecodeArray::kFrameSizeOffset)); + + // Do a stack check to ensure we don't go over the limit. + Label ok; + __ mov(ecx, esp); + __ sub(ecx, ebx); + ExternalReference stack_limit = + ExternalReference::address_of_real_stack_limit(masm->isolate()); + __ cmp(ecx, Operand::StaticVariable(stack_limit)); + __ j(above_equal, &ok); + __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); + __ bind(&ok); + + // If ok, push undefined as the initial value for all register file entries. + Label loop_header; + Label loop_check; + __ mov(eax, Immediate(masm->isolate()->factory()->undefined_value())); + __ jmp(&loop_check); + __ bind(&loop_header); + // TODO(rmcilroy): Consider doing more than one push per loop iteration. + __ push(eax); + // Continue loop if not done. + __ bind(&loop_check); + __ sub(ebx, Immediate(kPointerSize)); + __ j(greater_equal, &loop_header); + } + + // TODO(rmcilroy): List of things not currently dealt with here but done in + // fullcodegen's prologue: + // - Support profiler (specifically profiling_counter). + // - Call ProfileEntryHookStub when isolate has a function_entry_hook. + // - Allow simulator stop operations if FLAG_stop_at is set. + // - Deal with sloppy mode functions which need to replace the + // receiver with the global proxy when called as functions (without an + // explicit receiver object). + // - Code aging of the BytecodeArray object. + // - Supporting FLAG_trace. + // + // The following items are also not done here, and will probably be done using + // explicit bytecodes instead: + // - Allocating a new local context if applicable. + // - Setting up a local binding to the this function, which is used in + // derived constructors with super calls. + // - Setting new.target if required. + // - Dealing with REST parameters (only if + // https://codereview.chromium.org/1235153006 doesn't land by then). + // - Dealing with argument objects. + + // Perform stack guard check. + { + Label ok; + ExternalReference stack_limit = + ExternalReference::address_of_stack_limit(masm->isolate()); + __ cmp(esp, Operand::StaticVariable(stack_limit)); + __ j(above_equal, &ok); + __ CallRuntime(Runtime::kStackGuard, 0); + __ bind(&ok); + } + + // Load accumulator, register file, bytecode offset, dispatch table into + // registers. + __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex); + __ mov(kInterpreterRegisterFileRegister, ebp); + __ sub( + kInterpreterRegisterFileRegister, + Immediate(kPointerSize + StandardFrameConstants::kFixedFrameSizeFromFp)); + __ mov(kInterpreterBytecodeOffsetRegister, + Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag)); + // Since the dispatch table root might be set after builtins are generated, + // load directly from the roots table. + __ LoadRoot(kInterpreterDispatchTableRegister, + Heap::kInterpreterTableRootIndex); + __ add(kInterpreterDispatchTableRegister, + Immediate(FixedArray::kHeaderSize - kHeapObjectTag)); + + // TODO(rmcilroy) Push our context as a stack located parameter of the + // bytecode handler. + + // Dispatch to the first bytecode handler for the function. + __ movzx_b(esi, Operand(kInterpreterBytecodeArrayRegister, + kInterpreterBytecodeOffsetRegister, times_1, 0)); + __ mov(esi, Operand(kInterpreterDispatchTableRegister, esi, + times_pointer_size, 0)); + // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging + // and header removal. + __ add(esi, Immediate(Code::kHeaderSize - kHeapObjectTag)); + __ call(esi); +} + + +void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) { + // TODO(rmcilroy): List of things not currently dealt with here but done in + // fullcodegen's EmitReturnSequence. + // - Supporting FLAG_trace for Runtime::TraceExit. + // - Support profiler (specifically decrementing profiling_counter + // appropriately and calling out to HandleInterrupts if necessary). + + // The return value is in accumulator, which is already in rax. + + // Leave the frame (also dropping the register file). + __ leave(); + // Return droping receiver + arguments. + // TODO(rmcilroy): Get number of arguments from BytecodeArray. + __ Ret(1 * kPointerSize, ecx); +} + + void Builtins::Generate_CompileLazy(MacroAssembler* masm) { CallRuntimePassFunction(masm, Runtime::kCompileLazy); GenerateTailCallToReturnedCode(masm); @@ -961,8 +1013,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { __ SmiTag(eax); __ push(eax); - __ push(ebx); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ mov(eax, ebx); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ mov(ebx, eax); __ Move(edx, Immediate(0)); // restore @@ -1056,6 +1109,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { static void Generate_PushAppliedArguments(MacroAssembler* masm, + const int vectorOffset, const int argumentsOffset, const int indexOffset, const int limitOffset) { @@ -1071,12 +1125,9 @@ static void Generate_PushAppliedArguments(MacroAssembler* masm, __ mov(receiver, Operand(ebp, argumentsOffset)); // load arguments // Use inline caching to speed up access to arguments. - FeedbackVectorSpec spec(0, Code::KEYED_LOAD_IC); - Handle<TypeFeedbackVector> feedback_vector = - masm->isolate()->factory()->NewTypeFeedbackVector(&spec); - int index = feedback_vector->GetIndex(FeedbackVectorICSlot(0)); - __ mov(slot, Immediate(Smi::FromInt(index))); - __ mov(vector, Immediate(feedback_vector)); + int slot_index = TypeFeedbackVector::PushAppliedArgumentsIndex(); + __ mov(slot, Immediate(Smi::FromInt(slot_index))); + __ mov(vector, Operand(ebp, vectorOffset)); Handle<Code> ic = KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode(); __ call(ic, RelocInfo::CODE_TARGET); @@ -1124,6 +1175,13 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; static const int kReceiverOffset = kArgumentsOffset + kPointerSize; static const int kFunctionOffset = kReceiverOffset + kPointerSize; + static const int kVectorOffset = + InternalFrameConstants::kCodeOffset - 1 * kPointerSize; + + // Push the vector. + __ mov(edi, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); + __ mov(edi, FieldOperand(edi, SharedFunctionInfo::kFeedbackVectorOffset)); + __ push(edi); __ push(Operand(ebp, kFunctionOffset)); // push this __ push(Operand(ebp, kArgumentsOffset)); // push arguments @@ -1136,8 +1194,7 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { Generate_CheckStackOverflow(masm, kFunctionOffset, kEaxIsSmiTagged); // Push current index and limit. - const int kLimitOffset = - StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; + const int kLimitOffset = kVectorOffset - 1 * kPointerSize; const int kIndexOffset = kLimitOffset - 1 * kPointerSize; __ push(eax); // limit __ push(Immediate(0)); // index @@ -1182,8 +1239,9 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { __ j(above_equal, &push_receiver); __ bind(&call_to_object); - __ push(ebx); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ mov(eax, ebx); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ mov(ebx, eax); __ jmp(&push_receiver); @@ -1197,8 +1255,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { __ push(ebx); // Loop over the arguments array, pushing each value to the stack - Generate_PushAppliedArguments( - masm, kArgumentsOffset, kIndexOffset, kLimitOffset); + Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset, + kIndexOffset, kLimitOffset); // Call the function. Label call_proxy; @@ -1247,6 +1305,13 @@ static void Generate_ConstructHelper(MacroAssembler* masm) { static const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize; static const int kArgumentsOffset = kNewTargetOffset + kPointerSize; static const int kFunctionOffset = kArgumentsOffset + kPointerSize; + static const int kVectorOffset = + InternalFrameConstants::kCodeOffset - 1 * kPointerSize; + + // Push the vector. + __ mov(edi, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); + __ mov(edi, FieldOperand(edi, SharedFunctionInfo::kFeedbackVectorOffset)); + __ push(edi); // If newTarget is not supplied, set it to constructor Label validate_arguments; @@ -1266,29 +1331,26 @@ static void Generate_ConstructHelper(MacroAssembler* masm) { Generate_CheckStackOverflow(masm, kFunctionOffset, kEaxIsSmiTagged); // Push current index and limit. - const int kLimitOffset = - StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; + const int kLimitOffset = kVectorOffset - 1 * kPointerSize; const int kIndexOffset = kLimitOffset - 1 * kPointerSize; __ Push(eax); // limit __ push(Immediate(0)); // index - // Push newTarget and callee functions - __ push(Operand(ebp, kNewTargetOffset)); + // Push the constructor function as callee. __ push(Operand(ebp, kFunctionOffset)); // Loop over the arguments array, pushing each value to the stack - Generate_PushAppliedArguments( - masm, kArgumentsOffset, kIndexOffset, kLimitOffset); + Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset, + kIndexOffset, kLimitOffset); // Use undefined feedback vector __ LoadRoot(ebx, Heap::kUndefinedValueRootIndex); __ mov(edi, Operand(ebp, kFunctionOffset)); + __ mov(ecx, Operand(ebp, kNewTargetOffset)); // Call the function. CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL); __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); - __ Drop(1); - // Leave internal frame. } // remove this, target, arguments, and newTarget |