Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(484)

Unified Diff: runtime/vm/exceptions.cc

Issue 2734323003: Re-landing of "replace TrySync with Metadata". (Closed)
Patch Set: Address review comments Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/exceptions.h ('k') | runtime/vm/fixed_cache.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/exceptions.cc
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 0ee20ad2f34ddbf796c25f926172cf0440938d47..6e731c8d4d79182ecf10a32cd83d024ffc04f19f 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -10,7 +10,9 @@
#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"
@@ -143,50 +145,203 @@ static void BuildStackTrace(StackTraceBuilder* builder) {
}
-// 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();
+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 StackResource {
+ public:
+ explicit ExceptionHandlerFinder(Thread* thread)
+ : StackResource(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());
+ CatchEntryState* state = cache_->Lookup(pc_);
+ if (state != NULL) cached_ = *state;
+#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_PRECOMPILER)
+ intptr_t num_vars = Smi::Value(code_->variables());
+ if (cached_.Empty()) GetMetaDataFromDeopt(num_vars, frame);
+#else
+ if (cached_.Empty()) ReadCompressedMetaData();
+#endif // !defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_PRECOMPILER)
+ }
+ }
+ if (needs_stacktrace || is_catch_all) {
+ return true;
+ }
}
- 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_.Empty()) {
+ // Cache hit.
+ TrySyncCached(&cached_);
+ } else {
+ // New cache entry.
+ CatchEntryState m(metadata_);
+ TrySyncCached(&m);
+ cache_->Insert(pc_, 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 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;
-}
+
+#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;
+ }
+ 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);
+ }
+ }
+ }
+ 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;
+ }
+#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.
+};
static void FindErrorHandler(uword* handler_pc,
@@ -391,16 +546,15 @@ 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.
- handler_exists = FindExceptionHandler(thread, &handler_pc, &handler_sp,
- &handler_fp, &handler_needs_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);
if (use_preallocated_stacktrace) {
if (handler_pc == 0) {
// No Dart frame.
@@ -455,6 +609,7 @@ 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);
« no previous file with comments | « runtime/vm/exceptions.h ('k') | runtime/vm/fixed_cache.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698