void CEntryStub::GenerateCore(MacroAssembler* masm,
Label* throw_normal_exception,
Label* throw_out_of_memory_exception,
- bool do_gc,
- bool do_restore) {
+ StackFrame::Type frame_type,
+ bool do_gc) {
// r0: result parameter for PerformGC, if any
// r4: number of arguments including receiver (C callee-saved)
// r5: pointer to builtin function (C callee-saved)
__ tst(r2, Operand(kFailureTagMask));
__ b(eq, &failure_returned);
- // Restore the memory copy of the registers by digging them out from
- // the stack.
- if (do_restore) {
- // Ok to clobber r2 and r3.
- const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize;
- const int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize;
- __ add(r3, fp, Operand(kOffset));
- __ CopyRegistersFromStackToMemory(r3, r2, kJSCallerSaved);
- }
-
- // Exit C frame and return
+ // Exit C frame and return.
// r0:r1: result
// sp: stack pointer
// fp: frame pointer
// pp: caller's parameter pointer pp (restored as C callee-saved)
- __ LeaveExitFrame();
+ __ LeaveExitFrame(frame_type);
// check if we should retry or throw exception
Label retry;
// 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.
- // Use sp as base to push.
- __ CopyRegistersFromMemoryToStack(sp, kJSCallerSaved);
- }
-
- // r4: number of arguments
- // r5: pointer to builtin function (C callee-saved)
-
- Label entry;
- __ bind(&entry);
+ // r4: number of arguments (C callee-saved)
+ // r5: pointer to builtin function (C callee-saved)
+ // r6: pointer to first argument (C callee-saved)
Label throw_out_of_memory_exception;
Label throw_normal_exception;
GenerateCore(masm,
&throw_normal_exception,
&throw_out_of_memory_exception,
- FLAG_gc_greedy,
- is_debug_break);
+ frame_type,
+ FLAG_gc_greedy);
#else
GenerateCore(masm,
&throw_normal_exception,
&throw_out_of_memory_exception,
- false,
- is_debug_break);
+ frame_type,
+ false);
#endif
GenerateCore(masm,
&throw_normal_exception,
&throw_out_of_memory_exception,
- true,
- is_debug_break);
+ frame_type,
+ true);
__ bind(&throw_out_of_memory_exception);
GenerateThrowOutOfMemory(masm);
#define __ masm->
-void CEntryStub::GenerateReserveCParameterSpace(MacroAssembler* masm,
- int num_parameters) {
- if (num_parameters > 0) {
- __ sub(Operand(esp), Immediate(num_parameters * kPointerSize));
- }
- static const int kFrameAlignment = OS::ActivationFrameAlignment();
- if (kFrameAlignment > 0) {
- ASSERT(IsPowerOf2(kFrameAlignment));
- __ and_(esp, -kFrameAlignment);
- }
-}
-
-
void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize); // adjust this code
ExternalReference handler_address(Top::k_handler_address);
void CEntryStub::GenerateCore(MacroAssembler* masm,
Label* throw_normal_exception,
Label* throw_out_of_memory_exception,
- bool do_gc,
- bool do_restore) {
+ StackFrame::Type frame_type,
+ bool do_gc) {
// eax: result parameter for PerformGC, if any
// ebx: pointer to C function (C callee-saved)
// ebp: frame pointer (restored after C call)
__ test(ecx, Immediate(kFailureTagMask));
__ j(zero, &failure_returned, not_taken);
- // Restore the memory copy of the registers by digging them out from
- // the stack.
- if (do_restore) {
- // Ok to clobber ebx and edi - function pointer and number of arguments not
- // needed anymore.
- const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize;
- int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize;
- __ lea(ebx, Operand(ebp, kOffset));
- __ CopyRegistersFromStackToMemory(ebx, ecx, kJSCallerSaved);
- }
-
- // Exit C frame.
- __ LeaveExitFrame();
+ // Exit the JavaScript to C++ exit frame.
+ __ LeaveExitFrame(frame_type);
__ ret(0);
- // Handling of Failure.
+ // Handling of failure.
__ bind(&failure_returned);
Label retry;
// 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.
-
- // TODO(1243899): This should be symmetric to
- // CopyRegistersFromStackToMemory() but it isn't! esp is assumed
- // correct here, but computed for the other call. Very error
- // prone! FIX THIS. Actually there are deeper problems with
- // register saving than this asymmetry (see the bug report
- // associated with this issue).
- __ PushRegistersFromMemory(kJSCallerSaved);
- }
-
- // Allocate stack space for 2 arguments (argc, argv).
- GenerateReserveCParameterSpace(masm, 2);
- __ mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp); // save entry sp
-
// eax: result parameter for PerformGC, if any (setup below)
// ebx: pointer to builtin function (C callee-saved)
// ebp: frame pointer (restored after C call)
// esp: stack pointer (restored after C call)
// edi: number of arguments including receiver (C callee-saved)
-
- Label entry;
- __ bind(&entry);
+ // esi: argv pointer (C callee-saved)
Label throw_out_of_memory_exception;
Label throw_normal_exception;
}
GenerateCore(masm, &throw_normal_exception,
&throw_out_of_memory_exception,
- FLAG_gc_greedy,
- is_debug_break);
+ frame_type,
+ FLAG_gc_greedy);
#else
GenerateCore(masm,
&throw_normal_exception,
&throw_out_of_memory_exception,
- false,
- is_debug_break);
+ frame_type,
+ false);
#endif
+
GenerateCore(masm,
&throw_normal_exception,
&throw_out_of_memory_exception,
- true,
- is_debug_break);
+ frame_type,
+ true);
__ bind(&throw_out_of_memory_exception);
GenerateThrowOutOfMemory(masm);
void GenerateCore(MacroAssembler* masm,
Label* throw_normal_exception,
Label* throw_out_of_memory_exception,
- bool do_gc, bool do_restore);
+ StackFrame::Type frame_type,
+ bool do_gc);
void GenerateThrowTOS(MacroAssembler* masm);
void GenerateThrowOutOfMemory(MacroAssembler* masm);
- void GenerateReserveCParameterSpace(MacroAssembler* masm, int num_parameters);
private:
Major MajorKey() { return CEntry; }
};
-
class JSEntryStub : public CodeStub {
public:
JSEntryStub() { }
// 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));
+
+ // Save the state of all registers to the stack from the memory
+ // location. This is needed to allow nested break points.
+ if (type == StackFrame::EXIT_DEBUG) {
+ // Use sp as base to push.
+ CopyRegistersFromMemoryToStack(sp, kJSCallerSaved);
+ }
}
-void MacroAssembler::LeaveExitFrame() {
+void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
+ // Restore the memory copy of the registers by digging them out from
+ // the stack. This is needed to allow nested break points.
+ if (type == StackFrame::EXIT_DEBUG) {
+ // This code intentionally clobbers r2 and r3.
+ const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize;
+ const int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize;
+ add(r3, fp, Operand(kOffset));
+ CopyRegistersFromStackToMemory(r3, r2, kJSCallerSaved);
+ }
+
// Clear top frame.
mov(r3, Operand(0));
mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address)));
void EnterExitFrame(StackFrame::Type type);
// Leave the current exit frame. Expects the return value in r0.
- void LeaveExitFrame();
+ void LeaveExitFrame(StackFrame::Type type);
// ---------------------------------------------------------------------------
int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
mov(edi, Operand(eax));
lea(esi, Operand(ebp, eax, times_4, offset));
+
+ // Save the state of all registers to the stack from the memory
+ // location. This is needed to allow nested break points.
+ if (type == StackFrame::EXIT_DEBUG) {
+ // TODO(1243899): This should be symmetric to
+ // CopyRegistersFromStackToMemory() but it isn't! esp is assumed
+ // correct here, but computed for the other call. Very error
+ // prone! FIX THIS. Actually there are deeper problems with
+ // register saving than this asymmetry (see the bug report
+ // associated with this issue).
+ PushRegistersFromMemory(kJSCallerSaved);
+ }
+
+ // Reserve space for two arguments: argc and argv.
+ sub(Operand(esp), Immediate(2 * kPointerSize));
+
+ // Get the required frame alignment for the OS.
+ static const int kFrameAlignment = OS::ActivationFrameAlignment();
+ if (kFrameAlignment > 0) {
+ ASSERT(IsPowerOf2(kFrameAlignment));
+ and_(esp, -kFrameAlignment);
+ }
+
+ // Patch the saved entry sp.
+ mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp);
}
-void MacroAssembler::LeaveExitFrame() {
+void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
+ // Restore the memory copy of the registers by digging them out from
+ // the stack. This is needed to allow nested break points.
+ if (type == StackFrame::EXIT_DEBUG) {
+ // It's okay to clobber register ebx below because we don't need
+ // the function pointer after this.
+ const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize;
+ int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize;
+ lea(ebx, Operand(ebp, kOffset));
+ CopyRegistersFromStackToMemory(ebx, ecx, kJSCallerSaved);
+ }
+
// Get the return address from the stack and restore the frame pointer.
mov(ecx, Operand(ebp, 1 * kPointerSize));
mov(ebp, Operand(ebp, 0 * kPointerSize));
// 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();
+ void LeaveExitFrame(StackFrame::Type type);
// ---------------------------------------------------------------------------