| Index: src/isolate.cc
|
| diff --git a/src/isolate.cc b/src/isolate.cc
|
| index 90a3aa1152b4287accf2e8294efa8a6433ff20d9..7cd8b002c4b096e15c83a085eba72eaaf4b8739c 100644
|
| --- a/src/isolate.cc
|
| +++ b/src/isolate.cc
|
| @@ -1031,29 +1031,94 @@ Object* Isolate::ReThrow(Object* exception) {
|
| }
|
|
|
|
|
| +// TODO(turbofan): Make sure table is sorted and use binary search.
|
| +static int LookupInHandlerTable(Code* code, int pc_offset) {
|
| + FixedArray* handler_table = code->handler_table();
|
| + for (int i = 0; i < handler_table->length(); i += 2) {
|
| + int return_offset = Smi::cast(handler_table->get(i))->value();
|
| + int handler_offset = Smi::cast(handler_table->get(i + 1))->value();
|
| + if (pc_offset == return_offset) return handler_offset;
|
| + }
|
| + return -1;
|
| +}
|
| +
|
| +
|
| Object* Isolate::FindHandler() {
|
| Object* exception = pending_exception();
|
|
|
| - // Determine target stack handler. Special handling of termination exceptions
|
| - // which are uncatchable by JavaScript code, we unwind the handlers until the
|
| - // top ENTRY handler is found.
|
| - StackHandler* handler =
|
| - StackHandler::FromAddress(Isolate::handler(thread_local_top()));
|
| - if (!is_catchable_by_javascript(exception)) {
|
| - while (!handler->is_js_entry()) handler = handler->next();
|
| - }
|
| + Code* code = nullptr;
|
| + Context* context = nullptr;
|
| + intptr_t offset = 0;
|
| + Address handler_sp = nullptr;
|
| + Address handler_fp = nullptr;
|
| +
|
| + // Special handling of termination exceptions, uncatchable by JavaScript code,
|
| + // we unwind the handlers until the top ENTRY handler is found.
|
| + bool catchable_by_js = is_catchable_by_javascript(exception);
|
| +
|
| + // Compute handler and stack unwinding information 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 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.
|
| + thread_local_top()->handler_ = handler->next()->address();
|
| +
|
| + // Gather information from the handler.
|
| + code = handler->code();
|
| + handler_sp = handler->address() + StackHandlerConstants::kSize;
|
| + offset = Smi::cast(code->handler_table()->get(0))->value();
|
| + break;
|
| + }
|
| +
|
| + // 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();
|
| +
|
| + // Gather information from the handler.
|
| + code = handler->code();
|
| + context = handler->context();
|
| + offset = Smi::cast(code->handler_table()->get(handler->index()))->value();
|
| + handler_sp = handler->address() + StackHandlerConstants::kSize;
|
| + handler_fp = handler->frame_pointer();
|
| + break;
|
| + }
|
|
|
| - // Restore the next handler.
|
| - thread_local_top()->handler_ = handler->next()->address();
|
| + // For optimized frames we perform a lookup in the handler table.
|
| + if (frame->is_optimized() && catchable_by_js) {
|
| + 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;
|
| +
|
| + // Compute the stack pointer from the frame pointer. This ensures that
|
| + // argument slots on the stack are dropped as returning would.
|
| + Address return_sp = frame->fp() -
|
| + StandardFrameConstants::kFixedFrameSizeFromFp -
|
| + frame_code->stack_slots() * kPointerSize;
|
| +
|
| + // Gather information from the frame.
|
| + code = frame_code;
|
| + offset = handler_offset;
|
| + handler_sp = return_sp;
|
| + handler_fp = frame->fp();
|
| + break;
|
| + }
|
| + }
|
|
|
| - // Compute handler and stack unwinding information.
|
| - // TODO(mstarzinger): Extend this to perform actual stack-walk and take into
|
| - // account that TurboFan code can contain handlers as well.
|
| - Code* code = handler->code();
|
| - Context* context = handler->is_js_entry() ? nullptr : handler->context();
|
| - int offset = Smi::cast(code->handler_table()->get(handler->index()))->value();
|
| - Address handler_sp = handler->address() + StackHandlerConstants::kSize;
|
| - Address handler_fp = handler->frame_pointer();
|
| + // Handler must exist.
|
| + CHECK(code != nullptr);
|
|
|
| // Store information to be consumed by the CEntryStub.
|
| thread_local_top()->pending_handler_context_ = context;
|
|
|