| Index: src/isolate.cc
|
| diff --git a/src/isolate.cc b/src/isolate.cc
|
| index 17e80172c539890684eb2dc528795ebfadf20bd8..72acbea8f388b48577606881f6d24bc1863098a0 100644
|
| --- a/src/isolate.cc
|
| +++ b/src/isolate.cc
|
| @@ -103,6 +103,12 @@ void ThreadLocalTop::InitializeInternal() {
|
| catcher_ = NULL;
|
| top_lookup_result_ = NULL;
|
|
|
| + optimized_handler_patch_buffer_ = NULL;
|
| + optimized_pending_exception_ = NULL;
|
| + optimized_handler_handler_index_ = -1;
|
| + optimized_handler_deopt_index_ = -1;
|
| + optimized_handler_frame_pc_offset_ = -1;
|
| +
|
| // These members are re-initialized later after deserialization
|
| // is complete.
|
| pending_exception_ = NULL;
|
| @@ -1134,13 +1140,21 @@ Failure* Isolate::ReThrow(MaybeObject* exception) {
|
| bool catchable_by_javascript = is_catchable_by_javascript(exception);
|
| ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
|
|
|
| - thread_local_top()->catcher_ = can_be_caught_externally ?
|
| - try_catch_handler() : NULL;
|
| + thread_local_top()->catcher_ =
|
| + can_be_caught_externally ? try_catch_handler() : NULL;
|
|
|
| // Set the exception being re-thrown.
|
| set_pending_exception(exception);
|
| - if (exception->IsFailure()) return exception->ToFailureUnchecked();
|
| - return Failure::Exception();
|
| +
|
| + // Try to prepare the optimized code for catching only if there is not
|
| + // an optimized handler ready to catch from the previous throw.
|
| + if (!is_handling_optimized_catch_statement()) {
|
| + PrepareForOptimizedHandler();
|
| + }
|
| +
|
| + return exception->IsFailure()
|
| + ? exception->ToFailureUnchecked()
|
| + : Failure::Exception();
|
| }
|
|
|
|
|
| @@ -1393,10 +1407,79 @@ void Isolate::DoThrow(Object* exception, MessageLocation* location) {
|
|
|
| // Do not forget to clean catcher_ if currently thrown exception cannot
|
| // be caught. If necessary, ReThrow will update the catcher.
|
| - thread_local_top()->catcher_ = can_be_caught_externally ?
|
| - try_catch_handler() : NULL;
|
| + thread_local_top()->catcher_ =
|
| + can_be_caught_externally ? try_catch_handler() : NULL;
|
|
|
| set_pending_exception(*exception_handle);
|
| +
|
| + // If the top-most handler is an optimized JS handler, we need to do
|
| + // some work to prepare the optimized code for catching.
|
| + PrepareForOptimizedHandler();
|
| +}
|
| +
|
| +
|
| +void Isolate::PrepareForOptimizedHandler() {
|
| + // Look for the topmost handler that is not a of kind JS_ENTRY
|
| + Address js_handler_address = Isolate::handler(thread_local_top());
|
| + StackHandler* handler = StackHandler::FromAddress(js_handler_address);
|
| + while (handler != NULL && handler->is_js_entry()) {
|
| + handler = handler->next();
|
| + }
|
| + // There might not be a JS handler at all.
|
| + if (handler == NULL) {
|
| + return;
|
| + }
|
| + // There might be an API handler before the top JS handler.
|
| + Address api_handler_address = thread_local_top()->try_catch_handler_address();
|
| + if (api_handler_address != NULL && api_handler_address < Address(handler)) {
|
| + return;
|
| + }
|
| + // The top JS handler might not be in optimized code.
|
| + if (!handler->is_optimized()) {
|
| + return;
|
| + }
|
| +
|
| + set_optimized_handler_handler_index(handler->index());
|
| +
|
| + // Find the frame corresponding to this handler.
|
| + JavaScriptFrame* frame = NULL;
|
| + for (JavaScriptFrameIterator it(this); !it.done(); it.Advance()) {
|
| + frame = it.frame();
|
| + if (frame->HasHandler() && frame->fp() > Address(handler)) break;
|
| + }
|
| +
|
| + // This will be read by the deopt and put into eax.
|
| + // FIXME(mmassi): can this be moved by a collection?
|
| + set_optimized_pending_exception(pending_exception());
|
| +
|
| + // Set the index of the next safepoint from the current PC.
|
| + // Runtime_CatchInOptimizedCode will then use it to find the offset where
|
| + // the code needs to be patched.
|
| + Code* code = handler->code();
|
| + SafepointEntry safepoint = code->GetSafepointEntry(frame->pc());
|
| + int deopt_index = safepoint.deoptimization_index();
|
| + ASSERT(deopt_index != Safepoint::kNoDeoptimizationIndex);
|
| + set_optimized_handler_deopt_index(deopt_index);
|
| + // Also set the offset in "code" where we will need to jump to.
|
| + set_optimized_handler_frame_pc_offset(
|
| + frame->pc() - reinterpret_cast<Address>(code));
|
| +
|
| +}
|
| +
|
| +
|
| +void Isolate::ClearOptimizedHandlerByDeopt(Code* optimized_code) {
|
| + deoptimizer_data()->RemoveDeoptimizingCode(optimized_code);
|
| + clear_optimized_handler_handler_index();
|
| + clear_optimized_handler_deopt_index();
|
| + clear_optimized_handler_patch_buffer();
|
| +}
|
| +
|
| +
|
| +void Isolate::ClearOptimizedHandlerByAPI() {
|
| + clear_optimized_handler_handler_index();
|
| + clear_optimized_handler_deopt_index();
|
| + clear_optimized_handler_frame_pc_offset();
|
| + clear_optimized_pending_exception();
|
| }
|
|
|
|
|
| @@ -1433,6 +1516,8 @@ bool Isolate::IsExternallyCaught() {
|
| StackHandler::FromAddress(Isolate::handler(thread_local_top()));
|
| while (handler != NULL && handler->address() < external_handler_address) {
|
| ASSERT(!handler->is_catch());
|
| + // Despite the above ASSERT the handler could come from optimized code.
|
| + if (handler->is_optimized()) return false;
|
| if (handler->is_finally()) return false;
|
|
|
| handler = handler->next();
|
| @@ -1941,6 +2026,11 @@ Isolate::~Isolate() {
|
| delete[] assembler_spare_buffer_;
|
| assembler_spare_buffer_ = NULL;
|
|
|
| + // FIXME(mmassi): why there was no guard here?
|
| + if (optimized_handler_patch_buffer() != NULL) {
|
| + clear_optimized_handler_patch_buffer();
|
| + }
|
| +
|
| delete unicode_cache_;
|
| unicode_cache_ = NULL;
|
|
|
|
|