diff options
Diffstat (limited to 'deps/v8/src/mips/builtins-mips.cc')
-rw-r--r-- | deps/v8/src/mips/builtins-mips.cc | 453 |
1 files changed, 240 insertions, 213 deletions
diff --git a/deps/v8/src/mips/builtins-mips.cc b/deps/v8/src/mips/builtins-mips.cc index b5a67b47dc..b9607e05c4 100644 --- a/deps/v8/src/mips/builtins-mips.cc +++ b/deps/v8/src/mips/builtins-mips.cc @@ -2,16 +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_MIPS #include "src/codegen.h" -#include "src/debug.h" +#include "src/debug/debug.h" #include "src/deoptimizer.h" -#include "src/full-codegen.h" +#include "src/full-codegen/full-codegen.h" +#include "src/interpreter/bytecodes.h" #include "src/runtime/runtime.h" @@ -316,39 +313,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) { - if (create_memento) { - // Get the cell or allocation site. - __ lw(a2, MemOperand(sp, 2 * kPointerSize)); - __ push(a2); - } - - __ push(a1); // argument for Runtime_NewObject - __ push(original_constructor); // original constructor - if (create_memento) { - __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3); - } else { - __ CallRuntime(Runtime::kNewObject, 2); - } - __ mov(t4, v0); - - // 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 ------------- // -- a0 : number of arguments @@ -364,53 +330,33 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, Isolate* isolate = masm->isolate(); - // ----------- S t a t e ------------- - // -- a0 : number of arguments - // -- a1 : constructor function - // -- ra : return address - // -- sp[...]: constructor arguments - // ----------------------------------- - // Enter a construct frame. { FrameScope scope(masm, StackFrame::CONSTRUCT); - if (create_memento) { - __ AssertUndefinedOrAllocationSite(a2, t0); - __ push(a2); - } - // Preserve the incoming parameters on the stack. + __ AssertUndefinedOrAllocationSite(a2, t0); __ SmiTag(a0); - if (use_new_target) { - __ Push(a0, a1, a3); - } else { - __ Push(a0, a1); - } - - Label rt_call, allocated, normal_new, count_incremented; - __ Branch(&normal_new, eq, a1, Operand(a3)); - - // Original constructor and function are different. - Generate_Runtime_NewObject(masm, create_memento, a3, &count_incremented, - &allocated); - __ bind(&normal_new); + __ Push(a2, a0, a1, a3); // 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, allocated; if (FLAG_inline_new) { - Label undo_allocation; ExternalReference debug_step_in_fp = ExternalReference::debug_step_in_fp_address(isolate); __ li(a2, Operand(debug_step_in_fp)); __ lw(a2, MemOperand(a2)); __ Branch(&rt_call, ne, a2, Operand(zero_reg)); + // Fall back to runtime if the original constructor and function differ. + __ Branch(&rt_call, ne, a1, Operand(a3)); + // Load the initial map and verify that it is in fact a map. // a1: constructor function __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset)); __ JumpIfSmi(a2, &rt_call); - __ GetObjectType(a2, a3, t4); + __ GetObjectType(a2, t5, t4); __ Branch(&rt_call, ne, t4, Operand(MAP_TYPE)); // Check that the constructor is not constructing a JSFunction (see @@ -418,8 +364,8 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, // initial map's instance type would be JS_FUNCTION_TYPE. // a1: constructor function // a2: initial map - __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset)); - __ Branch(&rt_call, eq, a3, Operand(JS_FUNCTION_TYPE)); + __ lbu(t5, FieldMemOperand(a2, Map::kInstanceTypeOffset)); + __ Branch(&rt_call, eq, t5, Operand(JS_FUNCTION_TYPE)); if (!is_api_function) { Label allocate; @@ -446,12 +392,13 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, // Now allocate the JSObject on the heap. // a1: constructor function // a2: initial map + Label rt_call_reload_new_target; __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset)); if (create_memento) { __ Addu(a3, a3, Operand(AllocationMemento::kSize / kPointerSize)); } - __ Allocate(a3, t4, t5, t6, &rt_call, SIZE_IN_WORDS); + __ Allocate(a3, t4, t5, t6, &rt_call_reload_new_target, SIZE_IN_WORDS); // Allocated the JSObject, now initialize the fields. Map is set to // initial map and properties and elements are set to empty fixed array. @@ -489,7 +436,12 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, Operand(Map::kSlackTrackingCounterEnd)); // Allocate object with a slack. - __ lbu(a0, FieldMemOperand(a2, Map::kPreAllocatedPropertyFieldsOffset)); + __ lbu( + a0, + FieldMemOperand( + a2, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset)); + __ lbu(a2, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset)); + __ subu(a0, a0, a2); __ sll(at, a0, kPointerSizeLog2); __ addu(a0, t5, at); // a0: offset of first field after pre-allocated fields @@ -520,7 +472,8 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, __ sw(t7, MemOperand(t5)); __ Addu(t5, t5, kPointerSize); // Load the AllocationSite. - __ lw(t7, MemOperand(sp, 2 * kPointerSize)); + __ lw(t7, MemOperand(sp, 3 * kPointerSize)); + __ AssertUndefinedOrAllocationSite(a2, t0); DCHECK_EQ(1 * kPointerSize, AllocationMemento::kAllocationSiteOffset); __ sw(t7, MemOperand(t5)); __ Addu(t5, t5, kPointerSize); @@ -531,110 +484,49 @@ 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. + // and jump into the continuation code at any time from now on. __ Addu(t4, t4, Operand(kHeapObjectTag)); - // Check if a non-empty properties array is needed. Continue with - // allocated object if not; allocate and initialize a FixedArray if yes. - // a1: constructor function - // t4: JSObject - // t5: start of next object (not tagged) - __ lbu(a3, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset)); - // The field instance sizes contains both pre-allocated property fields - // and in-object properties. - __ lbu(t6, FieldMemOperand(a2, Map::kPreAllocatedPropertyFieldsOffset)); - __ Addu(a3, a3, Operand(t6)); - __ lbu(t6, FieldMemOperand(a2, Map::kInObjectPropertiesOffset)); - __ subu(a3, a3, t6); - - // Done if no extra properties are to be allocated. - __ Branch(&allocated, eq, a3, Operand(zero_reg)); - __ Assert(greater_equal, kPropertyAllocationCountFailed, - a3, Operand(zero_reg)); - - // Scale the number of elements by pointer size and add the header for - // FixedArrays to the start of the next object calculation from above. - // a1: constructor - // a3: number of elements in properties array - // t4: JSObject - // t5: start of next object - __ Addu(a0, a3, Operand(FixedArray::kHeaderSize / kPointerSize)); - __ Allocate( - a0, - t5, - t6, - a2, - &undo_allocation, - static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS)); - - // Initialize the FixedArray. - // a1: constructor - // a3: number of elements in properties array (untagged) - // t4: JSObject - // t5: start of FixedArray (untagged) - __ LoadRoot(t6, Heap::kFixedArrayMapRootIndex); - __ mov(a2, t5); - __ sw(t6, MemOperand(a2, JSObject::kMapOffset)); - __ sll(a0, a3, kSmiTagSize); - __ sw(a0, MemOperand(a2, FixedArray::kLengthOffset)); - __ Addu(a2, a2, Operand(2 * kPointerSize)); - - DCHECK_EQ(0 * kPointerSize, JSObject::kMapOffset); - DCHECK_EQ(1 * kPointerSize, FixedArray::kLengthOffset); - - // Initialize the fields to undefined. - // a1: constructor - // a2: First element of FixedArray (not tagged) - // a3: number of elements in properties array - // t4: JSObject - // t5: FixedArray (not tagged) - __ sll(t3, a3, kPointerSizeLog2); - __ addu(t6, a2, t3); // End of object. - DCHECK_EQ(2 * kPointerSize, FixedArray::kHeaderSize); - if (!is_api_function || create_memento) { - __ LoadRoot(t7, Heap::kUndefinedValueRootIndex); - } else if (FLAG_debug_code) { - __ LoadRoot(t2, Heap::kUndefinedValueRootIndex); - __ Assert(eq, kUndefinedValueNotLoaded, t7, Operand(t2)); - } - __ InitializeFieldsWithFiller(a2, t6, t7); - - // Store the initialized FixedArray into the properties field of - // the JSObject. - // a1: constructor function - // t4: JSObject - // t5: FixedArray (not tagged) - __ Addu(t5, t5, Operand(kHeapObjectTag)); // Add the heap tag. - __ sw(t5, FieldMemOperand(t4, JSObject::kPropertiesOffset)); - // Continue with JSObject being successfully allocated. - // a1: constructor function - // a4: JSObject + // t4: JSObject __ 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. - // t4: JSObject (previous new top) - __ bind(&undo_allocation); - __ UndoAllocationInNewSpace(t4, t5); + // Reload the original constructor and fall-through. + __ bind(&rt_call_reload_new_target); + __ lw(a3, MemOperand(sp, 0 * kPointerSize)); } // Allocate the new receiver object using the runtime call. // a1: constructor function + // a3: original constructor __ bind(&rt_call); - Generate_Runtime_NewObject(masm, create_memento, a1, &count_incremented, - &allocated); + if (create_memento) { + // Get the cell or allocation site. + __ lw(a2, MemOperand(sp, 3 * kPointerSize)); + __ push(a2); // argument 1: allocation site + } + + __ Push(a1, a3); // arguments 2-3 / 1-2 + if (create_memento) { + __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3); + } else { + __ CallRuntime(Runtime::kNewObject, 2); + } + __ mov(t4, v0); + + // Runtime_NewObjectWithAllocationSite increments allocation count. + // Skip the increment. + Label count_incremented; + if (create_memento) { + __ jmp(&count_incremented); + } // Receiver for constructor call allocated. // t4: JSObject __ bind(&allocated); if (create_memento) { - int offset = (use_new_target ? 3 : 2) * kPointerSize; - __ lw(a2, MemOperand(sp, offset)); + __ lw(a2, MemOperand(sp, 3 * kPointerSize)); __ LoadRoot(t5, Heap::kUndefinedValueRootIndex); __ Branch(&count_incremented, eq, a2, Operand(t5)); // a2 is an AllocationSite. We are creating a memento from it, so we @@ -648,20 +540,14 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, } // Restore the parameters. - if (use_new_target) { - __ Pop(a3); // new.target - } + __ Pop(a3); // new.target __ Pop(a1); // Retrieve smi-tagged arguments count from the stack. __ lw(a0, MemOperand(sp)); __ SmiUntag(a0); - if (use_new_target) { - __ Push(a3, t4, t4); - } else { - __ Push(t4, t4); - } + __ Push(a3, t4, t4); // Set up pointer to last argument. __ Addu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); @@ -673,8 +559,8 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, // a3: number of arguments (smi-tagged) // sp[0]: receiver // sp[1]: receiver - // sp[2]: new.target (if used) - // sp[2/3]: number of arguments (smi-tagged) + // sp[2]: new.target + // sp[3]: number of arguments (smi-tagged) Label loop, entry; __ SmiTag(a3, a0); __ jmp(&entry); @@ -701,9 +587,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()); } @@ -718,8 +602,8 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, // If the result is a smi, it is *not* an object in the ECMA sense. // v0: result // sp[0]: receiver (newly allocated object) - // sp[1]: new.target (if used) - // sp[1/2]: number of arguments (smi-tagged) + // sp[1]: new.target + // sp[2]: number of arguments (smi-tagged) __ JumpIfSmi(v0, &use_receiver); // If the type of the result (stored in its map) is less than @@ -737,10 +621,9 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, __ bind(&exit); // v0: result // sp[0]: receiver (newly allocated object) - // sp[1]: new.target (if used) - // sp[1/2]: number of arguments (smi-tagged) - int offset = (use_new_target ? 2 : 1) * kPointerSize; - __ lw(a1, MemOperand(sp, offset)); + // sp[1]: new.target (original constructor) + // sp[2]: number of arguments (smi-tagged) + __ lw(a1, MemOperand(sp, 2 * kPointerSize)); // Leave construct frame. } @@ -754,17 +637,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); } @@ -778,12 +656,12 @@ void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { // -- sp[...]: constructor arguments // ----------------------------------- - // TODO(dslomov): support pretenuring - CHECK(!FLAG_pretenuring_call_new); - { FrameScope frame_scope(masm, StackFrame::CONSTRUCT); + __ AssertUndefinedOrAllocationSite(a2, t0); + __ push(a2); + __ mov(t0, a0); __ SmiTag(t0); __ push(t0); // Smi-tagged arguments count. @@ -982,6 +860,148 @@ 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 a1: the JS function object being called. +// o cp: our context +// o fp: the caller's frame pointer +// o sp: stack pointer +// o ra: return address +// +// The function builds a JS frame. Please see JavaScriptFrameConstants in +// frames-mips.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(ra, fp, cp, a1); + __ Addu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); + + // Get the bytecode array from the function object and load the pointer to the + // first entry into kInterpreterBytecodeRegister. + __ lw(a0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); + __ lw(kInterpreterBytecodeArrayRegister, + FieldMemOperand(a0, SharedFunctionInfo::kFunctionDataOffset)); + + if (FLAG_debug_code) { + // Check function data field is actually a BytecodeArray object. + __ SmiTst(kInterpreterBytecodeArrayRegister, t0); + __ Assert(ne, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry, t0, + Operand(zero_reg)); + __ GetObjectType(kInterpreterBytecodeArrayRegister, t0, t0); + __ Assert(eq, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry, t0, + Operand(BYTECODE_ARRAY_TYPE)); + } + + // Allocate the local and temporary register file on the stack. + { + // Load frame size from the BytecodeArray object. + __ lw(t0, FieldMemOperand(kInterpreterBytecodeArrayRegister, + BytecodeArray::kFrameSizeOffset)); + + // Do a stack check to ensure we don't go over the limit. + Label ok; + __ Subu(t1, sp, Operand(t0)); + __ LoadRoot(a2, Heap::kRealStackLimitRootIndex); + __ Branch(&ok, hs, t1, Operand(a2)); + __ 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; + __ LoadRoot(t1, Heap::kUndefinedValueRootIndex); + __ Branch(&loop_check); + __ bind(&loop_header); + // TODO(rmcilroy): Consider doing more than one push per loop iteration. + __ push(t1); + // Continue loop if not done. + __ bind(&loop_check); + __ Subu(t0, t0, Operand(kPointerSize)); + __ Branch(&loop_header, ge, t0, Operand(zero_reg)); + } + + // 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; + __ LoadRoot(at, Heap::kStackLimitRootIndex); + __ Branch(&ok, hs, sp, Operand(at)); + __ CallRuntime(Runtime::kStackGuard, 0); + __ bind(&ok); + } + + // Load bytecode offset and dispatch table into registers. + __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex); + __ Subu( + kInterpreterRegisterFileRegister, fp, + Operand(kPointerSize + StandardFrameConstants::kFixedFrameSizeFromFp)); + __ li(kInterpreterBytecodeOffsetRegister, + Operand(BytecodeArray::kHeaderSize - kHeapObjectTag)); + __ LoadRoot(kInterpreterDispatchTableRegister, + Heap::kInterpreterTableRootIndex); + __ Addu(kInterpreterDispatchTableRegister, kInterpreterDispatchTableRegister, + Operand(FixedArray::kHeaderSize - kHeapObjectTag)); + + // Dispatch to the first bytecode handler for the function. + __ Addu(a0, kInterpreterBytecodeArrayRegister, + kInterpreterBytecodeOffsetRegister); + __ lbu(a0, MemOperand(a0)); + __ sll(at, a0, kPointerSizeLog2); + __ Addu(at, kInterpreterDispatchTableRegister, at); + __ lw(at, MemOperand(at)); + // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging + // and header removal. + __ Addu(at, at, Operand(Code::kHeaderSize - kHeapObjectTag)); + __ Call(at); +} + + +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 v0. + + // Leave the frame (also dropping the register file). + __ LeaveFrame(StackFrame::JAVA_SCRIPT); + // Drop receiver + arguments. + __ Drop(1); // TODO(rmcilroy): Get number of arguments from BytecodeArray. + __ Jump(ra); +} + + void Builtins::Generate_CompileLazy(MacroAssembler* masm) { CallRuntimePassFunction(masm, Runtime::kCompileLazy); GenerateTailCallToReturnedCode(masm); @@ -1296,8 +1316,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { { FrameScope scope(masm, StackFrame::INTERNAL); __ sll(a0, a0, kSmiTagSize); // Smi tagged. - __ Push(a0, a2); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ push(a0); + __ mov(a0, a2); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ mov(a2, v0); __ pop(a0); @@ -1410,6 +1432,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) { @@ -1427,12 +1450,9 @@ static void Generate_PushAppliedArguments(MacroAssembler* masm, __ lw(receiver, MemOperand(fp, argumentsOffset)); // 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)); - __ li(slot, Operand(Smi::FromInt(index))); - __ li(vector, feedback_vector); + int slot_index = TypeFeedbackVector::PushAppliedArgumentsIndex(); + __ li(slot, Operand(Smi::FromInt(slot_index))); + __ lw(vector, MemOperand(fp, vectorOffset)); Handle<Code> ic = KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode(); __ Call(ic, RelocInfo::CODE_TARGET); @@ -1466,6 +1486,13 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; const int kReceiverOffset = kArgumentsOffset + kPointerSize; const int kFunctionOffset = kReceiverOffset + kPointerSize; + const int kVectorOffset = + InternalFrameConstants::kCodeOffset - 1 * kPointerSize; + + // Push the vector. + __ lw(a1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); + __ lw(a1, FieldMemOperand(a1, SharedFunctionInfo::kFeedbackVectorOffset)); + __ Push(a1); __ lw(a0, MemOperand(fp, kFunctionOffset)); // Get the function. __ push(a0); @@ -1482,10 +1509,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { Generate_CheckStackOverflow(masm, kFunctionOffset, v0, kArgcIsSmiTagged); // Push current limit and index. - const int kIndexOffset = - StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); - const int kLimitOffset = - StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); + const int kIndexOffset = kVectorOffset - (2 * kPointerSize); + const int kLimitOffset = kVectorOffset - (1 * kPointerSize); __ mov(a1, zero_reg); __ Push(v0, a1); // Limit and initial index. @@ -1531,8 +1556,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { // Convert the receiver to a regular object. // a0: receiver __ bind(&call_to_object); - __ push(a0); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ mov(a0, v0); // Put object in a0 to match other paths to push_receiver. __ Branch(&push_receiver); @@ -1546,8 +1571,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { __ push(a0); // Copy all arguments from the array to the stack. - Generate_PushAppliedArguments( - masm, kArgumentsOffset, kIndexOffset, kLimitOffset); + Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset, + kIndexOffset, kLimitOffset); // Call the function. Label call_proxy; @@ -1587,6 +1612,13 @@ static void Generate_ConstructHelper(MacroAssembler* masm) { const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize; const int kArgumentsOffset = kNewTargetOffset + kPointerSize; const int kFunctionOffset = kArgumentsOffset + kPointerSize; + const int kVectorOffset = + InternalFrameConstants::kCodeOffset - 1 * kPointerSize; + + // Push the vector. + __ lw(a1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); + __ lw(a1, FieldMemOperand(a1, SharedFunctionInfo::kFeedbackVectorOffset)); + __ Push(a1); // If newTarget is not supplied, set it to constructor Label validate_arguments; @@ -1611,33 +1643,28 @@ static void Generate_ConstructHelper(MacroAssembler* masm) { Generate_CheckStackOverflow(masm, kFunctionOffset, v0, kArgcIsSmiTagged); // Push current limit and index. - const int kIndexOffset = - StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); - const int kLimitOffset = - StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); + const int kIndexOffset = kVectorOffset - (2 * kPointerSize); + const int kLimitOffset = kVectorOffset - (1 * kPointerSize); __ push(v0); // limit __ mov(a1, zero_reg); // initial index __ push(a1); - // Push newTarget and callee functions - __ lw(a0, MemOperand(fp, kNewTargetOffset)); - __ push(a0); + // Push the constructor function as callee. __ lw(a0, MemOperand(fp, kFunctionOffset)); __ push(a0); // Copy all arguments from the array to the stack. - Generate_PushAppliedArguments( - masm, kArgumentsOffset, kIndexOffset, kLimitOffset); + Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset, + kIndexOffset, kLimitOffset); // Use undefined feedback vector __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); __ lw(a1, MemOperand(fp, kFunctionOffset)); + __ lw(t0, MemOperand(fp, kNewTargetOffset)); // Call the function. CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL); __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); - __ Drop(1); - // Leave internal frame. } __ jr(ra); |