Remove kind field from StackHandler.
This relands commit 96f79568a9
.
This makes the Isolate::Throw logic not depend on a prediction of
whether an exception is caught or uncaught. Such a prediction is
inherently undecidable because a finally block can decide between
consuming or re-throwing an exception depending on arbitray control
flow.
There still is a conservative prediction mechanism in place that
components like the debugger or tracing can use for reporting.
With this change we can get rid of the StackHandler::kind field, a
pre-requisite to do table-based lookups of exception handlers.
R=yangguo@chromium.org
Review URL: https://codereview.chromium.org/997213003
Cr-Commit-Position: refs/heads/master@{#27263}
This commit is contained in:
parent
0e024449b8
commit
15f8213809
@ -1406,13 +1406,10 @@ void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
|
||||
|
||||
// For the JSEntry handler, we must preserve r0-r4, r5-r6 are available.
|
||||
// We will build up the handler from the bottom by pushing on the stack.
|
||||
// Set up the the state (r6) for pushing.
|
||||
unsigned state =
|
||||
StackHandler::IndexField::encode(handler_index) |
|
||||
StackHandler::KindField::encode(kind);
|
||||
mov(r6, Operand(state));
|
||||
// Set up the the index (r6) for pushing.
|
||||
mov(r6, Operand(handler_index));
|
||||
|
||||
// Push the context and state.
|
||||
// Push the context and index.
|
||||
if (kind == StackHandler::JS_ENTRY) {
|
||||
mov(cp, Operand(Smi::FromInt(0))); // Indicates no context.
|
||||
stm(db_w, sp, r6.bit() | cp.bit());
|
||||
|
@ -3050,12 +3050,8 @@ void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
|
||||
// For the JSEntry handler, we must preserve the live registers x0-x4.
|
||||
// (See JSEntryStub::GenerateBody().)
|
||||
|
||||
unsigned state =
|
||||
StackHandler::IndexField::encode(handler_index) |
|
||||
StackHandler::KindField::encode(kind);
|
||||
|
||||
// Set up the state for pushing.
|
||||
Mov(x11, state);
|
||||
// Set up the index for pushing.
|
||||
Mov(x11, handler_index);
|
||||
|
||||
// Push the context and state.
|
||||
if (kind == StackHandler::JS_ENTRY) {
|
||||
|
12
src/debug.cc
12
src/debug.cc
@ -2456,7 +2456,7 @@ MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<JSObject> task_event) {
|
||||
}
|
||||
|
||||
|
||||
void Debug::OnThrow(Handle<Object> exception, bool uncaught) {
|
||||
void Debug::OnThrow(Handle<Object> exception) {
|
||||
if (in_debug_scope() || ignore_events()) return;
|
||||
// Temporarily clear any scheduled_exception to allow evaluating
|
||||
// JavaScript from the debug event handler.
|
||||
@ -2466,7 +2466,7 @@ void Debug::OnThrow(Handle<Object> exception, bool uncaught) {
|
||||
scheduled_exception = handle(isolate_->scheduled_exception(), isolate_);
|
||||
isolate_->clear_scheduled_exception();
|
||||
}
|
||||
OnException(exception, uncaught, isolate_->GetPromiseOnStackOnThrow());
|
||||
OnException(exception, isolate_->GetPromiseOnStackOnThrow());
|
||||
if (!scheduled_exception.is_null()) {
|
||||
isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception;
|
||||
}
|
||||
@ -2479,7 +2479,7 @@ void Debug::OnPromiseReject(Handle<JSObject> promise, Handle<Object> value) {
|
||||
// Check whether the promise has been marked as having triggered a message.
|
||||
Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
|
||||
if (JSObject::GetDataProperty(promise, key)->IsUndefined()) {
|
||||
OnException(value, false, promise);
|
||||
OnException(value, promise);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2494,9 +2494,9 @@ MaybeHandle<Object> Debug::PromiseHasUserDefinedRejectHandler(
|
||||
}
|
||||
|
||||
|
||||
void Debug::OnException(Handle<Object> exception, bool uncaught,
|
||||
Handle<Object> promise) {
|
||||
if (!uncaught && promise->IsJSObject()) {
|
||||
void Debug::OnException(Handle<Object> exception, Handle<Object> promise) {
|
||||
bool uncaught = !isolate_->PredictWhetherExceptionIsCaught(*exception);
|
||||
if (promise->IsJSObject()) {
|
||||
Handle<JSObject> jspromise = Handle<JSObject>::cast(promise);
|
||||
// Mark the promise as already having triggered a message.
|
||||
Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
|
||||
|
@ -425,7 +425,7 @@ class Debug {
|
||||
// Debug event triggers.
|
||||
void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue);
|
||||
|
||||
void OnThrow(Handle<Object> exception, bool uncaught);
|
||||
void OnThrow(Handle<Object> exception);
|
||||
void OnPromiseReject(Handle<JSObject> promise, Handle<Object> value);
|
||||
void OnCompileError(Handle<Script> script);
|
||||
void OnBeforeCompile(Handle<Script> script);
|
||||
@ -595,8 +595,7 @@ class Debug {
|
||||
return break_disabled_ || in_debug_event_listener_;
|
||||
}
|
||||
|
||||
void OnException(Handle<Object> exception, bool uncaught,
|
||||
Handle<Object> promise);
|
||||
void OnException(Handle<Object> exception, Handle<Object> promise);
|
||||
|
||||
// Constructors for debug event objects.
|
||||
MUST_USE_RESULT MaybeHandle<Object> MakeJSObject(
|
||||
|
@ -61,36 +61,15 @@ inline StackHandler* StackHandler::FromAddress(Address address) {
|
||||
}
|
||||
|
||||
|
||||
inline bool StackHandler::is_js_entry() const {
|
||||
return kind() == JS_ENTRY;
|
||||
}
|
||||
|
||||
|
||||
inline bool StackHandler::is_catch() const {
|
||||
return kind() == CATCH;
|
||||
}
|
||||
|
||||
|
||||
inline bool StackHandler::is_finally() const {
|
||||
return kind() == FINALLY;
|
||||
}
|
||||
|
||||
|
||||
inline Context* StackHandler::context() const {
|
||||
const int offset = StackHandlerConstants::kContextOffset;
|
||||
return Context::cast(Memory::Object_at(address() + offset));
|
||||
}
|
||||
|
||||
|
||||
inline StackHandler::Kind StackHandler::kind() const {
|
||||
inline int StackHandler::index() const {
|
||||
const int offset = StackHandlerConstants::kStateIntOffset;
|
||||
return KindField::decode(Memory::unsigned_at(address() + offset));
|
||||
}
|
||||
|
||||
|
||||
inline unsigned StackHandler::index() const {
|
||||
const int offset = StackHandlerConstants::kStateIntOffset;
|
||||
return IndexField::decode(Memory::unsigned_at(address() + offset));
|
||||
return Memory::int_at(address() + offset);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1338,7 +1338,6 @@ void EntryFrame::Iterate(ObjectVisitor* v) const {
|
||||
StackHandlerIterator it(this, top_handler());
|
||||
DCHECK(!it.done());
|
||||
StackHandler* handler = it.handler();
|
||||
DCHECK(handler->is_js_entry());
|
||||
handler->Iterate(v, LookupCode());
|
||||
#ifdef DEBUG
|
||||
// Make sure that the entry frame does not contain more than one
|
||||
|
15
src/frames.h
15
src/frames.h
@ -88,15 +88,8 @@ class StackHandler BASE_EMBEDDED {
|
||||
JS_ENTRY,
|
||||
CATCH,
|
||||
FINALLY,
|
||||
LAST_KIND = FINALLY
|
||||
};
|
||||
|
||||
static const int kKindWidth = 2;
|
||||
STATIC_ASSERT(LAST_KIND < (1 << kKindWidth));
|
||||
static const int kIndexWidth = 32 - kKindWidth;
|
||||
class KindField: public BitField<StackHandler::Kind, 0, kKindWidth> {};
|
||||
class IndexField: public BitField<unsigned, kKindWidth, kIndexWidth> {};
|
||||
|
||||
// Get the address of this stack handler.
|
||||
inline Address address() const;
|
||||
|
||||
@ -114,13 +107,7 @@ class StackHandler BASE_EMBEDDED {
|
||||
|
||||
// Accessors.
|
||||
inline Context* context() const;
|
||||
inline Kind kind() const;
|
||||
inline unsigned index() const;
|
||||
|
||||
// Testers.
|
||||
inline bool is_js_entry() const;
|
||||
inline bool is_catch() const;
|
||||
inline bool is_finally() const;
|
||||
inline int index() const;
|
||||
|
||||
// Generator support to preserve stack handlers.
|
||||
void Unwind(Isolate* isolate, FixedArray* array, int offset,
|
||||
|
@ -1038,11 +1038,9 @@ void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
|
||||
} else {
|
||||
push(esi);
|
||||
}
|
||||
// Push the state.
|
||||
unsigned state =
|
||||
StackHandler::IndexField::encode(handler_index) |
|
||||
StackHandler::KindField::encode(kind);
|
||||
push(Immediate(state));
|
||||
|
||||
// Push the index.
|
||||
push(Immediate(handler_index));
|
||||
|
||||
// Link the current handler as the next handler.
|
||||
ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
|
||||
|
224
src/isolate.cc
224
src/isolate.cc
@ -929,39 +929,34 @@ void ReportBootstrappingException(Handle<Object> exception,
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
// Only use by Isolate::Throw for --abort-on-uncaught-exception.
|
||||
int fatal_exception_depth = 0;
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
Object* Isolate::Throw(Object* exception, MessageLocation* location) {
|
||||
DCHECK(!has_pending_exception());
|
||||
|
||||
HandleScope scope(this);
|
||||
Handle<Object> exception_handle(exception, this);
|
||||
|
||||
// Determine reporting and whether the exception is caught externally.
|
||||
bool catchable_by_javascript = is_catchable_by_javascript(exception);
|
||||
bool can_be_caught_externally = false;
|
||||
bool should_report_exception =
|
||||
ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
|
||||
bool report_exception = catchable_by_javascript && should_report_exception;
|
||||
bool try_catch_needs_message =
|
||||
can_be_caught_externally && try_catch_handler()->capture_message_;
|
||||
// Determine whether a message needs to be created for the given exception
|
||||
// depending on the following criteria:
|
||||
// 1) External v8::TryCatch missing: Always create a message because any
|
||||
// JavaScript handler for a finally-block might re-throw to top-level.
|
||||
// 2) External v8::TryCatch exists: Only create a message if the handler
|
||||
// captures messages or is verbose (which reports despite the catch).
|
||||
// 3) ReThrow from v8::TryCatch: The message from a previous throw still
|
||||
// exists and we preserve it instead of creating a new message.
|
||||
bool requires_message = try_catch_handler() == nullptr ||
|
||||
try_catch_handler()->is_verbose_ ||
|
||||
try_catch_handler()->capture_message_;
|
||||
bool rethrowing_message = thread_local_top()->rethrowing_message_;
|
||||
|
||||
thread_local_top()->rethrowing_message_ = false;
|
||||
|
||||
// Notify debugger of exception.
|
||||
if (catchable_by_javascript) {
|
||||
debug()->OnThrow(exception_handle, report_exception);
|
||||
if (is_catchable_by_javascript(exception)) {
|
||||
debug()->OnThrow(exception_handle);
|
||||
}
|
||||
|
||||
// Generate the message if required.
|
||||
if (!rethrowing_message && (report_exception || try_catch_needs_message)) {
|
||||
if (requires_message && !rethrowing_message) {
|
||||
MessageLocation potential_computed_location;
|
||||
if (location == NULL) {
|
||||
// If no location was specified we use a computed one instead.
|
||||
@ -976,16 +971,15 @@ Object* Isolate::Throw(Object* exception, MessageLocation* location) {
|
||||
ReportBootstrappingException(exception_handle, location);
|
||||
} else {
|
||||
Handle<Object> message_obj = CreateMessage(exception_handle, location);
|
||||
|
||||
thread_local_top()->pending_message_obj_ = *message_obj;
|
||||
|
||||
// If the abort-on-uncaught-exception flag is specified, abort on any
|
||||
// exception not caught by JavaScript, even when an external handler is
|
||||
// present. This flag is intended for use by JavaScript developers, so
|
||||
// print a user-friendly stack trace (not an internal one).
|
||||
if (fatal_exception_depth == 0 && FLAG_abort_on_uncaught_exception &&
|
||||
(report_exception || can_be_caught_externally)) {
|
||||
fatal_exception_depth++;
|
||||
if (FLAG_abort_on_uncaught_exception &&
|
||||
!PredictWhetherExceptionIsCaught(*exception_handle)) {
|
||||
FLAG_abort_on_uncaught_exception = false; // Prevent endless recursion.
|
||||
PrintF(stderr, "%s\n\nFROM\n",
|
||||
MessageHandler::GetLocalizedMessage(this, message_obj).get());
|
||||
PrintCurrentStackTrace(stderr);
|
||||
@ -1042,7 +1036,6 @@ Object* Isolate::FindHandler() {
|
||||
// For JSEntryStub frames we always have a handler.
|
||||
if (frame->is_entry() || frame->is_entry_construct()) {
|
||||
StackHandler* handler = frame->top_handler();
|
||||
DCHECK_EQ(StackHandler::JS_ENTRY, handler->kind());
|
||||
DCHECK_EQ(0, handler->index());
|
||||
|
||||
// Restore the next handler.
|
||||
@ -1058,7 +1051,6 @@ Object* Isolate::FindHandler() {
|
||||
// For JavaScript frames which have a handler, we use the handler.
|
||||
if (frame->is_java_script() && catchable_by_js && frame->HasHandler()) {
|
||||
StackHandler* handler = frame->top_handler();
|
||||
DCHECK_NE(StackHandler::JS_ENTRY, handler->kind());
|
||||
|
||||
// Restore the next handler.
|
||||
thread_local_top()->handler_ = handler->next()->address();
|
||||
@ -1111,9 +1103,39 @@ Object* Isolate::FindHandler() {
|
||||
}
|
||||
|
||||
|
||||
// TODO(mstarzinger): We shouldn't need the exception object here.
|
||||
bool Isolate::PredictWhetherExceptionIsCaught(Object* exception) {
|
||||
if (IsExternalHandlerOnTop(exception)) return true;
|
||||
|
||||
// Search for a JavaScript handler by performing a full walk over the stack
|
||||
// and dispatching according to the frame type.
|
||||
for (StackFrameIterator iter(this); !iter.done(); iter.Advance()) {
|
||||
StackFrame* frame = iter.frame();
|
||||
|
||||
// For JavaScript frames which have a handler, we use the handler.
|
||||
if (frame->is_java_script() && frame->HasHandler()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// For optimized frames we perform a lookup in the handler table.
|
||||
if (frame->is_optimized()) {
|
||||
Code* frame_code = frame->LookupCode();
|
||||
DCHECK(frame_code->is_optimized_code());
|
||||
int pc_offset = static_cast<int>(frame->pc() - frame_code->entry());
|
||||
int handler_offset = LookupInHandlerTable(frame_code, pc_offset);
|
||||
if (handler_offset < 0) continue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Handler not found.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Object* Isolate::ThrowIllegalOperation() {
|
||||
if (FLAG_stack_trace_on_illegal) PrintStack(stdout);
|
||||
return Throw(heap_.illegal_access_string());
|
||||
return Throw(heap()->illegal_access_string());
|
||||
}
|
||||
|
||||
|
||||
@ -1264,37 +1286,6 @@ bool Isolate::ComputeLocationFromStackTrace(MessageLocation* target,
|
||||
}
|
||||
|
||||
|
||||
bool Isolate::ShouldReportException(bool* can_be_caught_externally,
|
||||
bool catchable_by_javascript) {
|
||||
// Find the top-most try-catch handler.
|
||||
StackHandler* handler =
|
||||
StackHandler::FromAddress(Isolate::handler(thread_local_top()));
|
||||
while (handler != NULL && !handler->is_catch()) {
|
||||
handler = handler->next();
|
||||
}
|
||||
|
||||
// Get the address of the external handler so we can compare the address to
|
||||
// determine which one is closer to the top of the stack.
|
||||
Address external_handler_address =
|
||||
thread_local_top()->try_catch_handler_address();
|
||||
|
||||
// The exception has been externally caught if and only if there is
|
||||
// an external handler which is on top of the top-most try-catch
|
||||
// handler.
|
||||
*can_be_caught_externally = external_handler_address != NULL &&
|
||||
(handler == NULL || handler->address() > external_handler_address ||
|
||||
!catchable_by_javascript);
|
||||
|
||||
if (*can_be_caught_externally) {
|
||||
// Only report the exception if the external handler is verbose.
|
||||
return try_catch_handler()->is_verbose_;
|
||||
} else {
|
||||
// Report the exception if it isn't caught by JavaScript code.
|
||||
return handler == NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Traverse prototype chain to find out whether the object is derived from
|
||||
// the Error object.
|
||||
bool Isolate::IsErrorObject(Handle<Object> obj) {
|
||||
@ -1366,32 +1357,53 @@ Handle<JSMessageObject> Isolate::CreateMessage(Handle<Object> exception,
|
||||
}
|
||||
|
||||
|
||||
bool Isolate::IsFinallyOnTop() {
|
||||
bool Isolate::IsJavaScriptHandlerOnTop(Object* exception) {
|
||||
DCHECK_NE(heap()->the_hole_value(), exception);
|
||||
|
||||
// For uncatchable exceptions, the JavaScript handler cannot be on top.
|
||||
if (!is_catchable_by_javascript(exception)) return false;
|
||||
|
||||
// Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist.
|
||||
Address entry_handler = Isolate::handler(thread_local_top());
|
||||
if (entry_handler == nullptr) return false;
|
||||
|
||||
// Get the address of the external handler so we can compare the address to
|
||||
// determine which one is closer to the top of the stack.
|
||||
Address external_handler_address =
|
||||
thread_local_top()->try_catch_handler_address();
|
||||
DCHECK(external_handler_address != NULL);
|
||||
Address external_handler = thread_local_top()->try_catch_handler_address();
|
||||
if (external_handler == nullptr) return true;
|
||||
|
||||
// The exception has been externally caught if and only if there is
|
||||
// an external handler which is on top of the top-most try-finally
|
||||
// handler.
|
||||
// There should be no try-catch blocks as they would prohibit us from
|
||||
// finding external catcher in the first place (see catcher_ check above).
|
||||
// The exception has been externally caught if and only if there is an
|
||||
// external handler which is on top of the top-most JS_ENTRY handler.
|
||||
//
|
||||
// Note, that finally clause would rethrow an exception unless it's
|
||||
// aborted by jumps in control flow like return, break, etc. and we'll
|
||||
// have another chances to set proper v8::TryCatch.
|
||||
StackHandler* handler =
|
||||
StackHandler::FromAddress(Isolate::handler(thread_local_top()));
|
||||
while (handler != NULL && handler->address() < external_handler_address) {
|
||||
DCHECK(!handler->is_catch());
|
||||
if (handler->is_finally()) return true;
|
||||
// Note, that finally clauses would re-throw an exception unless it's aborted
|
||||
// by jumps in control flow (like return, break, etc.) and we'll have another
|
||||
// chance to set proper v8::TryCatch later.
|
||||
return (entry_handler < external_handler);
|
||||
}
|
||||
|
||||
handler = handler->next();
|
||||
}
|
||||
|
||||
return false;
|
||||
bool Isolate::IsExternalHandlerOnTop(Object* exception) {
|
||||
DCHECK_NE(heap()->the_hole_value(), exception);
|
||||
|
||||
// Get the address of the external handler so we can compare the address to
|
||||
// determine which one is closer to the top of the stack.
|
||||
Address external_handler = thread_local_top()->try_catch_handler_address();
|
||||
if (external_handler == nullptr) return false;
|
||||
|
||||
// For uncatchable exceptions, the external handler is always on top.
|
||||
if (!is_catchable_by_javascript(exception)) return true;
|
||||
|
||||
// Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist.
|
||||
Address entry_handler = Isolate::handler(thread_local_top());
|
||||
if (entry_handler == nullptr) return true;
|
||||
|
||||
// The exception has been externally caught if and only if there is an
|
||||
// external handler which is on top of the top-most JS_ENTRY handler.
|
||||
//
|
||||
// Note, that finally clauses would re-throw an exception unless it's aborted
|
||||
// by jumps in control flow (like return, break, etc.) and we'll have another
|
||||
// chance to set proper v8::TryCatch later.
|
||||
return (entry_handler > external_handler);
|
||||
}
|
||||
|
||||
|
||||
@ -1408,25 +1420,32 @@ void Isolate::ReportPendingMessages() {
|
||||
Object* message_obj = thread_local_top_.pending_message_obj_;
|
||||
clear_pending_message();
|
||||
|
||||
bool can_be_caught_externally = false;
|
||||
bool catchable_by_javascript = is_catchable_by_javascript(exception);
|
||||
bool should_report_exception =
|
||||
ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
|
||||
// For uncatchable exceptions we do nothing. If needed, the exception and the
|
||||
// message have already been propagated to v8::TryCatch.
|
||||
if (!is_catchable_by_javascript(exception)) return;
|
||||
|
||||
if (!catchable_by_javascript) {
|
||||
// Do nothing: if needed, the exception has been already propagated to
|
||||
// v8::TryCatch.
|
||||
// Determine whether the message needs to be reported to all message handlers
|
||||
// depending on whether and external v8::TryCatch or an internal JavaScript
|
||||
// handler is on top.
|
||||
bool should_report_exception;
|
||||
if (IsExternalHandlerOnTop(exception)) {
|
||||
// Only report the exception if the external handler is verbose.
|
||||
should_report_exception = try_catch_handler()->is_verbose_;
|
||||
} else {
|
||||
if (!message_obj->IsTheHole() && should_report_exception) {
|
||||
HandleScope scope(this);
|
||||
Handle<JSMessageObject> message(JSMessageObject::cast(message_obj));
|
||||
Handle<JSValue> script_wrapper(JSValue::cast(message->script()));
|
||||
Handle<Script> script(Script::cast(script_wrapper->value()));
|
||||
int start_pos = message->start_position();
|
||||
int end_pos = message->end_position();
|
||||
MessageLocation location(script, start_pos, end_pos);
|
||||
MessageHandler::ReportMessage(this, &location, message);
|
||||
}
|
||||
// Report the exception if it isn't caught by JavaScript code.
|
||||
should_report_exception = !IsJavaScriptHandlerOnTop(exception);
|
||||
}
|
||||
|
||||
// Actually report the pending message to all message handlers.
|
||||
if (!message_obj->IsTheHole() && should_report_exception) {
|
||||
HandleScope scope(this);
|
||||
Handle<JSMessageObject> message(JSMessageObject::cast(message_obj));
|
||||
Handle<JSValue> script_wrapper(JSValue::cast(message->script()));
|
||||
Handle<Script> script(Script::cast(script_wrapper->value()));
|
||||
int start_pos = message->start_position();
|
||||
int end_pos = message->end_position();
|
||||
MessageLocation location(script, start_pos, end_pos);
|
||||
MessageHandler::ReportMessage(this, &location, message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1934,21 +1953,18 @@ void Isolate::InitializeThreadLocal() {
|
||||
bool Isolate::PropagatePendingExceptionToExternalTryCatch() {
|
||||
Object* exception = pending_exception();
|
||||
|
||||
bool can_be_caught_externally = false;
|
||||
bool catchable_by_javascript = is_catchable_by_javascript(exception);
|
||||
ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
|
||||
if (!can_be_caught_externally) {
|
||||
thread_local_top_.external_caught_exception_ = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (catchable_by_javascript && IsFinallyOnTop()) {
|
||||
if (IsJavaScriptHandlerOnTop(exception)) {
|
||||
thread_local_top_.external_caught_exception_ = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsExternalHandlerOnTop(exception)) {
|
||||
thread_local_top_.external_caught_exception_ = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
thread_local_top_.external_caught_exception_ = true;
|
||||
if (!catchable_by_javascript) {
|
||||
if (!is_catchable_by_javascript(exception)) {
|
||||
try_catch_handler()->can_continue_ = false;
|
||||
try_catch_handler()->has_terminated_ = true;
|
||||
try_catch_handler()->exception_ = heap()->null_value();
|
||||
|
@ -629,7 +629,8 @@ class Isolate {
|
||||
thread_local_top_.scheduled_exception_ = heap_.the_hole_value();
|
||||
}
|
||||
|
||||
bool IsFinallyOnTop();
|
||||
bool IsJavaScriptHandlerOnTop(Object* exception);
|
||||
bool IsExternalHandlerOnTop(Object* exception);
|
||||
|
||||
bool is_catchable_by_javascript(Object* exception) {
|
||||
return exception != heap()->termination_exception();
|
||||
@ -743,6 +744,7 @@ class Isolate {
|
||||
// Exception throwing support. The caller should use the result
|
||||
// of Throw() as its return value.
|
||||
Object* Throw(Object* exception, MessageLocation* location = NULL);
|
||||
Object* ThrowIllegalOperation();
|
||||
|
||||
template <typename T>
|
||||
MUST_USE_RESULT MaybeHandle<T> Throw(Handle<Object> exception,
|
||||
@ -751,15 +753,20 @@ class Isolate {
|
||||
return MaybeHandle<T>();
|
||||
}
|
||||
|
||||
// Re-throw an exception. This involves no error reporting since
|
||||
// error reporting was handled when the exception was thrown
|
||||
// originally.
|
||||
// Re-throw an exception. This involves no error reporting since error
|
||||
// reporting was handled when the exception was thrown originally.
|
||||
Object* ReThrow(Object* exception);
|
||||
|
||||
// Find the correct handler for the current pending exception. This also
|
||||
// clears and returns the current pending exception.
|
||||
Object* FindHandler();
|
||||
|
||||
// Tries to predict whether the exception will be caught. Note that this can
|
||||
// only produce an estimate, because it is undecidable whether a finally
|
||||
// clause will consume or re-throw an exception. We conservatively assume any
|
||||
// finally clause will behave as if the exception were consumed.
|
||||
bool PredictWhetherExceptionIsCaught(Object* exception);
|
||||
|
||||
void ScheduleThrow(Object* exception);
|
||||
// Re-set pending message, script and positions reported to the TryCatch
|
||||
// back to the TLS for re-use when rethrowing.
|
||||
@ -769,14 +776,9 @@ class Isolate {
|
||||
void ReportPendingMessages();
|
||||
// Return pending location if any or unfilled structure.
|
||||
MessageLocation GetMessageLocation();
|
||||
Object* ThrowIllegalOperation();
|
||||
|
||||
// Promote a scheduled exception to pending. Asserts has_scheduled_exception.
|
||||
Object* PromoteScheduledException();
|
||||
// Checks if exception should be reported and finds out if it's
|
||||
// caught externally.
|
||||
bool ShouldReportException(bool* can_be_caught_externally,
|
||||
bool catchable_by_javascript);
|
||||
|
||||
// Attempts to compute the current source location, storing the
|
||||
// result in the target out parameter.
|
||||
@ -803,7 +805,6 @@ class Isolate {
|
||||
char* Iterate(ObjectVisitor* v, char* t);
|
||||
void IterateThread(ThreadVisitor* v, char* t);
|
||||
|
||||
|
||||
// Returns the current native context.
|
||||
Handle<Context> native_context();
|
||||
|
||||
|
@ -2995,11 +2995,8 @@ void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
|
||||
Push(rsi);
|
||||
}
|
||||
|
||||
// Push the state.
|
||||
unsigned state =
|
||||
StackHandler::IndexField::encode(handler_index) |
|
||||
StackHandler::KindField::encode(kind);
|
||||
Push(Immediate(state));
|
||||
// Push the index.
|
||||
Push(Immediate(handler_index));
|
||||
|
||||
// Link the current handler as the next handler.
|
||||
ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
|
||||
|
Loading…
Reference in New Issue
Block a user