Refactored the code for entering and leaving exit frames (calls
from JavaScript to C++). Includes a few slight optimizations like keeping argv in a callee-saved register. Review URL: http://codereview.chromium.org/4035 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@359 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
ee7e7be35f
commit
9d30045d06
@ -168,7 +168,7 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
|
||||
// sp[1]: constructor function
|
||||
// sp[2]: number of arguments (smi-tagged)
|
||||
__ ldr(r1, MemOperand(sp, 2 * kPointerSize));
|
||||
__ ExitInternalFrame();
|
||||
__ LeaveInternalFrame();
|
||||
__ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
|
||||
__ add(sp, sp, Operand(kPointerSize));
|
||||
__ mov(pc, Operand(lr));
|
||||
@ -240,7 +240,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
|
||||
|
||||
// Exit the JS frame and remove the parameters (except function), and return.
|
||||
// Respect ABI stack constraint.
|
||||
__ ExitInternalFrame();
|
||||
__ LeaveInternalFrame();
|
||||
__ mov(pc, lr);
|
||||
|
||||
// r0: result
|
||||
@ -337,7 +337,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
|
||||
__ pop(r0);
|
||||
__ mov(r0, Operand(r0, ASR, kSmiTagSize));
|
||||
|
||||
__ ExitInternalFrame();
|
||||
__ LeaveInternalFrame();
|
||||
__ b(&patch_receiver);
|
||||
|
||||
// Use the global object from the called function as the receiver.
|
||||
@ -525,7 +525,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
|
||||
__ InvokeFunction(r1, actual, CALL_FUNCTION);
|
||||
|
||||
// Tear down the internal frame and remove function, receiver and args.
|
||||
__ ExitInternalFrame();
|
||||
__ LeaveInternalFrame();
|
||||
__ add(sp, sp, Operand(3 * kPointerSize));
|
||||
__ mov(pc, lr);
|
||||
}
|
||||
|
@ -297,7 +297,7 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
|
||||
// Restore the arguments count and exit the internal frame.
|
||||
__ bind(&exit);
|
||||
__ mov(ebx, Operand(esp, kPointerSize)); // get arguments count
|
||||
__ ExitInternalFrame();
|
||||
__ LeaveInternalFrame();
|
||||
|
||||
// Remove caller arguments from the stack and return.
|
||||
ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
|
||||
@ -363,7 +363,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
|
||||
// Exit the JS frame. Notice that this also removes the empty
|
||||
// context and the function left on the stack by the code
|
||||
// invocation.
|
||||
__ ExitInternalFrame();
|
||||
__ LeaveInternalFrame();
|
||||
__ ret(1 * kPointerSize); // remove receiver
|
||||
}
|
||||
|
||||
@ -450,7 +450,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
|
||||
__ pop(eax);
|
||||
__ shr(eax, kSmiTagSize);
|
||||
|
||||
__ ExitInternalFrame();
|
||||
__ LeaveInternalFrame();
|
||||
__ jmp(&patch_receiver);
|
||||
|
||||
// Use the global object from the called function as the receiver.
|
||||
@ -613,7 +613,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
|
||||
__ mov(edi, Operand(ebp, 4 * kPointerSize));
|
||||
__ InvokeFunction(edi, actual, CALL_FUNCTION);
|
||||
|
||||
__ ExitInternalFrame();
|
||||
__ LeaveInternalFrame();
|
||||
__ ret(3 * kPointerSize); // remove this, receiver, and arguments
|
||||
}
|
||||
|
||||
@ -771,7 +771,7 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
|
||||
__ PopRegistersToMemory(pointer_regs);
|
||||
|
||||
// Get rid of the internal frame.
|
||||
__ ExitInternalFrame();
|
||||
__ LeaveInternalFrame();
|
||||
|
||||
// If this call did not replace a call but patched other code then there will
|
||||
// be an unwanted return address left on the stack. Here we get rid of that.
|
||||
|
@ -1634,6 +1634,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
|
||||
// r0: result parameter for PerformGC, if any
|
||||
// r4: number of arguments including receiver (C callee-saved)
|
||||
// r5: pointer to builtin function (C callee-saved)
|
||||
// r6: pointer to the first argument (C callee-saved)
|
||||
|
||||
if (do_gc) {
|
||||
// Passing r0.
|
||||
@ -1641,11 +1642,9 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
// Call C built-in.
|
||||
// r0 = argc.
|
||||
// r0 = argc, r1 = argv
|
||||
__ mov(r0, Operand(r4));
|
||||
// r1 = argv.
|
||||
__ add(r1, fp, Operand(r4, LSL, kPointerSizeLog2));
|
||||
__ add(r1, r1, Operand(ExitFrameConstants::kPPDisplacement - kPointerSize));
|
||||
__ mov(r1, Operand(r6));
|
||||
|
||||
// TODO(1242173): To let the GC traverse the return address of the exit
|
||||
// frames, we need to know where the return address is. Right now,
|
||||
@ -1672,11 +1671,6 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
|
||||
__ tst(r2, Operand(kFailureTagMask));
|
||||
__ b(eq, &failure_returned);
|
||||
|
||||
// clear top frame
|
||||
__ mov(r3, Operand(0));
|
||||
__ mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address)));
|
||||
__ str(r3, MemOperand(ip));
|
||||
|
||||
// Restore the memory copy of the registers by digging them out from
|
||||
// the stack.
|
||||
if (do_restore) {
|
||||
@ -1692,12 +1686,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
|
||||
// sp: stack pointer
|
||||
// fp: frame pointer
|
||||
// pp: caller's parameter pointer pp (restored as C callee-saved)
|
||||
|
||||
// Restore current context from top and clear it in debug mode.
|
||||
__ mov(r3, Operand(Top::context_address()));
|
||||
__ ldr(cp, MemOperand(r3));
|
||||
__ mov(sp, Operand(fp)); // respect ABI stack constraint
|
||||
__ ldm(ia, sp, fp.bit() | sp.bit() | pc.bit());
|
||||
__ LeaveExitFrame();
|
||||
|
||||
// check if we should retry or throw exception
|
||||
Label retry;
|
||||
@ -1745,28 +1734,12 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
|
||||
// this by performing a garbage collection and retrying the
|
||||
// builtin once.
|
||||
|
||||
// Enter C frame
|
||||
// Compute parameter pointer before making changes and save it as ip register
|
||||
// so that it is restored as sp register on exit, thereby popping the args.
|
||||
// ip = sp + kPointerSize*args_len;
|
||||
__ add(ip, sp, Operand(r0, LSL, kPointerSizeLog2));
|
||||
StackFrame::Type frame_type = is_debug_break
|
||||
? StackFrame::EXIT_DEBUG
|
||||
: StackFrame::EXIT;
|
||||
|
||||
// push in reverse order:
|
||||
// caller_fp, sp_on_exit, caller_pc
|
||||
__ stm(db_w, sp, fp.bit() | ip.bit() | lr.bit());
|
||||
__ mov(fp, Operand(sp)); // setup new frame pointer
|
||||
|
||||
// Store the current context in top.
|
||||
__ mov(ip, Operand(ExternalReference(Top::k_context_address)));
|
||||
__ str(cp, MemOperand(ip));
|
||||
|
||||
// remember top frame
|
||||
__ mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address)));
|
||||
__ str(fp, MemOperand(ip));
|
||||
|
||||
// Push debug marker.
|
||||
__ mov(ip, Operand(is_debug_break ? 1 : 0));
|
||||
__ push(ip);
|
||||
// Enter the exit frame that transitions from JavaScript to C++.
|
||||
__ EnterExitFrame(frame_type);
|
||||
|
||||
if (is_debug_break) {
|
||||
// Save the state of all registers to the stack from the memory location.
|
||||
@ -1774,13 +1747,6 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
|
||||
__ CopyRegistersFromMemoryToStack(sp, kJSCallerSaved);
|
||||
}
|
||||
|
||||
// move number of arguments (argc) into callee-saved register
|
||||
__ mov(r4, Operand(r0));
|
||||
|
||||
// move pointer to builtin function into callee-saved register
|
||||
__ mov(r5, Operand(r1));
|
||||
|
||||
// r0: result parameter for PerformGC, if any (setup below)
|
||||
// r4: number of arguments
|
||||
// r5: pointer to builtin function (C callee-saved)
|
||||
|
||||
|
@ -5252,6 +5252,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
|
||||
// ebp: frame pointer (restored after C call)
|
||||
// esp: stack pointer (restored after C call)
|
||||
// edi: number of arguments including receiver (C callee-saved)
|
||||
// esi: pointer to the first argument (C callee-saved)
|
||||
|
||||
if (do_gc) {
|
||||
__ mov(Operand(esp, 0 * kPointerSize), eax); // Result.
|
||||
@ -5259,12 +5260,8 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
// Call C function.
|
||||
__ lea(eax, Operand(ebp,
|
||||
edi,
|
||||
times_4,
|
||||
StandardFrameConstants::kCallerSPOffset - kPointerSize));
|
||||
__ mov(Operand(esp, 0 * kPointerSize), edi); // argc.
|
||||
__ mov(Operand(esp, 1 * kPointerSize), eax); // argv.
|
||||
__ mov(Operand(esp, 1 * kPointerSize), esi); // argv.
|
||||
__ call(Operand(ebx));
|
||||
// Result is in eax or edx:eax - do not destroy these registers!
|
||||
|
||||
@ -5276,11 +5273,6 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
|
||||
__ test(ecx, Immediate(kFailureTagMask));
|
||||
__ j(zero, &failure_returned, not_taken);
|
||||
|
||||
// Restore number of arguments to ecx and clear top frame.
|
||||
__ mov(ecx, Operand(edi));
|
||||
ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
|
||||
__ mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0));
|
||||
|
||||
// Restore the memory copy of the registers by digging them out from
|
||||
// the stack.
|
||||
if (do_restore) {
|
||||
@ -5289,25 +5281,11 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
|
||||
const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize;
|
||||
int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize;
|
||||
__ lea(ebx, Operand(ebp, kOffset));
|
||||
__ CopyRegistersFromStackToMemory(ebx, edi, kJSCallerSaved);
|
||||
__ CopyRegistersFromStackToMemory(ebx, ecx, kJSCallerSaved);
|
||||
}
|
||||
|
||||
// Exit C frame.
|
||||
__ lea(esp, Operand(ebp, -1 * kPointerSize));
|
||||
__ pop(ebx);
|
||||
__ pop(ebp);
|
||||
|
||||
// Restore current context from top and clear it in debug mode.
|
||||
ExternalReference context_address(Top::k_context_address);
|
||||
__ mov(esi, Operand::StaticVariable(context_address));
|
||||
if (kDebug) {
|
||||
__ mov(Operand::StaticVariable(context_address), Immediate(0));
|
||||
}
|
||||
|
||||
// Pop arguments from caller's stack and return.
|
||||
__ pop(ebx); // Ok to clobber ebx - function pointer not needed anymore.
|
||||
__ lea(esp, Operand(esp, ecx, times_4, 0));
|
||||
__ push(ebx);
|
||||
__ LeaveExitFrame();
|
||||
__ ret(0);
|
||||
|
||||
// Handling of Failure.
|
||||
@ -5407,25 +5385,12 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
|
||||
// this by performing a garbage collection and retrying the
|
||||
// builtin once.
|
||||
|
||||
// Enter C frame.
|
||||
// Here we make the following assumptions and use them when setting
|
||||
// up the top-most Frame. Adjust the code if these assumptions
|
||||
// change.
|
||||
ASSERT(ExitFrameConstants::kPPDisplacement == +2 * kPointerSize);
|
||||
ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize);
|
||||
ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize);
|
||||
ASSERT(ExitFrameConstants::kSPOffset == -2 * kPointerSize);
|
||||
__ push(ebp); // caller fp
|
||||
__ mov(ebp, Operand(esp)); // C entry fp
|
||||
__ push(ebx); // C function
|
||||
__ push(Immediate(0)); // saved entry sp, set before call
|
||||
__ push(Immediate(is_debug_break ? 1 : 0));
|
||||
StackFrame::Type frame_type = is_debug_break ?
|
||||
StackFrame::EXIT_DEBUG :
|
||||
StackFrame::EXIT;
|
||||
|
||||
// Remember top frame.
|
||||
ExternalReference c_entry_fp(Top::k_c_entry_fp_address);
|
||||
ExternalReference context_address(Top::k_context_address);
|
||||
__ mov(Operand::StaticVariable(c_entry_fp), ebp);
|
||||
__ mov(Operand::StaticVariable(context_address), esi);
|
||||
// Enter the exit frame that transitions from JavaScript to C++.
|
||||
__ EnterExitFrame(frame_type);
|
||||
|
||||
if (is_debug_break) {
|
||||
// Save the state of all registers to the stack from the memory
|
||||
@ -5440,10 +5405,6 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
|
||||
__ PushRegistersFromMemory(kJSCallerSaved);
|
||||
}
|
||||
|
||||
// Move number of arguments (argc) into callee-saved register. Note
|
||||
// that edi is only available after remembering the top frame.
|
||||
__ mov(edi, Operand(eax));
|
||||
|
||||
// Allocate stack space for 2 arguments (argc, argv).
|
||||
GenerateReserveCParameterSpace(masm, 2);
|
||||
__ mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp); // save entry sp
|
||||
|
@ -81,8 +81,8 @@ class EntryFrameConstants : public AllStatic {
|
||||
|
||||
class ExitFrameConstants : public AllStatic {
|
||||
public:
|
||||
static const int kDebugMarkOffset = -3 * kPointerSize;
|
||||
static const int kSPOffset = -2 * kPointerSize;
|
||||
static const int kDebugMarkOffset = -2 * kPointerSize;
|
||||
static const int kSPOffset = -1 * kPointerSize;
|
||||
|
||||
// Let the parameters pointer for exit frames point just below the
|
||||
// frame structure on the stack (frame pointer and return address).
|
||||
|
@ -427,7 +427,7 @@ void CallIC::Generate(MacroAssembler* masm,
|
||||
// Move result to r1.
|
||||
__ mov(r1, Operand(r0));
|
||||
|
||||
__ ExitInternalFrame();
|
||||
__ LeaveInternalFrame();
|
||||
|
||||
// Patch the function on the stack; 1 ~ receiver.
|
||||
__ str(r1, MemOperand(sp, (argc + 1) * kPointerSize));
|
||||
|
@ -528,7 +528,7 @@ void CallIC::Generate(MacroAssembler* masm,
|
||||
|
||||
// Move result to edi and exit the internal frame.
|
||||
__ mov(Operand(edi), eax);
|
||||
__ ExitInternalFrame();
|
||||
__ LeaveInternalFrame();
|
||||
|
||||
// Invoke the function.
|
||||
ParameterCount actual(argc);
|
||||
|
@ -264,7 +264,7 @@ void MacroAssembler::EnterInternalFrame() {
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::ExitInternalFrame() {
|
||||
void MacroAssembler::LeaveInternalFrame() {
|
||||
// r0: preserved
|
||||
// r1: preserved
|
||||
// r2: preserved
|
||||
@ -276,6 +276,58 @@ void MacroAssembler::ExitInternalFrame() {
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
|
||||
ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG);
|
||||
// Compute parameter pointer before making changes and save it as ip
|
||||
// register so that it is restored as sp register on exit, thereby
|
||||
// popping the args.
|
||||
|
||||
// ip = sp + kPointerSize * #args;
|
||||
add(ip, sp, Operand(r0, LSL, kPointerSizeLog2));
|
||||
|
||||
// Push in reverse order: caller_fp, sp_on_exit, and caller_pc.
|
||||
stm(db_w, sp, fp.bit() | ip.bit() | lr.bit());
|
||||
mov(fp, Operand(sp)); // setup new frame pointer
|
||||
|
||||
// Push debug marker.
|
||||
mov(ip, Operand(type == StackFrame::EXIT_DEBUG ? 1 : 0));
|
||||
push(ip);
|
||||
|
||||
// Save the frame pointer and the context in top.
|
||||
mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address)));
|
||||
str(fp, MemOperand(ip));
|
||||
mov(ip, Operand(ExternalReference(Top::k_context_address)));
|
||||
str(cp, MemOperand(ip));
|
||||
|
||||
// Setup argc and the builtin function in callee-saved registers.
|
||||
mov(r4, Operand(r0));
|
||||
mov(r5, Operand(r1));
|
||||
|
||||
// Compute the argv pointer and keep it in a callee-saved register.
|
||||
add(r6, fp, Operand(r4, LSL, kPointerSizeLog2));
|
||||
add(r6, r6, Operand(ExitFrameConstants::kPPDisplacement - kPointerSize));
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::LeaveExitFrame() {
|
||||
// Clear top frame.
|
||||
mov(r3, Operand(0));
|
||||
mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address)));
|
||||
str(r3, MemOperand(ip));
|
||||
|
||||
// Restore current context from top and clear it in debug mode.
|
||||
mov(ip, Operand(ExternalReference(Top::k_context_address)));
|
||||
ldr(cp, MemOperand(ip));
|
||||
if (kDebug) {
|
||||
str(r3, MemOperand(ip));
|
||||
}
|
||||
|
||||
// Pop the arguments, restore registers, and return.
|
||||
mov(sp, Operand(fp)); // respect ABI stack constraint
|
||||
ldm(ia, sp, fp.bit() | sp.bit() | pc.bit());
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::InvokePrologue(const ParameterCount& expected,
|
||||
const ParameterCount& actual,
|
||||
Handle<Code> code_constant,
|
||||
|
@ -99,7 +99,16 @@ class MacroAssembler: public Assembler {
|
||||
// Activation frames
|
||||
|
||||
void EnterInternalFrame();
|
||||
void ExitInternalFrame();
|
||||
void LeaveInternalFrame();
|
||||
|
||||
// Enter specific kind of exit frame; either EXIT or
|
||||
// EXIT_DEBUG. Expects the number of arguments in register r0 and
|
||||
// the builtin function to call in register r1. Exits with argc in
|
||||
// r4, argv in r6, and and the builtin function to call in r5.
|
||||
void EnterExitFrame(StackFrame::Type type);
|
||||
|
||||
// Leave the current exit frame. Expects the return value in r0.
|
||||
void LeaveExitFrame();
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -325,7 +325,7 @@ void MacroAssembler::EnterInternalFrame() {
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::ExitInternalFrame() {
|
||||
void MacroAssembler::LeaveInternalFrame() {
|
||||
if (FLAG_debug_code) {
|
||||
StackFrame::Type type = StackFrame::INTERNAL;
|
||||
cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset),
|
||||
@ -336,6 +336,58 @@ void MacroAssembler::ExitInternalFrame() {
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
|
||||
ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG);
|
||||
|
||||
// Setup the frame structure on the stack.
|
||||
ASSERT(ExitFrameConstants::kPPDisplacement == +2 * kPointerSize);
|
||||
ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize);
|
||||
ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize);
|
||||
push(ebp);
|
||||
mov(ebp, Operand(esp));
|
||||
|
||||
// Reserve room for entry stack pointer and push the debug marker.
|
||||
ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize);
|
||||
push(Immediate(0)); // saved entry sp, patched before call
|
||||
push(Immediate(type == StackFrame::EXIT_DEBUG ? 1 : 0));
|
||||
|
||||
// Save the frame pointer and the context in top.
|
||||
ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
|
||||
ExternalReference context_address(Top::k_context_address);
|
||||
mov(Operand::StaticVariable(c_entry_fp_address), ebp);
|
||||
mov(Operand::StaticVariable(context_address), esi);
|
||||
|
||||
// Setup argc and argv in callee-saved registers.
|
||||
int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
|
||||
mov(edi, Operand(eax));
|
||||
lea(esi, Operand(ebp, eax, times_4, offset));
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::LeaveExitFrame() {
|
||||
// Get the return address from the stack and restore the frame pointer.
|
||||
mov(ecx, Operand(ebp, 1 * kPointerSize));
|
||||
mov(ebp, Operand(ebp, 0 * kPointerSize));
|
||||
|
||||
// Pop the arguments and the receiver from the caller stack.
|
||||
lea(esp, Operand(esi, 1 * kPointerSize));
|
||||
|
||||
// Restore current context from top and clear it in debug mode.
|
||||
ExternalReference context_address(Top::k_context_address);
|
||||
mov(esi, Operand::StaticVariable(context_address));
|
||||
if (kDebug) {
|
||||
mov(Operand::StaticVariable(context_address), Immediate(0));
|
||||
}
|
||||
|
||||
// Push the return address to get ready to return.
|
||||
push(ecx);
|
||||
|
||||
// Clear the top frame.
|
||||
ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
|
||||
mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0));
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::PushTryHandler(CodeLocation try_location,
|
||||
HandlerType type) {
|
||||
ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize); // adjust this code
|
||||
|
@ -86,10 +86,19 @@ class MacroAssembler: public Assembler {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Activation frames
|
||||
|
||||
// Enter or exit a stack frame of the given type. Cannot be used to
|
||||
// construct or leave JavaScript frames.
|
||||
void EnterInternalFrame();
|
||||
void ExitInternalFrame();
|
||||
void LeaveInternalFrame();
|
||||
|
||||
// Enter specific kind of exit frame; either EXIT or
|
||||
// EXIT_DEBUG. Expects the number of arguments in register eax and
|
||||
// sets up the number of arguments in register edi and the pointer
|
||||
// to the first argument in register esi.
|
||||
void EnterExitFrame(StackFrame::Type type);
|
||||
|
||||
// Leave the current exit frame. Expects the return value in
|
||||
// register eax:edx (untouched) and the pointer to the first
|
||||
// argument in register esi.
|
||||
void LeaveExitFrame();
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@ -198,6 +207,10 @@ class MacroAssembler: public Assembler {
|
||||
// Jump to the builtin routine.
|
||||
void JumpToBuiltin(const ExternalReference& ext);
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Utilities
|
||||
|
||||
void Ret();
|
||||
|
||||
struct Unresolved {
|
||||
|
@ -178,7 +178,7 @@ Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
|
||||
__ pop(r1);
|
||||
|
||||
// Tear down temporary frame.
|
||||
__ ExitInternalFrame();
|
||||
__ LeaveInternalFrame();
|
||||
|
||||
// Do a tail-call of the compiled function.
|
||||
__ Jump(r2);
|
||||
|
@ -476,7 +476,7 @@ Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
|
||||
__ CallRuntime(Runtime::kLazyCompile, 1);
|
||||
__ pop(edi);
|
||||
|
||||
__ ExitInternalFrame();
|
||||
__ LeaveInternalFrame();
|
||||
|
||||
// Do a tail-call of the compiled function.
|
||||
__ lea(ecx, FieldOperand(eax, Code::kHeaderSize));
|
||||
@ -688,7 +688,7 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* object,
|
||||
__ mov(edx, Operand(ebp, (argc + 2) * kPointerSize)); // receiver
|
||||
|
||||
// Exit frame.
|
||||
__ ExitInternalFrame();
|
||||
__ LeaveInternalFrame();
|
||||
|
||||
// Check that the function really is a function.
|
||||
__ test(edi, Immediate(kSmiTagMask));
|
||||
|
Loading…
Reference in New Issue
Block a user