// 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();
}
// 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) {
// 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.
// 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
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);
__ 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));
__ 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);
__ mov(lr, Operand(pc));
}
#endif
+ ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
__ pop(pc);
}
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;
};
}
-// ----------------------------------------------------
-
-
-
-
- // 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_
}
#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));
}
}
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);
}
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));
}
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;
// 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");
// 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);
// 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);
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));
__ 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);
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));
static const int kStateOffset = 2 * kPointerSize;
static const int kPCOffset = 3 * kPointerSize;
- static const int kAddressDisplacement = 0;
static const int kSize = kPCOffset + kPointerSize;
};
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)));
// 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());
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;
};
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) {
} 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);
}
// ---------------------------------------------------------------------------
// 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);