Commit 96f79568 authored by mstarzinger's avatar mstarzinger Committed by Commit bot

Remove kind field from StackHandler.

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/1002203002

Cr-Commit-Position: refs/heads/master@{#27210}
parent 788d9d1b
...@@ -1406,13 +1406,10 @@ void MacroAssembler::PushTryHandler(StackHandler::Kind kind, ...@@ -1406,13 +1406,10 @@ void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
// For the JSEntry handler, we must preserve r0-r4, r5-r6 are available. // 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. // We will build up the handler from the bottom by pushing on the stack.
// Set up the the state (r6) for pushing. // Set up the the index (r6) for pushing.
unsigned state = mov(r6, Operand(handler_index));
StackHandler::IndexField::encode(handler_index) |
StackHandler::KindField::encode(kind);
mov(r6, Operand(state));
// Push the context and state. // Push the context and index.
if (kind == StackHandler::JS_ENTRY) { if (kind == StackHandler::JS_ENTRY) {
mov(cp, Operand(Smi::FromInt(0))); // Indicates no context. mov(cp, Operand(Smi::FromInt(0))); // Indicates no context.
stm(db_w, sp, r6.bit() | cp.bit()); stm(db_w, sp, r6.bit() | cp.bit());
......
...@@ -3050,12 +3050,8 @@ void MacroAssembler::PushTryHandler(StackHandler::Kind kind, ...@@ -3050,12 +3050,8 @@ void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
// For the JSEntry handler, we must preserve the live registers x0-x4. // For the JSEntry handler, we must preserve the live registers x0-x4.
// (See JSEntryStub::GenerateBody().) // (See JSEntryStub::GenerateBody().)
unsigned state = // Set up the index for pushing.
StackHandler::IndexField::encode(handler_index) | Mov(x11, handler_index);
StackHandler::KindField::encode(kind);
// Set up the state for pushing.
Mov(x11, state);
// Push the context and state. // Push the context and state.
if (kind == StackHandler::JS_ENTRY) { if (kind == StackHandler::JS_ENTRY) {
......
...@@ -2456,7 +2456,7 @@ MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<JSObject> task_event) { ...@@ -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; if (in_debug_scope() || ignore_events()) return;
// Temporarily clear any scheduled_exception to allow evaluating // Temporarily clear any scheduled_exception to allow evaluating
// JavaScript from the debug event handler. // JavaScript from the debug event handler.
...@@ -2466,7 +2466,7 @@ void Debug::OnThrow(Handle<Object> exception, bool uncaught) { ...@@ -2466,7 +2466,7 @@ void Debug::OnThrow(Handle<Object> exception, bool uncaught) {
scheduled_exception = handle(isolate_->scheduled_exception(), isolate_); scheduled_exception = handle(isolate_->scheduled_exception(), isolate_);
isolate_->clear_scheduled_exception(); isolate_->clear_scheduled_exception();
} }
OnException(exception, uncaught, isolate_->GetPromiseOnStackOnThrow()); OnException(exception, isolate_->GetPromiseOnStackOnThrow());
if (!scheduled_exception.is_null()) { if (!scheduled_exception.is_null()) {
isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception; isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception;
} }
...@@ -2479,7 +2479,7 @@ void Debug::OnPromiseReject(Handle<JSObject> promise, Handle<Object> value) { ...@@ -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. // Check whether the promise has been marked as having triggered a message.
Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol(); Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
if (JSObject::GetDataProperty(promise, key)->IsUndefined()) { if (JSObject::GetDataProperty(promise, key)->IsUndefined()) {
OnException(value, false, promise); OnException(value, promise);
} }
} }
...@@ -2494,8 +2494,8 @@ MaybeHandle<Object> Debug::PromiseHasUserDefinedRejectHandler( ...@@ -2494,8 +2494,8 @@ MaybeHandle<Object> Debug::PromiseHasUserDefinedRejectHandler(
} }
void Debug::OnException(Handle<Object> exception, bool uncaught, void Debug::OnException(Handle<Object> exception, Handle<Object> promise) {
Handle<Object> promise) { bool uncaught = !isolate_->PredictWhetherExceptionIsCaught(*exception);
if (!uncaught && promise->IsJSObject()) { if (!uncaught && promise->IsJSObject()) {
Handle<JSObject> jspromise = Handle<JSObject>::cast(promise); Handle<JSObject> jspromise = Handle<JSObject>::cast(promise);
// Mark the promise as already having triggered a message. // Mark the promise as already having triggered a message.
......
...@@ -425,7 +425,7 @@ class Debug { ...@@ -425,7 +425,7 @@ class Debug {
// Debug event triggers. // Debug event triggers.
void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue); 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 OnPromiseReject(Handle<JSObject> promise, Handle<Object> value);
void OnCompileError(Handle<Script> script); void OnCompileError(Handle<Script> script);
void OnBeforeCompile(Handle<Script> script); void OnBeforeCompile(Handle<Script> script);
...@@ -595,8 +595,7 @@ class Debug { ...@@ -595,8 +595,7 @@ class Debug {
return break_disabled_ || in_debug_event_listener_; return break_disabled_ || in_debug_event_listener_;
} }
void OnException(Handle<Object> exception, bool uncaught, void OnException(Handle<Object> exception, Handle<Object> promise);
Handle<Object> promise);
// Constructors for debug event objects. // Constructors for debug event objects.
MUST_USE_RESULT MaybeHandle<Object> MakeJSObject( MUST_USE_RESULT MaybeHandle<Object> MakeJSObject(
......
...@@ -61,36 +61,15 @@ inline StackHandler* StackHandler::FromAddress(Address address) { ...@@ -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 { inline Context* StackHandler::context() const {
const int offset = StackHandlerConstants::kContextOffset; const int offset = StackHandlerConstants::kContextOffset;
return Context::cast(Memory::Object_at(address() + offset)); 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; 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 { ...@@ -1338,7 +1338,6 @@ void EntryFrame::Iterate(ObjectVisitor* v) const {
StackHandlerIterator it(this, top_handler()); StackHandlerIterator it(this, top_handler());
DCHECK(!it.done()); DCHECK(!it.done());
StackHandler* handler = it.handler(); StackHandler* handler = it.handler();
DCHECK(handler->is_js_entry());
handler->Iterate(v, LookupCode()); handler->Iterate(v, LookupCode());
#ifdef DEBUG #ifdef DEBUG
// Make sure that the entry frame does not contain more than one // Make sure that the entry frame does not contain more than one
......
...@@ -88,15 +88,8 @@ class StackHandler BASE_EMBEDDED { ...@@ -88,15 +88,8 @@ class StackHandler BASE_EMBEDDED {
JS_ENTRY, JS_ENTRY,
CATCH, CATCH,
FINALLY, 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. // Get the address of this stack handler.
inline Address address() const; inline Address address() const;
...@@ -114,13 +107,7 @@ class StackHandler BASE_EMBEDDED { ...@@ -114,13 +107,7 @@ class StackHandler BASE_EMBEDDED {
// Accessors. // Accessors.
inline Context* context() const; inline Context* context() const;
inline Kind kind() const; inline int index() const;
inline unsigned index() const;
// Testers.
inline bool is_js_entry() const;
inline bool is_catch() const;
inline bool is_finally() const;
// Generator support to preserve stack handlers. // Generator support to preserve stack handlers.
void Unwind(Isolate* isolate, FixedArray* array, int offset, void Unwind(Isolate* isolate, FixedArray* array, int offset,
......
...@@ -1038,11 +1038,9 @@ void MacroAssembler::PushTryHandler(StackHandler::Kind kind, ...@@ -1038,11 +1038,9 @@ void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
} else { } else {
push(esi); push(esi);
} }
// Push the state.
unsigned state = // Push the index.
StackHandler::IndexField::encode(handler_index) | push(Immediate(handler_index));
StackHandler::KindField::encode(kind);
push(Immediate(state));
// Link the current handler as the next handler. // Link the current handler as the next handler.
ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
......
This diff is collapsed.
...@@ -629,7 +629,8 @@ class Isolate { ...@@ -629,7 +629,8 @@ class Isolate {
thread_local_top_.scheduled_exception_ = heap_.the_hole_value(); 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) { bool is_catchable_by_javascript(Object* exception) {
return exception != heap()->termination_exception(); return exception != heap()->termination_exception();
...@@ -743,6 +744,7 @@ class Isolate { ...@@ -743,6 +744,7 @@ class Isolate {
// Exception throwing support. The caller should use the result // Exception throwing support. The caller should use the result
// of Throw() as its return value. // of Throw() as its return value.
Object* Throw(Object* exception, MessageLocation* location = NULL); Object* Throw(Object* exception, MessageLocation* location = NULL);
Object* ThrowIllegalOperation();
template <typename T> template <typename T>
MUST_USE_RESULT MaybeHandle<T> Throw(Handle<Object> exception, MUST_USE_RESULT MaybeHandle<T> Throw(Handle<Object> exception,
...@@ -751,15 +753,20 @@ class Isolate { ...@@ -751,15 +753,20 @@ class Isolate {
return MaybeHandle<T>(); return MaybeHandle<T>();
} }
// Re-throw an exception. This involves no error reporting since // Re-throw an exception. This involves no error reporting since error
// error reporting was handled when the exception was thrown // reporting was handled when the exception was thrown originally.
// originally.
Object* ReThrow(Object* exception); Object* ReThrow(Object* exception);
// Find the correct handler for the current pending exception. This also // Find the correct handler for the current pending exception. This also
// clears and returns the current pending exception. // clears and returns the current pending exception.
Object* FindHandler(); 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); void ScheduleThrow(Object* exception);
// Re-set pending message, script and positions reported to the TryCatch // Re-set pending message, script and positions reported to the TryCatch
// back to the TLS for re-use when rethrowing. // back to the TLS for re-use when rethrowing.
...@@ -769,14 +776,9 @@ class Isolate { ...@@ -769,14 +776,9 @@ class Isolate {
void ReportPendingMessages(); void ReportPendingMessages();
// Return pending location if any or unfilled structure. // Return pending location if any or unfilled structure.
MessageLocation GetMessageLocation(); MessageLocation GetMessageLocation();
Object* ThrowIllegalOperation();
// Promote a scheduled exception to pending. Asserts has_scheduled_exception. // Promote a scheduled exception to pending. Asserts has_scheduled_exception.
Object* PromoteScheduledException(); 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 // Attempts to compute the current source location, storing the
// result in the target out parameter. // result in the target out parameter.
...@@ -803,7 +805,6 @@ class Isolate { ...@@ -803,7 +805,6 @@ class Isolate {
char* Iterate(ObjectVisitor* v, char* t); char* Iterate(ObjectVisitor* v, char* t);
void IterateThread(ThreadVisitor* v, char* t); void IterateThread(ThreadVisitor* v, char* t);
// Returns the current native context. // Returns the current native context.
Handle<Context> native_context(); Handle<Context> native_context();
......
...@@ -2995,11 +2995,8 @@ void MacroAssembler::PushTryHandler(StackHandler::Kind kind, ...@@ -2995,11 +2995,8 @@ void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
Push(rsi); Push(rsi);
} }
// Push the state. // Push the index.
unsigned state = Push(Immediate(handler_index));
StackHandler::IndexField::encode(handler_index) |
StackHandler::KindField::encode(kind);
Push(Immediate(state));
// Link the current handler as the next handler. // Link the current handler as the next handler.
ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
......
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