Chromium Code Reviews| Index: src/arm/builtins-arm.cc |
| diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc |
| index e3774cb27d50f3b97a9d9f4cdc80ec775d30b789..89e2c109730b7849e12b778cb4901299c979b622 100644 |
| --- a/src/arm/builtins-arm.cc |
| +++ b/src/arm/builtins-arm.cc |
| @@ -10,6 +10,7 @@ |
| #include "src/debug.h" |
| #include "src/deoptimizer.h" |
| #include "src/full-codegen/full-codegen.h" |
| +#include "src/interpreter/bytecodes.h" |
| #include "src/runtime/runtime.h" |
| namespace v8 { |
| @@ -869,6 +870,145 @@ 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 r1: the JS function object being called. |
| +// o cp: the context |
| +// o pp: the caller's constant pool pointer (if enabled) |
| +// o fp: the caller's frame pointer |
| +// o sp: stack pointer |
| +// o lr: return address |
| +// |
| +// The function builds a JS frame. Please see JavaScriptFrameConstants in |
| +// frames-arm.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); |
| + |
| + __ PushFixedFrame(r1); |
| + __ add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); |
| + |
| + // Get the bytecode array from the function object and load the pointer to the |
| + // first entry into kInterpreterBytecodeRegister. |
| + __ ldr(r0, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| + __ ldr(kInterpreterBytecodeArrayRegister, |
| + FieldMemOperand(r0, SharedFunctionInfo::kFunctionDataOffset)); |
| + |
| + if (FLAG_debug_code) { |
| + // Check function data field is actually a BytecodeArray object. |
| + __ SmiTst(kInterpreterBytecodeArrayRegister); |
| + __ Assert(ne, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry); |
| + __ CompareObjectType(kInterpreterBytecodeArrayRegister, r0, no_reg, |
| + BYTECODE_ARRAY_TYPE); |
| + __ Assert(eq, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry); |
| + } |
| + |
| + // Allocate the local and temporary register file on the stack. |
| + { |
| + // Load frame size from the BytecodeArray object. |
| + __ ldr(r4, FieldMemOperand(kInterpreterBytecodeArrayRegister, |
| + BytecodeArray::kFrameSizeOffset)); |
| + |
| + // Do a stack check to ensure we don't go over the limit. |
| + Label ok; |
| + __ sub(r9, sp, Operand(r4)); |
| + __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); |
| + __ cmp(r9, Operand(r2)); |
| + __ b(hs, &ok); |
| + __ 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(r9, Heap::kUndefinedValueRootIndex); |
| + __ bind(&loop_header); |
| + // TODO(rmcilroy): Consider doing more than one push per loop iteration. |
| + __ push(r9); |
| + // Continue loop if not done. |
| + __ sub(r4, r4, Operand(kPointerSize), SetCC); |
| + __ b(&loop_header, ne); |
| + } |
| + |
| + // 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. |
| + // - Allocating a new local context if applicable. |
|
Benedikt Meurer
2015/07/28 13:06:53
Note: This should be explicit as in TurboFan.
rmcilroy
2015/07/30 07:18:15
Agreed, this was already my plan :). Rearranged th
|
| + // - 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. |
| + // - Supporting FLAG_trace. |
| + // These should all either be added here or added as specific bytecodes in the |
| + // BytecodeArray. |
| + |
| + // Perform stack guard check. |
| + { |
| + Label ok; |
| + __ LoadRoot(ip, Heap::kStackLimitRootIndex); |
| + __ cmp(sp, Operand(ip)); |
| + __ b(hs, &ok); |
| + __ CallRuntime(Runtime::kStackGuard, 0); |
| + __ bind(&ok); |
| + } |
| + |
| + // Load bytecode offset and dispatch table into registers. |
| + __ mov(kInterpreterBytecodeOffsetRegister, |
| + Operand(BytecodeArray::kHeaderSize - kHeapObjectTag)); |
| + __ LoadRoot(kInterpreterDispatchTableRegister, |
| + Heap::kInterpreterTableRootIndex); |
| + __ add(kInterpreterDispatchTableRegister, kInterpreterDispatchTableRegister, |
| + Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| + |
| + // Dispatch to the first bytecode handler for the function. |
| + __ ldrb(r0, MemOperand(kInterpreterBytecodeArrayRegister, |
| + kInterpreterBytecodeOffsetRegister)); |
| + __ mov(r0, Operand(r0, LSL, kPointerSizeLog2)); |
| + __ ldr(ip, MemOperand(kInterpreterDispatchTableRegister, r0)); |
| + // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging |
| + // and header removal. |
| + __ add(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| + __ Jump(ip); |
| +} |
| + |
| + |
| +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). |
| + // These should all either be added here or added as specific bytecodes in the |
| + // BytecodeArray. |
| + |
| + // Load return value into r0. |
| + __ ldr(r0, 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(lr); |
| +} |
| + |
| + |
| void Builtins::Generate_CompileLazy(MacroAssembler* masm) { |
| CallRuntimePassFunction(masm, Runtime::kCompileLazy); |
| GenerateTailCallToReturnedCode(masm); |