MIPS: Add a level of indirection to exception handler addresses.

Port r9977 (9aded78be4).
Note: This is the port of the reapplied patch, not the original.

Original commit message:

To support deoptimization of exception handlers, the handler address in the
stack is converted to a pair of code object and an index into a separate
table of code offsets.  The index part is invariant under deoptimization.
The index is packed into the handler state field so that handler size does
not change.

BUG=
TEST=

Review URL: http://codereview.chromium.org/8557003
Patch from Gergely Kis <gergely@homejinni.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10039 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 561b5716
......@@ -3856,7 +3856,7 @@ void CEntryStub::Generate(MacroAssembler* masm) {
void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
Label invoke, exit;
Label invoke, handler_entry, exit;
Isolate* isolate = masm->isolate();
// Registers:
......@@ -3933,14 +3933,15 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
__ bind(&cont);
__ push(t0);
// Call a faked try-block that does the invoke.
__ bal(&invoke); // bal exposes branch delay slot.
__ nop(); // Branch delay slot nop.
// Caught exception: Store result (exception) in the pending
// exception field in the JSEnv and return a failure sentinel.
// Coming in here the fp will be invalid because the PushTryHandler below
// sets it to 0 to signal the existence of the JSEntry frame.
// Jump to a faked try block that does the invoke, with a faked catch
// block that sets the pending exception.
__ jmp(&invoke);
__ bind(&handler_entry);
handler_offset_ = handler_entry.pos();
// Caught exception: Store result (exception) in the pending exception
// field in the JSEnv and return a failure sentinel. Coming in here the
// fp will be invalid because the PushTryHandler below sets it to 0 to
// signal the existence of the JSEntry frame.
__ li(t0, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
isolate)));
__ sw(v0, MemOperand(t0)); // We come back from 'invoke'. result is in v0.
......@@ -3948,9 +3949,10 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
__ b(&exit); // b exposes branch delay slot.
__ nop(); // Branch delay slot nop.
// Invoke: Link this frame into the handler chain.
// Invoke: Link this frame into the handler chain. There's only one
// handler block in this code object, so its index is 0.
__ bind(&invoke);
__ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER);
__ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER, 0);
// If an exception not caught by another handler occurs, this handler
// returns control to the code after the bal(&invoke) above, which
// restores all kCalleeSaved registers (including cp and fp) to their
......@@ -5103,7 +5105,7 @@ void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
}
void CallFunctionStub::FinishCode(Code* code) {
void CallFunctionStub::FinishCode(Handle<Code> code) {
code->set_has_function_cache(false);
}
......
......@@ -137,7 +137,7 @@ class UnaryOpStub: public CodeStub {
return UnaryOpIC::ToState(operand_type_);
}
virtual void FinishCode(Code* code) {
virtual void FinishCode(Handle<Code> code) {
code->set_unary_op_type(operand_type_);
}
};
......@@ -236,7 +236,7 @@ class BinaryOpStub: public CodeStub {
return BinaryOpIC::ToState(operands_type_);
}
virtual void FinishCode(Code* code) {
virtual void FinishCode(Handle<Code> code) {
code->set_binary_op_type(operands_type_);
code->set_binary_op_result_type(result_type_);
}
......
......@@ -154,13 +154,13 @@ static const int kSafepointRegisterStackIndexMap[kNumRegs] = {
class StackHandlerConstants : public AllStatic {
public:
static const int kNextOffset = 0 * kPointerSize;
static const int kStateOffset = 1 * kPointerSize;
static const int kContextOffset = 2 * kPointerSize;
static const int kFPOffset = 3 * kPointerSize;
static const int kPCOffset = 4 * kPointerSize;
static const int kNextOffset = 0 * kPointerSize;
static const int kCodeOffset = 1 * kPointerSize;
static const int kStateOffset = 2 * kPointerSize;
static const int kContextOffset = 3 * kPointerSize;
static const int kFPOffset = 4 * kPointerSize;
static const int kSize = kPCOffset + kPointerSize;
static const int kSize = kFPOffset + kPointerSize;
};
......
......@@ -137,6 +137,8 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
ASSERT(info_ == NULL);
info_ = info;
scope_ = info->scope();
handler_table_ =
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
SetFunctionPosition(function());
Comment cmnt(masm_, "[ function compiled by full code generator");
......
This diff is collapsed.
......@@ -843,9 +843,9 @@ class MacroAssembler: public Assembler {
// Exception handling.
// Push a new try handler and link into try handler chain.
// The return address must be passed in register ra.
// Clobber t0, t1, t2.
void PushTryHandler(CodeLocation try_location, HandlerType type);
void PushTryHandler(CodeLocation try_location,
HandlerType type,
int handler_index);
// Unlink the stack handler on top of the stack from the try handler chain.
// Must preserve the result register.
......@@ -1381,6 +1381,10 @@ class MacroAssembler: public Assembler {
Register bitmap_reg,
Register mask_reg);
// Helper for throwing exceptions. Compute a handler address and jump to
// it. See the implementation for register usage.
void JumpToHandlerEntry();
// Compute memory operands for safepoint stack slots.
static int SafepointRegisterStackIndex(int reg_code);
MemOperand SafepointRegisterSlot(Register reg);
......
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