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); |