Index: src/mips64/builtins-mips64.cc |
diff --git a/src/mips64/builtins-mips64.cc b/src/mips64/builtins-mips64.cc |
index 04b854ee9e966086da9c3d92e95d55826f6ebd92..1426f15858b896dcac70c392f612b97ffeb431ca 100644 |
--- a/src/mips64/builtins-mips64.cc |
+++ b/src/mips64/builtins-mips64.cc |
@@ -858,6 +858,144 @@ 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); |
+ __ Daddu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); |
+ |
+ // Get the bytecode array from the function object and load the pointer to the |
+ // first entry into kInterpreterBytecodeRegister. |
+ __ ld(a0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
+ __ ld(kInterpreterBytecodeArrayRegister, |
+ FieldMemOperand(a0, SharedFunctionInfo::kFunctionDataOffset)); |
+ |
+ if (FLAG_debug_code) { |
+ // Check function data field is actually a BytecodeArray object. |
+ __ SmiTst(kInterpreterBytecodeArrayRegister, a4); |
+ __ Assert(ne, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry, a4, |
+ Operand(zero_reg)); |
+ __ GetObjectType(kInterpreterBytecodeArrayRegister, a4, a4); |
+ __ Assert(eq, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry, a4, |
+ Operand(BYTECODE_ARRAY_TYPE)); |
+ } |
+ |
+ // Allocate the local and temporary register file on the stack. |
+ { |
+ // Load frame size from the BytecodeArray object. |
+ __ ld(a4, FieldMemOperand(kInterpreterBytecodeArrayRegister, |
+ BytecodeArray::kFrameSizeOffset)); |
+ |
+ // Do a stack check to ensure we don't go over the limit. |
+ Label ok; |
+ __ Dsubu(a5, sp, Operand(a4)); |
+ __ LoadRoot(a2, Heap::kRealStackLimitRootIndex); |
+ __ Branch(&ok, hs, a5, Operand(a2)); |
+ __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); |
+ __ bind(&ok); |
+ |
+ // If ok, push undefined as the initial value for all register file entries. |
+ // Note: there should always be at least one stack slot for the return |
+ // register in the register file. |
+ Label loop_header; |
+ __ LoadRoot(a5, Heap::kUndefinedValueRootIndex); |
+ __ bind(&loop_header); |
+ // TODO(rmcilroy): Consider doing more than one push per loop iteration. |
+ __ push(a5); |
+ // Continue loop if not done. |
+ __ Dsubu(a4, a4, Operand(kPointerSize)); |
+ __ Branch(&loop_header, ge, a4, 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. |
+ __ li(kInterpreterBytecodeOffsetRegister, |
+ Operand(BytecodeArray::kHeaderSize - kHeapObjectTag)); |
+ __ LoadRoot(kInterpreterDispatchTableRegister, |
+ Heap::kInterpreterTableRootIndex); |
+ __ Daddu(kInterpreterDispatchTableRegister, kInterpreterDispatchTableRegister, |
+ Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
+ |
+ // Dispatch to the first bytecode handler for the function. |
+ __ Daddu(a0, kInterpreterBytecodeArrayRegister, |
+ kInterpreterBytecodeOffsetRegister); |
+ __ lbu(a0, MemOperand(a0)); |
+ __ dsll(at, a0, kPointerSizeLog2); |
+ __ Daddu(at, kInterpreterDispatchTableRegister, at); |
+ __ ld(at, MemOperand(at)); |
+ // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging |
+ // and header removal. |
+ __ Daddu(at, at, Operand(Code::kHeaderSize - kHeapObjectTag)); |
+ __ Jump(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). |
+ |
+ // Load return value into v0. |
+ __ ld(v0, MemOperand(fp, -kPointerSize - |
+ StandardFrameConstants::kFixedFrameSizeFromFp)); |
+ // 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); |