[VM runtime] Add transition before checking for error after interpreting call.
Change-Id: I6030f17ae9ebb937231f5766f4477cf7127dcc33
Reviewed-on: https://dart-review.googlesource.com/73289
Commit-Queue: Régis Crelier <regis@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index c5b9eba..3731a08 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -2722,7 +2722,7 @@
return reinterpret_cast<uword>(RuntimeEntry::InterpretCall);
}
-// Interpret a function call. Should be called only for uncompiled functions.
+// Interpret a function call. Should be called only for non-jitted functions.
// argc indicates the number of arguments, including the type arguments.
// argv points to the first argument.
// If argc < 0, arguments are passed at decreasing memory addresses from argv.
@@ -2737,6 +2737,9 @@
uword exit_fp = thread->top_exit_frame_info();
ASSERT(exit_fp != 0);
ASSERT(thread == Thread::Current());
+ // Caller is InterpretCall stub called from generated code.
+ // We stay in "in generated code" execution state when interpreting code.
+ ASSERT(thread->execution_state() == Thread::kThreadInGenerated);
ASSERT(!Function::HasCode(function));
ASSERT(Function::HasBytecode(function));
ASSERT(interpreter != NULL);
@@ -2744,7 +2747,12 @@
const Object& result = Object::Handle(
thread->zone(), interpreter->Call(function, argdesc, argc, argv, thread));
DEBUG_ASSERT(thread->top_exit_frame_info() == exit_fp);
- CheckResultError(result);
+ if (result.IsError()) {
+ // Propagating an error may cause allocation. Check if we need to block for
+ // a safepoint by switching to "in VM" execution state.
+ TransitionGeneratedToVM transition(thread);
+ Exceptions::PropagateError(Error::Cast(result));
+ }
return result.raw();
#else
UNREACHABLE();