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) { ...@@ -2107,14 +2107,16 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
// Get an external reference to the handler address. // Get an external reference to the handler address.
ExternalReference handler_address(Top::k_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 we can fall off the end of the try block, unlink from try chain.
if (has_valid_frame()) { 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)); __ mov(r3, Operand(handler_address));
__ str(r1, MemOperand(r3)); __ str(r1, MemOperand(r3));
frame_->Drop(StackHandlerConstants::kSize / kPointerSize); frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
if (has_unlinks) { if (has_unlinks) {
exit.Jump(); exit.Jump();
} }
...@@ -2134,15 +2136,11 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) { ...@@ -2134,15 +2136,11 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
// break from (eg, for...in) may have left stuff on the stack. // break from (eg, for...in) may have left stuff on the stack.
__ mov(r3, Operand(handler_address)); __ mov(r3, Operand(handler_address));
__ ldr(sp, MemOperand(r3)); __ ldr(sp, MemOperand(r3));
// The stack pointer was restored to just below the code slot frame_->Forget(frame_->height() - handler_height);
// (the topmost slot) in the handler.
frame_->Forget(frame_->height() - handler_height + 1);
// kNextIndex is off by one because the code slot has already ASSERT(StackHandlerConstants::kNextOffset == 0);
// been dropped. frame_->EmitPop(r1);
__ ldr(r1, frame_->ElementAt(kNextIndex - 1));
__ str(r1, MemOperand(r3)); __ str(r1, MemOperand(r3));
// The code slot has already been dropped from the handler.
frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
if (!function_return_is_shadowed_ && i == kReturnShadowIndex) { if (!function_return_is_shadowed_ && i == kReturnShadowIndex) {
...@@ -2223,15 +2221,15 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) { ...@@ -2223,15 +2221,15 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
// Get an external reference to the handler address. // Get an external reference to the handler address.
ExternalReference handler_address(Top::k_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 // 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. // chain and set the state on the frame to FALLING.
if (has_valid_frame()) { 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)); __ mov(r3, Operand(handler_address));
__ str(r1, MemOperand(r3)); __ 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 // Fake a top of stack value (unneeded when FALLING) and set the
// state in r2, then jump around the unlink blocks if any. // state in r2, then jump around the unlink blocks if any.
...@@ -2262,17 +2260,14 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) { ...@@ -2262,17 +2260,14 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
// stack. // stack.
__ mov(r3, Operand(handler_address)); __ mov(r3, Operand(handler_address));
__ ldr(sp, MemOperand(r3)); __ ldr(sp, MemOperand(r3));
// The stack pointer was restored to the address slot in the handler. frame_->Forget(frame_->height() - handler_height);
ASSERT(StackHandlerConstants::kNextOffset == 1 * kPointerSize);
frame_->Forget(frame_->height() - handler_height + 1);
// Unlink this handler and drop it from the frame. The next // 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); frame_->EmitPop(r1);
__ str(r1, MemOperand(r3)); __ str(r1, MemOperand(r3));
// The top (code) and the second (handler) slot have both been frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
// dropped already.
frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 2);
if (i == kReturnShadowIndex) { if (i == kReturnShadowIndex) {
// If this label shadowed the function return, materialize the // If this label shadowed the function return, materialize the
...@@ -4679,16 +4674,25 @@ void UnarySubStub::Generate(MacroAssembler* masm) { ...@@ -4679,16 +4674,25 @@ void UnarySubStub::Generate(MacroAssembler* masm) {
void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
// r0 holds exception // r0 holds the exception.
ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize); // adjust this code
// 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))); __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
__ ldr(sp, MemOperand(r3)); __ 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)); __ str(r2, MemOperand(r3));
// restore parameter- and frame-pointer and pop state. ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize);
__ ldm(ia_w, sp, r3.bit() | pp.bit() | fp.bit()); __ 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. // 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)); __ cmp(fp, Operand(0));
// Set cp to NULL if fp is NULL. // Set cp to NULL if fp is NULL.
__ mov(cp, Operand(0), LeaveCC, eq); __ mov(cp, Operand(0), LeaveCC, eq);
...@@ -4699,39 +4703,41 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { ...@@ -4699,39 +4703,41 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
__ mov(lr, Operand(pc)); __ mov(lr, Operand(pc));
} }
#endif #endif
ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
__ pop(pc); __ pop(pc);
} }
void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) { 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))); __ 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. // Unwind the handlers until the ENTRY handler is found.
Label loop, done; Label loop, done;
__ bind(&loop); __ bind(&loop);
// Load the type of the current stack handler. // Load the type of the current stack handler.
const int kStateOffset = StackHandlerConstants::kAddressDisplacement + const int kStateOffset = StackHandlerConstants::kStateOffset;
StackHandlerConstants::kStateOffset; __ ldr(r2, MemOperand(sp, kStateOffset));
__ ldr(r2, MemOperand(r3, kStateOffset));
__ cmp(r2, Operand(StackHandler::ENTRY)); __ cmp(r2, Operand(StackHandler::ENTRY));
__ b(eq, &done); __ b(eq, &done);
// Fetch the next handler in the list. // Fetch the next handler in the list.
const int kNextOffset = StackHandlerConstants::kAddressDisplacement + const int kNextOffset = StackHandlerConstants::kNextOffset;
StackHandlerConstants::kNextOffset; __ ldr(sp, MemOperand(sp, kNextOffset));
__ ldr(r3, MemOperand(r3, kNextOffset));
__ jmp(&loop); __ jmp(&loop);
__ bind(&done); __ bind(&done);
// Set the top handler address to next handler past the current ENTRY handler. // Set the top handler address to next handler past the current ENTRY handler.
__ ldr(r0, MemOperand(r3, kNextOffset)); ASSERT(StackHandlerConstants::kNextOffset == 0);
__ mov(r2, Operand(ExternalReference(Top::k_handler_address))); __ pop(r0);
__ str(r0, MemOperand(r2)); __ str(r0, MemOperand(r3));
// Set external caught exception to false. // Set external caught exception to false.
__ mov(r0, Operand(false));
ExternalReference external_caught(Top::k_external_caught_exception_address); ExternalReference external_caught(Top::k_external_caught_exception_address);
__ mov(r0, Operand(false));
__ mov(r2, Operand(external_caught)); __ mov(r2, Operand(external_caught));
__ str(r0, MemOperand(r2)); __ str(r0, MemOperand(r2));
...@@ -4741,21 +4747,17 @@ void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) { ...@@ -4741,21 +4747,17 @@ void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
__ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address))); __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address)));
__ str(r0, MemOperand(r2)); __ str(r0, MemOperand(r2));
// Restore the stack to the address of the ENTRY handler // Stack layout at this point. See also StackHandlerConstants.
__ mov(sp, Operand(r3)); // sp -> state (ENTRY)
// fp
// Stack layout at this point. See also PushTryHandler // lr
// r3, sp -> next handler
// state (ENTRY) // Discard handler state (r2 is not used) and restore frame pointer.
// pp ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize);
// fp __ ldm(ia_w, sp, r2.bit() | fp.bit()); // r2: discarded state.
// lr // Before returning we restore the context from the frame pointer if
// not NULL. The frame pointer is NULL in the exception handler of a
// Discard ENTRY state (r2 is not used), and restore parameter- // JS entry frame.
// 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.
__ cmp(fp, Operand(0)); __ cmp(fp, Operand(0));
// Set cp to NULL if fp is NULL. // Set cp to NULL if fp is NULL.
__ mov(cp, Operand(0), LeaveCC, eq); __ mov(cp, Operand(0), LeaveCC, eq);
...@@ -4766,6 +4768,7 @@ void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) { ...@@ -4766,6 +4768,7 @@ void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
__ mov(lr, Operand(pc)); __ mov(lr, Operand(pc));
} }
#endif #endif
ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
__ pop(pc); __ pop(pc);
} }
......
...@@ -79,15 +79,11 @@ static const int kNumCalleeSaved = 7 + kR9Available; ...@@ -79,15 +79,11 @@ static const int kNumCalleeSaved = 7 + kR9Available;
class StackHandlerConstants : public AllStatic { class StackHandlerConstants : public AllStatic {
public: public:
// TODO(1233780): Get rid of the code slot in stack handlers. static const int kNextOffset = 0 * kPointerSize;
static const int kCodeOffset = 0 * kPointerSize; static const int kStateOffset = 1 * kPointerSize;
static const int kNextOffset = 1 * kPointerSize; static const int kFPOffset = 2 * kPointerSize;
static const int kStateOffset = 2 * kPointerSize; static const int kPCOffset = 3 * 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 kSize = kPCOffset + kPointerSize; static const int kSize = kPCOffset + kPointerSize;
}; };
...@@ -161,220 +157,6 @@ inline Object* JavaScriptFrame::function_slot_object() const { ...@@ -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 } } // namespace v8::internal
#endif // V8_ARM_FRAMES_ARM_H_ #endif // V8_ARM_FRAMES_ARM_H_
...@@ -557,41 +557,48 @@ void MacroAssembler::CopyRegistersFromStackToMemory(Register base, ...@@ -557,41 +557,48 @@ void MacroAssembler::CopyRegistersFromStackToMemory(Register base,
} }
#endif #endif
void MacroAssembler::PushTryHandler(CodeLocation try_location, void MacroAssembler::PushTryHandler(CodeLocation try_location,
HandlerType type) { 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. // The pc (return address) is passed in register lr.
if (try_location == IN_JAVASCRIPT) { if (try_location == IN_JAVASCRIPT) {
stm(db_w, sp, pp.bit() | fp.bit() | lr.bit());
if (type == TRY_CATCH_HANDLER) { if (type == TRY_CATCH_HANDLER) {
mov(r3, Operand(StackHandler::TRY_CATCH)); mov(r3, Operand(StackHandler::TRY_CATCH));
} else { } else {
mov(r3, Operand(StackHandler::TRY_FINALLY)); 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))); mov(r3, Operand(ExternalReference(Top::k_handler_address)));
ldr(r1, MemOperand(r3)); ldr(r1, MemOperand(r3));
push(r1); // next sp ASSERT(StackHandlerConstants::kNextOffset == 0);
str(sp, MemOperand(r3)); // chain handler push(r1);
mov(r0, Operand(Smi::FromInt(StackHandler::kCodeNotPresent))); // new TOS // Link this handler as the new current one.
push(r0); str(sp, MemOperand(r3));
} else { } else {
// Must preserve r0-r4, r5-r7 are available. // Must preserve r0-r4, r5-r7 are available.
ASSERT(try_location == IN_JS_ENTRY); ASSERT(try_location == IN_JS_ENTRY);
// The parameter pointer is meaningless here and fp does not point to a JS // The frame pointer does not point to a JS frame so we save NULL
// frame. So we save NULL for both pp and fp. We expect the code throwing an // for fp. We expect the code throwing an exception to check fp
// exception to check fp before dereferencing it to restore the context. // before dereferencing it to restore the context.
mov(pp, Operand(0)); // set pp to NULL mov(ip, Operand(0)); // To save a NULL frame pointer.
mov(ip, Operand(0)); // to save a NULL fp
stm(db_w, sp, pp.bit() | ip.bit() | lr.bit());
mov(r6, Operand(StackHandler::ENTRY)); 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))); mov(r7, Operand(ExternalReference(Top::k_handler_address)));
ldr(r6, MemOperand(r7)); ldr(r6, MemOperand(r7));
push(r6); // next sp ASSERT(StackHandlerConstants::kNextOffset == 0);
str(sp, MemOperand(r7)); // chain handler push(r6);
mov(r5, Operand(Smi::FromInt(StackHandler::kCodeNotPresent))); // new TOS // Link this handler as the new current one.
push(r5); // flush TOS str(sp, MemOperand(r7));
} }
} }
......
...@@ -230,8 +230,8 @@ void VirtualFrame::StoreToFrameSlotAt(int index) { ...@@ -230,8 +230,8 @@ void VirtualFrame::StoreToFrameSlotAt(int index) {
void VirtualFrame::PushTryHandler(HandlerType type) { void VirtualFrame::PushTryHandler(HandlerType type) {
// Grow the expression stack by handler size less one (the return address // Grow the expression stack by handler size less one (the return
// is already pushed by a call instruction). // address in lr is already counted by a call instruction).
Adjust(kHandlerSize - 1); Adjust(kHandlerSize - 1);
__ PushTryHandler(IN_JAVASCRIPT, type); __ PushTryHandler(IN_JAVASCRIPT, type);
} }
......
...@@ -43,13 +43,7 @@ namespace internal { ...@@ -43,13 +43,7 @@ namespace internal {
inline Address StackHandler::address() const { inline Address StackHandler::address() const {
// NOTE: There's an obvious problem with the address of the NULL return reinterpret_cast<Address>(const_cast<StackHandler*>(this));
// 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;
} }
......
...@@ -78,9 +78,6 @@ class StackHandler BASE_EMBEDDED { ...@@ -78,9 +78,6 @@ class StackHandler BASE_EMBEDDED {
void Cook(Code* code); void Cook(Code* code);
void Uncook(Code* code); void Uncook(Code* code);
// TODO(1233780): Get rid of the code slot in stack handlers.
static const int kCodeNotPresent = 0;
private: private:
// Accessors. // Accessors.
inline State state() const; inline State state() const;
......
...@@ -3252,7 +3252,6 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) { ...@@ -3252,7 +3252,6 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
// Make sure that there's nothing left on the stack above the // Make sure that there's nothing left on the stack above the
// handler structure. // handler structure.
if (FLAG_debug_code) { if (FLAG_debug_code) {
ASSERT(StackHandlerConstants::kAddressDisplacement == 0);
__ mov(eax, Operand::StaticVariable(handler_address)); __ mov(eax, Operand::StaticVariable(handler_address));
__ cmp(esp, Operand(eax)); __ cmp(esp, Operand(eax));
__ Assert(equal, "stack pointer should point to top handler"); __ Assert(equal, "stack pointer should point to top handler");
...@@ -3291,7 +3290,6 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) { ...@@ -3291,7 +3290,6 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
// Reload sp from the top handler, because some statements that we // Reload sp from the top handler, because some statements that we
// break from (eg, for...in) may have left stuff on the stack. // break from (eg, for...in) may have left stuff on the stack.
ASSERT(StackHandlerConstants::kAddressDisplacement == 0);
__ mov(esp, Operand::StaticVariable(handler_address)); __ mov(esp, Operand::StaticVariable(handler_address));
frame_->Forget(frame_->height() - handler_height); frame_->Forget(frame_->height() - handler_height);
...@@ -3416,7 +3414,6 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) { ...@@ -3416,7 +3414,6 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
// Reload sp from the top handler, because some statements that // Reload sp from the top handler, because some statements that
// we break from (eg, for...in) may have left stuff on the // we break from (eg, for...in) may have left stuff on the
// stack. // stack.
ASSERT(StackHandlerConstants::kAddressDisplacement == 0);
__ mov(esp, Operand::StaticVariable(handler_address)); __ mov(esp, Operand::StaticVariable(handler_address));
frame_->Forget(frame_->height() - handler_height); frame_->Forget(frame_->height() - handler_height);
...@@ -6955,11 +6952,12 @@ void CallFunctionStub::Generate(MacroAssembler* masm) { ...@@ -6955,11 +6952,12 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
// eax holds the exception.
// Adjust this code if not the case. // Adjust this code if not the case.
ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
// Drop the sp to the top of the handler. // Drop the sp to the top of the handler.
ASSERT(StackHandlerConstants::kAddressDisplacement == 0);
ExternalReference handler_address(Top::k_handler_address); ExternalReference handler_address(Top::k_handler_address);
__ mov(esp, Operand::StaticVariable(handler_address)); __ mov(esp, Operand::StaticVariable(handler_address));
...@@ -6970,9 +6968,10 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { ...@@ -6970,9 +6968,10 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
__ pop(ebp); __ pop(ebp);
__ pop(edx); // Remove state. __ pop(edx); // Remove state.
// Before returning we restore the context from the frame pointer if not NULL. // Before returning we restore the context from the frame pointer if
// The frame pointer is NULL in the exception handler of a JS entry frame. // not NULL. The frame pointer is NULL in the exception handler of
__ xor_(esi, Operand(esi)); // tentatively set context pointer to NULL // a JS entry frame.
__ xor_(esi, Operand(esi)); // Tentatively set context pointer to NULL.
Label skip; Label skip;
__ cmp(ebp, 0); __ cmp(ebp, 0);
__ j(equal, &skip, not_taken); __ j(equal, &skip, not_taken);
...@@ -7069,7 +7068,6 @@ void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) { ...@@ -7069,7 +7068,6 @@ void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
// Drop sp to the top stack handler. // Drop sp to the top stack handler.
ASSERT(StackHandlerConstants::kAddressDisplacement == 0);
ExternalReference handler_address(Top::k_handler_address); ExternalReference handler_address(Top::k_handler_address);
__ mov(esp, Operand::StaticVariable(handler_address)); __ mov(esp, Operand::StaticVariable(handler_address));
......
...@@ -59,7 +59,6 @@ class StackHandlerConstants : public AllStatic { ...@@ -59,7 +59,6 @@ class StackHandlerConstants : public AllStatic {
static const int kStateOffset = 2 * kPointerSize; static const int kStateOffset = 2 * kPointerSize;
static const int kPCOffset = 3 * kPointerSize; static const int kPCOffset = 3 * kPointerSize;
static const int kAddressDisplacement = 0;
static const int kSize = kPCOffset + kPointerSize; static const int kSize = kPCOffset + kPointerSize;
}; };
......
...@@ -460,12 +460,11 @@ void MacroAssembler::PushTryHandler(CodeLocation try_location, ...@@ -460,12 +460,11 @@ void MacroAssembler::PushTryHandler(CodeLocation try_location,
push(ebp); push(ebp);
} else { } else {
ASSERT(try_location == IN_JS_ENTRY); ASSERT(try_location == IN_JS_ENTRY);
// The parameter pointer is meaningless here and ebp does not // The frame pointer does not point to a JS frame so we save NULL
// point to a JS frame. So we save NULL for both pp and ebp. We // for ebp. We expect the code throwing an exception to check ebp
// expect the code throwing an exception to check ebp before // before dereferencing it to restore the context.
// dereferencing it to restore the context.
push(Immediate(StackHandler::ENTRY)); push(Immediate(StackHandler::ENTRY));
push(Immediate(0)); // NULL frame pointer push(Immediate(0)); // NULL frame pointer.
} }
// Save the current handler as the next handler. // Save the current handler as the next handler.
push(Operand::StaticVariable(ExternalReference(Top::k_handler_address))); push(Operand::StaticVariable(ExternalReference(Top::k_handler_address)));
......
...@@ -281,7 +281,6 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { ...@@ -281,7 +281,6 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
// Invoke: Link this frame into the handler chain. // Invoke: Link this frame into the handler chain.
__ bind(&invoke); __ bind(&invoke);
__ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER); __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER);
__ push(rax); // flush TOS
// Clear any pending exceptions. // Clear any pending exceptions.
__ load_rax(ExternalReference::the_hole_value_location()); __ load_rax(ExternalReference::the_hole_value_location());
......
...@@ -42,16 +42,11 @@ typedef Object* JSCallerSavedBuffer[kNumJSCallerSaved]; ...@@ -42,16 +42,11 @@ typedef Object* JSCallerSavedBuffer[kNumJSCallerSaved];
class StackHandlerConstants : public AllStatic { class StackHandlerConstants : public AllStatic {
public: public:
static const int kNextOffset = 0 * kPointerSize; static const int kNextOffset = 0 * kPointerSize;
static const int kPPOffset = 1 * kPointerSize; static const int kFPOffset = 1 * kPointerSize;
static const int kFPOffset = 2 * kPointerSize; static const int kStateOffset = 2 * kPointerSize;
static const int kPCOffset = 3 * kPointerSize;
static const int kCodeOffset = 3 * kPointerSize; static const int kSize = 4 * 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;
}; };
......
...@@ -73,16 +73,17 @@ void MacroAssembler::Set(const Operand& dst, int64_t x) { ...@@ -73,16 +73,17 @@ void MacroAssembler::Set(const Operand& dst, int64_t x) {
void MacroAssembler::PushTryHandler(CodeLocation try_location, void MacroAssembler::PushTryHandler(CodeLocation try_location,
HandlerType type) { HandlerType type) {
// The pc (return address) is already on TOS. // Adjust this code if not the case.
// This code pushes state, code, frame pointer and parameter pointer. ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
// Check that they are expected next on the stack, int that order.
// 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, ASSERT_EQ(StackHandlerConstants::kStateOffset,
StackHandlerConstants::kPCOffset - kPointerSize); StackHandlerConstants::kPCOffset - kPointerSize);
ASSERT_EQ(StackHandlerConstants::kCodeOffset,
StackHandlerConstants::kStateOffset - kPointerSize);
ASSERT_EQ(StackHandlerConstants::kFPOffset, ASSERT_EQ(StackHandlerConstants::kFPOffset,
StackHandlerConstants::kCodeOffset - kPointerSize); StackHandlerConstants::kStateOffset - kPointerSize);
ASSERT_EQ(StackHandlerConstants::kPPOffset, ASSERT_EQ(StackHandlerConstants::kNextOffset,
StackHandlerConstants::kFPOffset - kPointerSize); StackHandlerConstants::kFPOffset - kPointerSize);
if (try_location == IN_JAVASCRIPT) { if (try_location == IN_JAVASCRIPT) {
...@@ -91,23 +92,18 @@ void MacroAssembler::PushTryHandler(CodeLocation try_location, ...@@ -91,23 +92,18 @@ void MacroAssembler::PushTryHandler(CodeLocation try_location,
} else { } else {
push(Immediate(StackHandler::TRY_FINALLY)); push(Immediate(StackHandler::TRY_FINALLY));
} }
push(Immediate(Smi::FromInt(StackHandler::kCodeNotPresent)));
push(rbp); push(rbp);
push(rdi);
} else { } else {
ASSERT(try_location == IN_JS_ENTRY); ASSERT(try_location == IN_JS_ENTRY);
// The parameter pointer is meaningless here and ebp does not // The frame pointer does not point to a JS frame so we save NULL
// point to a JS frame. So we save NULL for both pp and ebp. We // for rbp. We expect the code throwing an exception to check rbp
// expect the code throwing an exception to check ebp before // before dereferencing it to restore the context.
// dereferencing it to restore the context.
push(Immediate(StackHandler::ENTRY)); push(Immediate(StackHandler::ENTRY));
push(Immediate(Smi::FromInt(StackHandler::kCodeNotPresent))); push(Immediate(0)); // NULL frame pointer.
push(Immediate(0)); // NULL frame pointer
push(Immediate(0)); // NULL parameter pointer
} }
// Save the current handler.
movq(kScratchRegister, ExternalReference(Top::k_handler_address)); movq(kScratchRegister, ExternalReference(Top::k_handler_address));
// Cached TOS. push(Operand(kScratchRegister, 0));
movq(rax, Operand(kScratchRegister, 0));
// Link this handler. // Link this handler.
movq(Operand(kScratchRegister, 0), rsp); movq(Operand(kScratchRegister, 0), rsp);
} }
......
...@@ -159,9 +159,8 @@ class MacroAssembler: public Assembler { ...@@ -159,9 +159,8 @@ class MacroAssembler: public Assembler {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Exception handling // Exception handling
// Push a new try handler and link into try handler chain. // Push a new try handler and link into try handler chain. The return
// The return address must be pushed before calling this helper. // address must be pushed before calling this helper.
// On exit, rax contains TOS (next_sp).
void PushTryHandler(CodeLocation try_location, HandlerType type); 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