| Index: runtime/vm/exceptions.cc
|
| diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
|
| index dcc9829f7ece0451ceb1d8386ba23baf136ba922..0ee20ad2f34ddbf796c25f926172cf0440938d47 100644
|
| --- a/runtime/vm/exceptions.cc
|
| +++ b/runtime/vm/exceptions.cc
|
| @@ -10,9 +10,7 @@
|
|
|
| #include "vm/dart_api_impl.h"
|
| #include "vm/dart_entry.h"
|
| -#include "vm/datastream.h"
|
| #include "vm/debugger.h"
|
| -#include "vm/deopt_instructions.h"
|
| #include "vm/flags.h"
|
| #include "vm/log.h"
|
| #include "vm/longjump.h"
|
| @@ -145,201 +143,50 @@ static void BuildStackTrace(StackTraceBuilder* builder) {
|
| }
|
|
|
|
|
| -static RawObject** VariableAt(uword fp, int stack_slot) {
|
| -#if defined(TARGET_ARCH_DBC)
|
| - return reinterpret_cast<RawObject**>(fp + stack_slot * kWordSize);
|
| -#else
|
| - if (stack_slot < 0) {
|
| - return reinterpret_cast<RawObject**>(ParamAddress(fp, -stack_slot));
|
| - } else {
|
| - return reinterpret_cast<RawObject**>(
|
| - LocalVarAddress(fp, kFirstLocalSlotFromFp - stack_slot));
|
| - }
|
| -#endif
|
| -}
|
| -
|
| -
|
| -class ExceptionHandlerFinder {
|
| - public:
|
| - explicit ExceptionHandlerFinder(Thread* thread)
|
| - : thread_(thread), cache_(NULL), metadata_(NULL) {}
|
| -
|
| - // Iterate through the stack frames and try to find a frame with an
|
| - // exception handler. Once found, set the pc, sp and fp so that execution
|
| - // can continue in that frame. Sets 'needs_stacktrace' if there is no
|
| - // cath-all handler or if a stack-trace is specified in the catch.
|
| - bool Find() {
|
| - StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
|
| - StackFrame* frame = frames.NextFrame();
|
| - if (frame == NULL) return false; // No Dart frame.
|
| - handler_pc_set_ = false;
|
| - needs_stacktrace = false;
|
| - bool is_catch_all = false;
|
| - uword temp_handler_pc = kUwordMax;
|
| - bool is_optimized = false;
|
| - code_ = NULL;
|
| - cache_ = thread_->isolate()->catch_entry_state_cache();
|
| -
|
| - while (!frame->IsEntryFrame()) {
|
| - if (frame->IsDartFrame()) {
|
| - if (frame->FindExceptionHandler(thread_, &temp_handler_pc,
|
| - &needs_stacktrace, &is_catch_all,
|
| - &is_optimized)) {
|
| - if (!handler_pc_set_) {
|
| - handler_pc_set_ = true;
|
| - handler_pc = temp_handler_pc;
|
| - handler_sp = frame->sp();
|
| - handler_fp = frame->fp();
|
| - if (is_optimized) {
|
| - pc_ = frame->pc();
|
| - code_ = &Code::Handle(frame->LookupDartCode());
|
| - cached_ = cache_->Lookup(pc_);
|
| -#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_PRECOMPILER)
|
| - intptr_t num_vars = Smi::Value(code_->variables());
|
| - if (!cached_) GetMetaDataFromDeopt(num_vars, frame);
|
| -#else
|
| - if (!cached_) ReadCompressedMetaData();
|
| -#endif // !defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_PRECOMPILER)
|
| - }
|
| - }
|
| - if (needs_stacktrace || is_catch_all) {
|
| - return true;
|
| - }
|
| - }
|
| - } // if frame->IsDartFrame
|
| - frame = frames.NextFrame();
|
| - ASSERT(frame != NULL);
|
| - } // while !frame->IsEntryFrame
|
| - ASSERT(frame->IsEntryFrame());
|
| - if (!handler_pc_set_) {
|
| - handler_pc = frame->pc();
|
| - handler_sp = frame->sp();
|
| - handler_fp = frame->fp();
|
| - }
|
| - // No catch-all encountered, needs stacktrace.
|
| - needs_stacktrace = true;
|
| - return handler_pc_set_;
|
| - }
|
| -
|
| - void TrySync() {
|
| - if (code_ == NULL || !code_->is_optimized()) {
|
| - return;
|
| - }
|
| - if (cached_) {
|
| - // Cache hit.
|
| - TrySyncCached(cached_);
|
| - } else {
|
| - // New cache entry.
|
| - CatchEntryState m(metadata_);
|
| - TrySyncCached(&m);
|
| - }
|
| - }
|
| -
|
| - void TrySyncCached(CatchEntryState* md) {
|
| - uword fp = handler_fp;
|
| - ObjectPool* pool = NULL;
|
| - intptr_t pairs = md->Pairs();
|
| - for (int j = 0; j < pairs; j++) {
|
| - intptr_t src = md->Src(j);
|
| - intptr_t dest = md->Dest(j);
|
| - if (md->isMove(j)) {
|
| - *VariableAt(fp, dest) = *VariableAt(fp, src);
|
| - } else {
|
| - if (pool == NULL) {
|
| - pool = &ObjectPool::Handle(code_->object_pool());
|
| - }
|
| - RawObject* obj = pool->ObjectAt(src);
|
| - *VariableAt(fp, dest) = obj;
|
| - }
|
| - }
|
| - }
|
| -
|
| -#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
|
| - void ReadCompressedMetaData() {
|
| - intptr_t pc_offset = pc_ - code_->PayloadStart();
|
| - const TypedData& td = TypedData::Handle(code_->catch_entry_state_maps());
|
| - NoSafepointScope no_safepoint;
|
| - ReadStream stream(static_cast<uint8_t*>(td.DataAddr(0)), td.Length());
|
| -
|
| - bool found_metadata = false;
|
| - while (stream.PendingBytes() > 0) {
|
| - intptr_t target_pc_offset = Reader::Read(&stream);
|
| - intptr_t variables = Reader::Read(&stream);
|
| - intptr_t suffix_length = Reader::Read(&stream);
|
| - intptr_t suffix_offset = Reader::Read(&stream);
|
| - if (pc_offset == target_pc_offset) {
|
| - metadata_ = new intptr_t[2 * (variables + suffix_length) + 1];
|
| - metadata_[0] = variables + suffix_length;
|
| - for (int j = 0; j < variables; j++) {
|
| - intptr_t src = Reader::Read(&stream);
|
| - intptr_t dest = Reader::Read(&stream);
|
| - metadata_[1 + 2 * j] = src;
|
| - metadata_[2 + 2 * j] = dest;
|
| +// Iterate through the stack frames and try to find a frame with an
|
| +// exception handler. Once found, set the pc, sp and fp so that execution
|
| +// can continue in that frame. Sets 'needs_stacktrace' if there is no
|
| +// cath-all handler or if a stack-trace is specified in the catch.
|
| +static bool FindExceptionHandler(Thread* thread,
|
| + uword* handler_pc,
|
| + uword* handler_sp,
|
| + uword* handler_fp,
|
| + bool* needs_stacktrace) {
|
| + StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
|
| + StackFrame* frame = frames.NextFrame();
|
| + if (frame == NULL) return false; // No Dart frame.
|
| + bool handler_pc_set = false;
|
| + *needs_stacktrace = false;
|
| + bool is_catch_all = false;
|
| + uword temp_handler_pc = kUwordMax;
|
| + while (!frame->IsEntryFrame()) {
|
| + if (frame->IsDartFrame()) {
|
| + if (frame->FindExceptionHandler(thread, &temp_handler_pc,
|
| + needs_stacktrace, &is_catch_all)) {
|
| + if (!handler_pc_set) {
|
| + handler_pc_set = true;
|
| + *handler_pc = temp_handler_pc;
|
| + *handler_sp = frame->sp();
|
| + *handler_fp = frame->fp();
|
| }
|
| - ReadCompressedSuffix(&stream, suffix_offset, suffix_length, metadata_,
|
| - 2 * variables + 1);
|
| - found_metadata = true;
|
| - break;
|
| - } else {
|
| - for (intptr_t j = 0; j < 2 * variables; j++) {
|
| - Reader::Read(&stream);
|
| + if (*needs_stacktrace || is_catch_all) {
|
| + return true;
|
| }
|
| }
|
| - }
|
| - ASSERT(found_metadata);
|
| - }
|
| -
|
| - void ReadCompressedSuffix(ReadStream* stream,
|
| - intptr_t offset,
|
| - intptr_t length,
|
| - intptr_t* target,
|
| - intptr_t target_offset) {
|
| - stream->SetPosition(offset);
|
| - Reader::Read(stream); // skip pc_offset
|
| - Reader::Read(stream); // skip variables
|
| - intptr_t suffix_length = Reader::Read(stream);
|
| - intptr_t suffix_offset = Reader::Read(stream);
|
| - intptr_t to_read = length - suffix_length;
|
| - for (int j = 0; j < to_read; j++) {
|
| - target[target_offset + 2 * j] = Reader::Read(stream);
|
| - target[target_offset + 2 * j + 1] = Reader::Read(stream);
|
| - }
|
| - if (suffix_length > 0) {
|
| - ReadCompressedSuffix(stream, suffix_offset, suffix_length, target,
|
| - target_offset + to_read * 2);
|
| - }
|
| - }
|
| -
|
| -#else
|
| - void GetMetaDataFromDeopt(intptr_t num_vars, StackFrame* frame) {
|
| - Isolate* isolate = thread_->isolate();
|
| - DeoptContext* deopt_context =
|
| - new DeoptContext(frame, *code_, DeoptContext::kDestIsAllocated, NULL,
|
| - NULL, true, false /* deoptimizing_code */);
|
| - isolate->set_deopt_context(deopt_context);
|
| -
|
| - metadata_ = deopt_context->CatchEntryState(num_vars);
|
| -
|
| - isolate->set_deopt_context(NULL);
|
| - delete deopt_context;
|
| + } // if frame->IsDartFrame
|
| + frame = frames.NextFrame();
|
| + ASSERT(frame != NULL);
|
| + } // while !frame->IsEntryFrame
|
| + ASSERT(frame->IsEntryFrame());
|
| + if (!handler_pc_set) {
|
| + *handler_pc = frame->pc();
|
| + *handler_sp = frame->sp();
|
| + *handler_fp = frame->fp();
|
| }
|
| -#endif // defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
|
| -
|
| - bool needs_stacktrace;
|
| - uword handler_pc;
|
| - uword handler_sp;
|
| - uword handler_fp;
|
| -
|
| - private:
|
| - typedef ReadStream::Raw<sizeof(intptr_t), intptr_t> Reader;
|
| - Thread* thread_;
|
| - CatchEntryStateCache* cache_;
|
| - Code* code_;
|
| - bool handler_pc_set_;
|
| - intptr_t* metadata_; // MetaData generated from deopt.
|
| - CatchEntryState* cached_; // Value of per PC MetaData cache.
|
| - intptr_t pc_; // Current pc in the handler frame.
|
| -};
|
| + // No catch-all encountered, needs stacktrace.
|
| + *needs_stacktrace = true;
|
| + return handler_pc_set;
|
| +}
|
|
|
|
|
| static void FindErrorHandler(uword* handler_pc,
|
| @@ -544,15 +391,16 @@ static void ThrowExceptionHelper(Thread* thread,
|
| exception.raw() == isolate->object_store()->stack_overflow()) {
|
| use_preallocated_stacktrace = true;
|
| }
|
| + uword handler_pc = 0;
|
| + uword handler_sp = 0;
|
| + uword handler_fp = 0;
|
| + Instance& stacktrace = Instance::Handle(zone);
|
| + bool handler_exists = false;
|
| + bool handler_needs_stacktrace = false;
|
| // Find the exception handler and determine if the handler needs a
|
| // stacktrace.
|
| - ExceptionHandlerFinder finder(thread);
|
| - bool handler_exists = finder.Find();
|
| - uword handler_pc = finder.handler_pc;
|
| - uword handler_sp = finder.handler_sp;
|
| - uword handler_fp = finder.handler_fp;
|
| - bool handler_needs_stacktrace = finder.needs_stacktrace;
|
| - Instance& stacktrace = Instance::Handle(zone);
|
| + handler_exists = FindExceptionHandler(thread, &handler_pc, &handler_sp,
|
| + &handler_fp, &handler_needs_stacktrace);
|
| if (use_preallocated_stacktrace) {
|
| if (handler_pc == 0) {
|
| // No Dart frame.
|
| @@ -607,7 +455,6 @@ static void ThrowExceptionHelper(Thread* thread,
|
| THR_Print("%s\n", stacktrace.ToCString());
|
| }
|
| if (handler_exists) {
|
| - finder.TrySync();
|
| // Found a dart handler for the exception, jump to it.
|
| JumpToExceptionHandler(thread, handler_pc, handler_sp, handler_fp,
|
| exception, stacktrace);
|
|
|