Cleanup of ARM exception handlers. Remove the unused code and

parameter pointer slots.  Change it so that the handler address no
longer points into the middle of the handler.

Review URL: http://codereview.chromium.org/119414

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2129 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f6aa7ce3
......@@ -2107,14 +2107,16 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
// Get an external reference to the handler address.
ExternalReference handler_address(Top::k_handler_address);
// The next handler address is at kNextIndex in the stack.
const int kNextIndex = StackHandlerConstants::kNextOffset / kPointerSize;
// If we can fall off the end of the try block, unlink from try chain.
if (has_valid_frame()) {
__ ldr(r1, frame_->ElementAt(kNextIndex));
// The next handler address is on top of the frame. Unlink from
// the handler list and drop the rest of this handler from the
// frame.
ASSERT(StackHandlerConstants::kNextOffset == 0);
frame_->EmitPop(r1);
__ mov(r3, Operand(handler_address));
__ str(r1, MemOperand(r3));
frame_->Drop(StackHandlerConstants::kSize / kPointerSize);
frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
if (has_unlinks) {
exit.Jump();
}
......@@ -2134,15 +2136,11 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
// break from (eg, for...in) may have left stuff on the stack.
__ mov(r3, Operand(handler_address));
__ ldr(sp, MemOperand(r3));
// The stack pointer was restored to just below the code slot
// (the topmost slot) in the handler.
frame_->Forget(frame_->height() - handler_height + 1);
frame_->Forget(frame_->height() - handler_height);
// kNextIndex is off by one because the code slot has already
// been dropped.
__ ldr(r1, frame_->ElementAt(kNextIndex - 1));
ASSERT(StackHandlerConstants::kNextOffset == 0);
frame_->EmitPop(r1);
__ str(r1, MemOperand(r3));
// The code slot has already been dropped from the handler.
frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
if (!function_return_is_shadowed_ && i == kReturnShadowIndex) {
......@@ -2223,15 +2221,15 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
// Get an external reference to the handler address.
ExternalReference handler_address(Top::k_handler_address);
// The next handler address is at kNextIndex in the stack.
const int kNextIndex = StackHandlerConstants::kNextOffset / kPointerSize;
// If we can fall off the end of the try block, unlink from the try
// chain and set the state on the frame to FALLING.
if (has_valid_frame()) {
__ ldr(r1, frame_->ElementAt(kNextIndex));
// The next handler address is on top of the frame.
ASSERT(StackHandlerConstants::kNextOffset == 0);
frame_->EmitPop(r1);
__ mov(r3, Operand(handler_address));
__ str(r1, MemOperand(r3));
frame_->Drop(StackHandlerConstants::kSize / kPointerSize);
frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
// Fake a top of stack value (unneeded when FALLING) and set the
// state in r2, then jump around the unlink blocks if any.
......@@ -2262,17 +2260,14 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
// stack.
__ mov(r3, Operand(handler_address));
__ ldr(sp, MemOperand(r3));
// The stack pointer was restored to the address slot in the handler.
ASSERT(StackHandlerConstants::kNextOffset == 1 * kPointerSize);
frame_->Forget(frame_->height() - handler_height + 1);
frame_->Forget(frame_->height() - handler_height);
// Unlink this handler and drop it from the frame. The next
// handler address is now on top of the frame.
// handler address is currently on top of the frame.
ASSERT(StackHandlerConstants::kNextOffset == 0);
frame_->EmitPop(r1);
__ str(r1, MemOperand(r3));
// The top (code) and the second (handler) slot have both been
// dropped already.
frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 2);
frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
if (i == kReturnShadowIndex) {
// If this label shadowed the function return, materialize the
......@@ -4679,16 +4674,25 @@ void UnarySubStub::Generate(MacroAssembler* masm) {
void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
// r0 holds exception
ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize); // adjust this code
// r0 holds the exception.
// Adjust this code if not the case.
ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
// Drop the sp to the top of the handler.
__ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
__ ldr(sp, MemOperand(r3));
__ pop(r2); // pop next in chain
// Restore the next handler and frame pointer, discard handler state.
ASSERT(StackHandlerConstants::kNextOffset == 0);
__ pop(r2);
__ str(r2, MemOperand(r3));
// restore parameter- and frame-pointer and pop state.
__ ldm(ia_w, sp, r3.bit() | pp.bit() | fp.bit());
// Before returning we restore the context from the frame pointer if not NULL.
// The frame pointer is NULL in the exception handler of a JS entry frame.
ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize);
__ ldm(ia_w, sp, r3.bit() | fp.bit()); // r3: discarded state.
// Before returning we restore the context from the frame pointer if
// not NULL. The frame pointer is NULL in the exception handler of a
// JS entry frame.
__ cmp(fp, Operand(0));
// Set cp to NULL if fp is NULL.
__ mov(cp, Operand(0), LeaveCC, eq);
......@@ -4699,39 +4703,41 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
__ mov(lr, Operand(pc));
}
#endif
ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
__ pop(pc);
}
void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
// Fetch top stack handler.
// Adjust this code if not the case.
ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
// Drop sp to the top stack handler.
__ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
__ ldr(r3, MemOperand(r3));
__ ldr(sp, MemOperand(r3));
// Unwind the handlers until the ENTRY handler is found.
Label loop, done;
__ bind(&loop);
// Load the type of the current stack handler.
const int kStateOffset = StackHandlerConstants::kAddressDisplacement +
StackHandlerConstants::kStateOffset;
__ ldr(r2, MemOperand(r3, kStateOffset));
const int kStateOffset = StackHandlerConstants::kStateOffset;
__ ldr(r2, MemOperand(sp, kStateOffset));
__ cmp(r2, Operand(StackHandler::ENTRY));
__ b(eq, &done);
// Fetch the next handler in the list.
const int kNextOffset = StackHandlerConstants::kAddressDisplacement +
StackHandlerConstants::kNextOffset;
__ ldr(r3, MemOperand(r3, kNextOffset));
const int kNextOffset = StackHandlerConstants::kNextOffset;
__ ldr(sp, MemOperand(sp, kNextOffset));
__ jmp(&loop);
__ bind(&done);
// Set the top handler address to next handler past the current ENTRY handler.
__ ldr(r0, MemOperand(r3, kNextOffset));
__ mov(r2, Operand(ExternalReference(Top::k_handler_address)));
__ str(r0, MemOperand(r2));
ASSERT(StackHandlerConstants::kNextOffset == 0);
__ pop(r0);
__ str(r0, MemOperand(r3));
// Set external caught exception to false.
__ mov(r0, Operand(false));
ExternalReference external_caught(Top::k_external_caught_exception_address);
__ mov(r0, Operand(false));
__ mov(r2, Operand(external_caught));
__ str(r0, MemOperand(r2));
......@@ -4741,21 +4747,17 @@ void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
__ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address)));
__ str(r0, MemOperand(r2));
// Restore the stack to the address of the ENTRY handler
__ mov(sp, Operand(r3));
// Stack layout at this point. See also PushTryHandler
// r3, sp -> next handler
// state (ENTRY)
// pp
// fp
// lr
// Discard ENTRY state (r2 is not used), and restore parameter-
// and frame-pointer and pop state.
__ ldm(ia_w, sp, r2.bit() | r3.bit() | pp.bit() | fp.bit());
// Before returning we restore the context from the frame pointer if not NULL.
// The frame pointer is NULL in the exception handler of a JS entry frame.
// Stack layout at this point. See also StackHandlerConstants.
// sp -> state (ENTRY)
// fp
// lr
// Discard handler state (r2 is not used) and restore frame pointer.
ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize);
__ ldm(ia_w, sp, r2.bit() | fp.bit()); // r2: discarded state.
// Before returning we restore the context from the frame pointer if
// not NULL. The frame pointer is NULL in the exception handler of a
// JS entry frame.
__ cmp(fp, Operand(0));
// Set cp to NULL if fp is NULL.
__ mov(cp, Operand(0), LeaveCC, eq);
......@@ -4766,6 +4768,7 @@ void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
__ mov(lr, Operand(pc));
}
#endif
ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
__ pop(pc);
}
......
......@@ -79,15 +79,11 @@ static const int kNumCalleeSaved = 7 + kR9Available;
class StackHandlerConstants : public AllStatic {
public:
// TODO(1233780): Get rid of the code slot in stack handlers.
static const int kCodeOffset = 0 * kPointerSize;
static const int kNextOffset = 1 * kPointerSize;
static const int kStateOffset = 2 * kPointerSize;
static const int kPPOffset = 3 * kPointerSize;
static const int kFPOffset = 4 * kPointerSize;
static const int kPCOffset = 5 * kPointerSize;
static const int kAddressDisplacement = -1 * kPointerSize;
static const int kNextOffset = 0 * kPointerSize;
static const int kStateOffset = 1 * kPointerSize;
static const int kFPOffset = 2 * kPointerSize;
static const int kPCOffset = 3 * kPointerSize;
static const int kSize = kPCOffset + kPointerSize;
};
......@@ -161,220 +157,6 @@ inline Object* JavaScriptFrame::function_slot_object() const {
}
// ----------------------------------------------------
// lower | Stack |
// addresses | ^ |
// | | |
// | |
// | JS frame |
// | |
// | |
// ----------- +=============+ <--- sp (stack pointer)
// | function |
// +-------------+
// +-------------+
// | |
// | expressions |
// | |
// +-------------+
// | |
// a | locals |
// c | |
// t +- - - - - - -+ <---
// i -4 | local0 | ^
// v +-------------+ |
// a -3 | code | |
// t +-------------+ | kLocal0Offset
// i -2 | context | |
// o +-------------+ |
// n -1 | args_length | v
// +-------------+ <--- fp (frame pointer)
// 0 | caller_pp |
// f +-------------+
// r 1 | caller_fp |
// a +-------------+
// m 2 | sp_on_exit | (pp if return, caller_sp if no return)
// e +-------------+
// 3 | caller_pc |
// +-------------+ <--- caller_sp (incl. parameters)
// | |
// | parameters |
// | |
// +- - - - - - -+ <---
// -2 | parameter0 | ^
// +-------------+ | kParam0Offset
// -1 | receiver | v
// ----------- +=============+ <--- pp (parameter pointer, r10)
// 0 | function |
// +-------------+
// | |
// |caller-saved | (must be valid JS values, traversed during GC)
// | regs |
// | |
// +-------------+
// | |
// | caller |
// higher | expressions |
// addresses | |
// | |
// | JS frame |
// Handler frames (part of expressions of JS frames):
// lower | Stack |
// addresses | ^ |
// | | |
// | |
// h | expressions |
// a | |
// n +-------------+
// d -1 | code |
// l +-------------+ <--- handler sp
// e 0 | next_sp | link to next handler (next handler's sp)
// r +-------------+
// 1 | state |
// f +-------------+
// r 2 | pp |
// a +-------------+
// m 3 | fp |
// e +-------------+
// 4 | pc |
// +-------------+
// | |
// higher | expressions |
// addresses | |
// JS entry frames: When calling from C to JS, we construct two extra
// frames: An entry frame (C) and a trampoline frame (JS). The
// following pictures shows the two frames:
// lower | Stack |
// addresses | ^ |
// | | |
// | |
// | JS frame |
// | |
// | |
// ----------- +=============+ <--- sp (stack pointer)
// | |
// | parameters |
// t | |
// r +- - - - - - -+
// a | parameter0 |
// m +-------------+
// p | receiver |
// o +-------------+
// l | function |
// i +-------------+
// n -3 | code |
// e +-------------+
// -2 | NULL | context is always NULL
// +-------------+
// f -1 | 0 | args_length is always zero
// r +-------------+ <--- fp (frame pointer)
// a 0 | NULL | caller pp is always NULL for entries
// m +-------------+
// e 1 | caller_fp |
// +-------------+
// 2 | sp_on_exit | (caller_sp)
// +-------------+
// 3 | caller_pc |
// ----------- +=============+ <--- caller_sp == pp
// . ^
// . | try-handler, fake, not GC'ed
// . v
// +-------------+ <---
// -2 | next top pp |
// +-------------+
// -1 | next top fp |
// +-------------+ <--- fp
// | r4 | r4-r9 holding non-JS values must be preserved
// +-------------+
// J | r5 | before being initialized not to confuse GC
// S +-------------+
// | r6 |
// +-------------+
// e | r7 |
// n +-------------+
// t | r8 |
// r +-------------+
// y [ | r9 | ] only if r9 available
// +-------------+
// | r10 |
// f +-------------+
// r | r11 |
// a +-------------+
// m | caller_sp |
// e +-------------+
// | caller_pc |
// +-------------+ <--- caller_sp
// | argv | passed on stack from C code
// +-------------+
// | |
// higher | |
// addresses | C frame |
// The first 4 args are passed from C in r0-r3 and are not spilled on entry:
// r0: code entry
// r1: function
// r2: receiver
// r3: argc
// [sp+0]: argv
// C entry frames: When calling from JS to C, we construct one extra
// frame:
// lower | Stack |
// addresses | ^ |
// | | |
// | |
// | C frame |
// | |
// | |
// ----------- +=============+ <--- sp (stack pointer)
// | |
// | parameters | (first 4 args are passed in r0-r3)
// | |
// +-------------+ <--- fp (frame pointer)
// f 4/5 | caller_fp |
// r +-------------+
// a 5/6 | sp_on_exit | (pp)
// m +-------------+
// e 6/7 | caller_pc |
// +-------------+ <--- caller_sp (incl. parameters)
// 7/8 | |
// | parameters |
// | |
// +- - - - - - -+ <---
// -2 | parameter0 | ^
// +-------------+ | kParam0Offset
// -1 | receiver | v
// ----------- +=============+ <--- pp (parameter pointer, r10)
// 0 | function |
// +-------------+
// | |
// |caller-saved |
// | regs |
// | |
// +-------------+
// | |
// | caller |
// | expressions |
// | |
// higher | |
// addresses | JS frame |
} } // namespace v8::internal
#endif // V8_ARM_FRAMES_ARM_H_
......@@ -557,41 +557,48 @@ void MacroAssembler::CopyRegistersFromStackToMemory(Register base,
}
#endif
void MacroAssembler::PushTryHandler(CodeLocation try_location,
HandlerType type) {
ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize); // adjust this code
// Adjust this code if not the case.
ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
// The pc (return address) is passed in register lr.
if (try_location == IN_JAVASCRIPT) {
stm(db_w, sp, pp.bit() | fp.bit() | lr.bit());
if (type == TRY_CATCH_HANDLER) {
mov(r3, Operand(StackHandler::TRY_CATCH));
} else {
mov(r3, Operand(StackHandler::TRY_FINALLY));
}
push(r3); // state
ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize
&& StackHandlerConstants::kFPOffset == 2 * kPointerSize
&& StackHandlerConstants::kPCOffset == 3 * kPointerSize);
stm(db_w, sp, r3.bit() | fp.bit() | lr.bit());
// Save the current handler as the next handler.
mov(r3, Operand(ExternalReference(Top::k_handler_address)));
ldr(r1, MemOperand(r3));
push(r1); // next sp
str(sp, MemOperand(r3)); // chain handler
mov(r0, Operand(Smi::FromInt(StackHandler::kCodeNotPresent))); // new TOS
push(r0);
ASSERT(StackHandlerConstants::kNextOffset == 0);
push(r1);
// Link this handler as the new current one.
str(sp, MemOperand(r3));
} else {
// Must preserve r0-r4, r5-r7 are available.
ASSERT(try_location == IN_JS_ENTRY);
// The parameter pointer is meaningless here and fp does not point to a JS
// frame. So we save NULL for both pp and fp. We expect the code throwing an
// exception to check fp before dereferencing it to restore the context.
mov(pp, Operand(0)); // set pp to NULL
mov(ip, Operand(0)); // to save a NULL fp
stm(db_w, sp, pp.bit() | ip.bit() | lr.bit());
// The frame pointer does not point to a JS frame so we save NULL
// for fp. We expect the code throwing an exception to check fp
// before dereferencing it to restore the context.
mov(ip, Operand(0)); // To save a NULL frame pointer.
mov(r6, Operand(StackHandler::ENTRY));
push(r6); // state
ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize
&& StackHandlerConstants::kFPOffset == 2 * kPointerSize
&& StackHandlerConstants::kPCOffset == 3 * kPointerSize);
stm(db_w, sp, r6.bit() | ip.bit() | lr.bit());
// Save the current handler as the next handler.
mov(r7, Operand(ExternalReference(Top::k_handler_address)));
ldr(r6, MemOperand(r7));
push(r6); // next sp
str(sp, MemOperand(r7)); // chain handler
mov(r5, Operand(Smi::FromInt(StackHandler::kCodeNotPresent))); // new TOS
push(r5); // flush TOS
ASSERT(StackHandlerConstants::kNextOffset == 0);
push(r6);
// Link this handler as the new current one.
str(sp, MemOperand(r7));
}
}
......
......@@ -230,8 +230,8 @@ void VirtualFrame::StoreToFrameSlotAt(int index) {
void VirtualFrame::PushTryHandler(HandlerType type) {
// Grow the expression stack by handler size less one (the return address
// is already pushed by a call instruction).
// Grow the expression stack by handler size less one (the return
// address in lr is already counted by a call instruction).
Adjust(kHandlerSize - 1);
__ PushTryHandler(IN_JAVASCRIPT, type);
}
......
......@@ -43,13 +43,7 @@ namespace internal {
inline Address StackHandler::address() const {
// NOTE: There's an obvious problem with the address of the NULL
// stack handler. Right now, it benefits us that the subtraction
// leads to a very high address (above everything else on the
// stack), but maybe we should stop relying on it?
const int displacement = StackHandlerConstants::kAddressDisplacement;
Address address = reinterpret_cast<Address>(const_cast<StackHandler*>(this));
return address + displacement;
return reinterpret_cast<Address>(const_cast<StackHandler*>(this));
}
......
......@@ -78,9 +78,6 @@ class StackHandler BASE_EMBEDDED {
void Cook(Code* code);
void Uncook(Code* code);
// TODO(1233780): Get rid of the code slot in stack handlers.
static const int kCodeNotPresent = 0;
private:
// Accessors.
inline State state() const;
......
......@@ -3252,7 +3252,6 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
// Make sure that there's nothing left on the stack above the
// handler structure.
if (FLAG_debug_code) {
ASSERT(StackHandlerConstants::kAddressDisplacement == 0);
__ mov(eax, Operand::StaticVariable(handler_address));
__ cmp(esp, Operand(eax));
__ Assert(equal, "stack pointer should point to top handler");
......@@ -3291,7 +3290,6 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
// Reload sp from the top handler, because some statements that we
// break from (eg, for...in) may have left stuff on the stack.
ASSERT(StackHandlerConstants::kAddressDisplacement == 0);
__ mov(esp, Operand::StaticVariable(handler_address));
frame_->Forget(frame_->height() - handler_height);
......@@ -3416,7 +3414,6 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
// Reload sp from the top handler, because some statements that
// we break from (eg, for...in) may have left stuff on the
// stack.
ASSERT(StackHandlerConstants::kAddressDisplacement == 0);
__ mov(esp, Operand::StaticVariable(handler_address));
frame_->Forget(frame_->height() - handler_height);
......@@ -6955,11 +6952,12 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
// eax holds the exception.
// Adjust this code if not the case.
ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
// Drop the sp to the top of the handler.
ASSERT(StackHandlerConstants::kAddressDisplacement == 0);
ExternalReference handler_address(Top::k_handler_address);
__ mov(esp, Operand::StaticVariable(handler_address));
......@@ -6970,9 +6968,10 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
__ pop(ebp);
__ pop(edx); // Remove state.
// Before returning we restore the context from the frame pointer if not NULL.
// The frame pointer is NULL in the exception handler of a JS entry frame.
__ xor_(esi, Operand(esi)); // tentatively set context pointer to NULL
// Before returning we restore the context from the frame pointer if
// not NULL. The frame pointer is NULL in the exception handler of
// a JS entry frame.
__ xor_(esi, Operand(esi)); // Tentatively set context pointer to NULL.
Label skip;
__ cmp(ebp, 0);
__ j(equal, &skip, not_taken);
......@@ -7069,7 +7068,6 @@ void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
// Drop sp to the top stack handler.
ASSERT(StackHandlerConstants::kAddressDisplacement == 0);
ExternalReference handler_address(Top::k_handler_address);
__ mov(esp, Operand::StaticVariable(handler_address));
......
......@@ -59,7 +59,6 @@ class StackHandlerConstants : public AllStatic {
static const int kStateOffset = 2 * kPointerSize;
static const int kPCOffset = 3 * kPointerSize;
static const int kAddressDisplacement = 0;
static const int kSize = kPCOffset + kPointerSize;
};
......
......@@ -460,12 +460,11 @@ void MacroAssembler::PushTryHandler(CodeLocation try_location,
push(ebp);
} else {
ASSERT(try_location == IN_JS_ENTRY);
// The parameter pointer is meaningless here and ebp does not
// point to a JS frame. So we save NULL for both pp and ebp. We
// expect the code throwing an exception to check ebp before
// dereferencing it to restore the context.
// The frame pointer does not point to a JS frame so we save NULL
// for ebp. We expect the code throwing an exception to check ebp
// before dereferencing it to restore the context.
push(Immediate(StackHandler::ENTRY));
push(Immediate(0)); // NULL frame pointer
push(Immediate(0)); // NULL frame pointer.
}
// Save the current handler as the next handler.
push(Operand::StaticVariable(ExternalReference(Top::k_handler_address)));
......
......@@ -281,7 +281,6 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
// Invoke: Link this frame into the handler chain.
__ bind(&invoke);
__ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER);
__ push(rax); // flush TOS
// Clear any pending exceptions.
__ load_rax(ExternalReference::the_hole_value_location());
......
......@@ -42,16 +42,11 @@ typedef Object* JSCallerSavedBuffer[kNumJSCallerSaved];
class StackHandlerConstants : public AllStatic {
public:
static const int kNextOffset = 0 * kPointerSize;
static const int kPPOffset = 1 * kPointerSize;
static const int kFPOffset = 2 * kPointerSize;
static const int kFPOffset = 1 * kPointerSize;
static const int kStateOffset = 2 * kPointerSize;
static const int kPCOffset = 3 * kPointerSize;
static const int kCodeOffset = 3 * kPointerSize;
static const int kStateOffset = 4 * kPointerSize;
static const int kPCOffset = 5 * kPointerSize;
static const int kAddressDisplacement = -1 * kPointerSize;
static const int kSize = 6 * kPointerSize;
static const int kSize = 4 * kPointerSize;
};
......
......@@ -73,16 +73,17 @@ void MacroAssembler::Set(const Operand& dst, int64_t x) {
void MacroAssembler::PushTryHandler(CodeLocation try_location,
HandlerType type) {
// The pc (return address) is already on TOS.
// This code pushes state, code, frame pointer and parameter pointer.
// Check that they are expected next on the stack, int that order.
// Adjust this code if not the case.
ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
// The pc (return address) is already on TOS. This code pushes state,
// frame pointer and current handler. Check that they are expected
// next on the stack, in that order.
ASSERT_EQ(StackHandlerConstants::kStateOffset,
StackHandlerConstants::kPCOffset - kPointerSize);
ASSERT_EQ(StackHandlerConstants::kCodeOffset,
StackHandlerConstants::kStateOffset - kPointerSize);
ASSERT_EQ(StackHandlerConstants::kFPOffset,
StackHandlerConstants::kCodeOffset - kPointerSize);
ASSERT_EQ(StackHandlerConstants::kPPOffset,
StackHandlerConstants::kStateOffset - kPointerSize);
ASSERT_EQ(StackHandlerConstants::kNextOffset,
StackHandlerConstants::kFPOffset - kPointerSize);
if (try_location == IN_JAVASCRIPT) {
......@@ -91,23 +92,18 @@ void MacroAssembler::PushTryHandler(CodeLocation try_location,
} else {
push(Immediate(StackHandler::TRY_FINALLY));
}
push(Immediate(Smi::FromInt(StackHandler::kCodeNotPresent)));
push(rbp);
push(rdi);
} else {
ASSERT(try_location == IN_JS_ENTRY);
// The parameter pointer is meaningless here and ebp does not
// point to a JS frame. So we save NULL for both pp and ebp. We
// expect the code throwing an exception to check ebp before
// dereferencing it to restore the context.
// The frame pointer does not point to a JS frame so we save NULL
// for rbp. We expect the code throwing an exception to check rbp
// before dereferencing it to restore the context.
push(Immediate(StackHandler::ENTRY));
push(Immediate(Smi::FromInt(StackHandler::kCodeNotPresent)));
push(Immediate(0)); // NULL frame pointer
push(Immediate(0)); // NULL parameter pointer
push(Immediate(0)); // NULL frame pointer.
}
// Save the current handler.
movq(kScratchRegister, ExternalReference(Top::k_handler_address));
// Cached TOS.
movq(rax, Operand(kScratchRegister, 0));
push(Operand(kScratchRegister, 0));
// Link this handler.
movq(Operand(kScratchRegister, 0), rsp);
}
......
......@@ -159,9 +159,8 @@ class MacroAssembler: public Assembler {
// ---------------------------------------------------------------------------
// Exception handling
// Push a new try handler and link into try handler chain.
// The return address must be pushed before calling this helper.
// On exit, rax contains TOS (next_sp).
// Push a new try handler and link into try handler chain. The return
// address must be pushed before calling this helper.
void PushTryHandler(CodeLocation try_location, HandlerType type);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment