// handler block in this code object, so its index is 0.
__ bind(&invoke);
// Must preserve r0-r4, r5-r7 are available.
- __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER, 0);
+ __ PushTryHandler(StackHandler::JS_ENTRY, 0);
// If an exception not caught by another handler occurs, this handler
// returns control to the code after the bl(&invoke) above, which
// restores all kCalleeSaved registers (including cp and fp) to their
#endif
-void MacroAssembler::PushTryHandler(CodeLocation try_location,
- HandlerType type,
+void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
int handler_index) {
// Adjust this code if not the case.
STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
// For the JSEntry handler, we must preserve r0-r4, r5-r7 are available.
// We will build up the handler from the bottom by pushing on the stack.
- // First compute the state.
- unsigned state = StackHandler::OffsetField::encode(handler_index);
- if (try_location == IN_JAVASCRIPT) {
- state |= (type == TRY_CATCH_HANDLER)
- ? StackHandler::KindField::encode(StackHandler::TRY_CATCH)
- : StackHandler::KindField::encode(StackHandler::TRY_FINALLY);
- } else {
- ASSERT(try_location == IN_JS_ENTRY);
- state |= StackHandler::KindField::encode(StackHandler::ENTRY);
- }
-
// Set up the code object (r5) and the state (r6) for pushing.
+ unsigned state =
+ StackHandler::IndexField::encode(handler_index) |
+ StackHandler::KindField::encode(kind);
mov(r5, Operand(CodeObject()));
mov(r6, Operand(state));
// Push the frame pointer, context, state, and code object.
- if (try_location == IN_JAVASCRIPT) {
- stm(db_w, sp, r5.bit() | r6.bit() | cp.bit() | fp.bit());
- } else {
+ if (kind == StackHandler::JS_ENTRY) {
mov(r7, Operand(Smi::FromInt(0))); // Indicates no context.
mov(ip, Operand(0, RelocInfo::NONE)); // NULL frame pointer.
stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() | ip.bit());
+ } else {
+ stm(db_w, sp, r5.bit() | r6.bit() | cp.bit() | fp.bit());
}
// Link the current handler as the next handler.
ldr(sp, MemOperand(sp, StackHandlerConstants::kNextOffset));
bind(&check_kind);
- STATIC_ASSERT(StackHandler::ENTRY == 0);
+ STATIC_ASSERT(StackHandler::JS_ENTRY == 0);
ldr(r2, MemOperand(sp, StackHandlerConstants::kStateOffset));
tst(r2, Operand(StackHandler::KindField::kMask));
b(ne, &fetch_next);
// Exception handling
// Push a new try handler and link into try handler chain.
- void PushTryHandler(CodeLocation try_location,
- HandlerType type,
- int handler_index);
+ void PushTryHandler(StackHandler::Kind kind, int handler_index);
// Unlink the stack handler on top of the stack from the try handler chain.
// Must preserve the result register.
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
}
-inline bool StackHandler::is_entry() const {
- return kind() == ENTRY;
+inline bool StackHandler::is_js_entry() const {
+ return kind() == JS_ENTRY;
}
-inline bool StackHandler::is_try_catch() const {
- return kind() == TRY_CATCH;
+inline bool StackHandler::is_catch() const {
+ return kind() == CATCH;
}
-inline bool StackHandler::is_try_finally() const {
- return kind() == TRY_FINALLY;
+inline bool StackHandler::is_finally() const {
+ return kind() == FINALLY;
}
StackHandlerIterator it(this, top_handler());
ASSERT(!it.done());
StackHandler* handler = it.handler();
- ASSERT(handler->is_entry());
+ ASSERT(handler->is_js_entry());
handler->Iterate(v, LookupCode());
#ifdef DEBUG
// Make sure that the entry frame does not contain more than one
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
class StackHandler BASE_EMBEDDED {
public:
enum Kind {
- ENTRY,
- TRY_CATCH,
- TRY_FINALLY
+ JS_ENTRY,
+ CATCH,
+ FINALLY,
+ LAST_KIND = FINALLY
};
static const int kKindWidth = 2;
- static const int kOffsetWidth = 32 - kKindWidth;
+ STATIC_ASSERT(LAST_KIND < (1 << kKindWidth));
+ static const int kIndexWidth = 32 - kKindWidth;
class KindField: public BitField<StackHandler::Kind, 0, kKindWidth> {};
- class OffsetField: public BitField<unsigned, kKindWidth, kOffsetWidth> {};
+ class IndexField: public BitField<unsigned, kKindWidth, kIndexWidth> {};
// Get the address of this stack handler.
inline Address address() const;
static inline StackHandler* FromAddress(Address address);
// Testers
- inline bool is_entry() const;
- inline bool is_try_catch() const;
- inline bool is_try_finally() const;
+ inline bool is_js_entry() const;
+ inline bool is_catch() const;
+ inline bool is_finally() const;
private:
// Accessors.
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// Try block code. Sets up the exception handler chain.
__ bind(&try_entry);
- __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER, stmt->index());
+ __ PushTryHandler(StackHandler::CATCH, stmt->index());
{ TryCatch try_body(this);
Visit(stmt->try_block());
}
// Set up try handler.
__ bind(&try_entry);
- __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER, stmt->index());
+ __ PushTryHandler(StackHandler::FINALLY, stmt->index());
{ TryFinally try_body(this, &finally_entry);
Visit(stmt->try_block());
}
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// 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, 0);
+ __ PushTryHandler(StackHandler::JS_ENTRY, 0);
// Clear any pending exceptions.
__ mov(edx, Immediate(masm->isolate()->factory()->the_hole_value()));
}
-void MacroAssembler::PushTryHandler(CodeLocation try_location,
- HandlerType type,
+void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
int handler_index) {
// Adjust this code if not the case.
STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
// We will build up the handler from the bottom by pushing on the stack.
- // First compute the state and push the frame pointer and context.
- unsigned state = StackHandler::OffsetField::encode(handler_index);
- if (try_location == IN_JAVASCRIPT) {
- push(ebp);
- push(esi);
- state |= (type == TRY_CATCH_HANDLER)
- ? StackHandler::KindField::encode(StackHandler::TRY_CATCH)
- : StackHandler::KindField::encode(StackHandler::TRY_FINALLY);
- } else {
- ASSERT(try_location == IN_JS_ENTRY);
+ // First push the frame pointer and context.
+ if (kind == StackHandler::JS_ENTRY) {
// 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(0)); // NULL frame pointer.
push(Immediate(Smi::FromInt(0))); // No context.
- state |= StackHandler::KindField::encode(StackHandler::ENTRY);
+ } else {
+ push(ebp);
+ push(esi);
}
-
// Push the state and the code object.
+ unsigned state =
+ StackHandler::IndexField::encode(handler_index) |
+ StackHandler::KindField::encode(kind);
push(Immediate(state));
Push(CodeObject());
mov(esp, Operand(esp, StackHandlerConstants::kNextOffset));
bind(&check_kind);
- STATIC_ASSERT(StackHandler::ENTRY == 0);
+ STATIC_ASSERT(StackHandler::JS_ENTRY == 0);
test(Operand(esp, StackHandlerConstants::kStateOffset),
Immediate(StackHandler::KindField::kMask));
j(not_zero, &fetch_next);
// Exception handling
// Push a new try handler and link it into try handler chain.
- void PushTryHandler(CodeLocation try_location,
- HandlerType type,
- int handler_index);
+ void PushTryHandler(StackHandler::Kind kind, int handler_index);
// Unlink the stack handler on top of the stack from the try handler chain.
void PopTryHandler();
// Find the top-most try-catch handler.
StackHandler* handler =
StackHandler::FromAddress(Isolate::handler(thread_local_top()));
- while (handler != NULL && !handler->is_try_catch()) {
+ while (handler != NULL && !handler->is_catch()) {
handler = handler->next();
}
StackHandler* handler =
StackHandler::FromAddress(Isolate::handler(thread_local_top()));
while (handler != NULL && handler->address() < external_handler_address) {
- ASSERT(!handler->is_try_catch());
- if (handler->is_try_finally()) return false;
+ ASSERT(!handler->is_catch());
+ if (handler->is_finally()) return false;
handler = handler->next();
}
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
};
-enum CodeLocation {
- IN_JAVASCRIPT,
- IN_JS_ENTRY,
- IN_C_ENTRY
-};
-
-
-enum HandlerType {
- TRY_CATCH_HANDLER,
- TRY_FINALLY_HANDLER,
- JS_ENTRY_HANDLER
-};
-
-
// Types of uncatchable exceptions.
enum UncatchableExceptionType {
OUT_OF_MEMORY,
// 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, 0);
+ __ PushTryHandler(StackHandler::JS_ENTRY, 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
// ---------------------------------------------------------------------------
// Exception handling.
-void MacroAssembler::PushTryHandler(CodeLocation try_location,
- HandlerType type,
+void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
int handler_index) {
// Adjust this code if not the case.
STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
// For the JSEntry handler, we must preserve a0-a3 and s0.
// t1-t3 are available. We will build up the handler from the bottom by
- // pushing on the stack. First compute the state.
- unsigned state = StackHandler::OffsetField::encode(handler_index);
- if (try_location == IN_JAVASCRIPT) {
- state |= (type == TRY_CATCH_HANDLER)
- ? StackHandler::KindField::encode(StackHandler::TRY_CATCH)
- : StackHandler::KindField::encode(StackHandler::TRY_FINALLY);
- } else {
- ASSERT(try_location == IN_JS_ENTRY);
- state |= StackHandler::KindField::encode(StackHandler::ENTRY);
- }
-
+ // pushing on the stack.
// Set up the code object (t1) and the state (t2) for pushing.
+ unsigned state =
+ StackHandler::IndexField::encode(handler_index) |
+ StackHandler::KindField::encode(kind);
li(t1, Operand(CodeObject()));
li(t2, Operand(state));
// Push the frame pointer, context, state, and code object.
- if (try_location == IN_JAVASCRIPT) {
- MultiPush(t1.bit() | t2.bit() | cp.bit() | fp.bit());
- } else {
+ if (kind == StackHandler::JS_ENTRY) {
ASSERT_EQ(Smi::FromInt(0), 0);
// The second zero_reg indicates no context.
// The first zero_reg is the NULL frame pointer.
// The operands are reversed to match the order of MultiPush/Pop.
Push(zero_reg, zero_reg, t2, t1);
+ } else {
+ MultiPush(t1.bit() | t2.bit() | cp.bit() | fp.bit());
}
// Link the current handler as the next handler.
lw(sp, MemOperand(sp, StackHandlerConstants::kNextOffset));
bind(&check_kind);
- STATIC_ASSERT(StackHandler::ENTRY == 0);
+ STATIC_ASSERT(StackHandler::JS_ENTRY == 0);
lw(a2, MemOperand(sp, StackHandlerConstants::kStateOffset));
And(a2, a2, Operand(StackHandler::KindField::kMask));
Branch(&fetch_next, ne, a2, Operand(zero_reg));
// Exception handling.
// Push a new try handler and link into try handler chain.
- void PushTryHandler(CodeLocation try_location,
- HandlerType type,
- int handler_index);
+ void PushTryHandler(StackHandler::Kind kind, int handler_index);
// Unlink the stack handler on top of the stack from the try handler chain.
// Must preserve the result register.
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// 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, 0);
+ __ PushTryHandler(StackHandler::JS_ENTRY, 0);
// Clear any pending exceptions.
__ LoadRoot(rax, Heap::kTheHoleValueRootIndex);
}
-void MacroAssembler::PushTryHandler(CodeLocation try_location,
- HandlerType type,
+void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
int handler_index) {
// Adjust this code if not the case.
STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
// We will build up the handler from the bottom by pushing on the stack.
- // First compute the state and push the frame pointer and context.
- unsigned state = StackHandler::OffsetField::encode(handler_index);
- if (try_location == IN_JAVASCRIPT) {
- push(rbp);
- push(rsi);
- state |= (type == TRY_CATCH_HANDLER)
- ? StackHandler::KindField::encode(StackHandler::TRY_CATCH)
- : StackHandler::KindField::encode(StackHandler::TRY_FINALLY);
- } else {
- ASSERT(try_location == IN_JS_ENTRY);
+ // First push the frame pointer and context.
+ if (kind == StackHandler::JS_ENTRY) {
// 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(0)); // NULL frame pointer.
Push(Smi::FromInt(0)); // No context.
- state |= StackHandler::KindField::encode(StackHandler::ENTRY);
+ } else {
+ push(rbp);
+ push(rsi);
}
// Push the state and the code object.
+ unsigned state =
+ StackHandler::IndexField::encode(handler_index) |
+ StackHandler::KindField::encode(kind);
push(Immediate(state));
Push(CodeObject());
movq(rsp, Operand(rsp, StackHandlerConstants::kNextOffset));
bind(&check_kind);
- STATIC_ASSERT(StackHandler::ENTRY == 0);
+ STATIC_ASSERT(StackHandler::JS_ENTRY == 0);
testl(Operand(rsp, StackHandlerConstants::kStateOffset),
Immediate(StackHandler::KindField::kMask));
j(not_zero, &fetch_next);
// Exception handling
// Push a new try handler and link it into try handler chain.
- void PushTryHandler(CodeLocation try_location,
- HandlerType type,
- int handler_index);
+ void PushTryHandler(StackHandler::Kind kind, int handler_index);
// Unlink the stack handler on top of the stack from the try handler chain.
void PopTryHandler();