diff options
Diffstat (limited to 'runtime/thread.cc')
-rw-r--r-- | runtime/thread.cc | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/runtime/thread.cc b/runtime/thread.cc index 0ce018ab76..df75f34e59 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -133,8 +133,6 @@ namespace art HIDDEN { using android::base::StringAppendV; using android::base::StringPrintf; -extern "C" Context* artDeoptimize(Thread* self, bool skip_method_exit_callbacks); - bool Thread::is_started_ = false; pthread_key_t Thread::pthread_key_self_; ConditionVariable* Thread::resume_cond_ = nullptr; @@ -3934,7 +3932,7 @@ void Thread::DumpThreadOffset(std::ostream& os, uint32_t offset) { os << offset; } -Context* Thread::QuickDeliverException(bool skip_method_exit_callbacks) { +std::unique_ptr<Context> Thread::QuickDeliverException(bool skip_method_exit_callbacks) { // Get exception from thread. ObjPtr<mirror::Throwable> exception = GetException(); CHECK(exception != nullptr); @@ -3942,7 +3940,9 @@ Context* Thread::QuickDeliverException(bool skip_method_exit_callbacks) { // This wasn't a real exception, so just clear it here. If there was an actual exception it // will be recorded in the DeoptimizationContext and it will be restored later. ClearException(); - return artDeoptimize(this, skip_method_exit_callbacks); + return Deoptimize(DeoptimizationKind::kFullFrame, + /*single_frame=*/ false, + skip_method_exit_callbacks); } ReadBarrier::MaybeAssertToSpaceInvariant(exception.Ptr()); @@ -3984,7 +3984,9 @@ Context* Thread::QuickDeliverException(bool skip_method_exit_callbacks) { exception, /* from_code= */ false, method_type); - return artDeoptimize(this, skip_method_exit_callbacks); + return Deoptimize(DeoptimizationKind::kFullFrame, + /*single_frame=*/ false, + skip_method_exit_callbacks); } else { LOG(WARNING) << "Got a deoptimization request on un-deoptimizable method " << visitor.caller->PrettyMethod(); @@ -4012,6 +4014,38 @@ Context* Thread::QuickDeliverException(bool skip_method_exit_callbacks) { return exception_handler.PrepareLongJump(); } +std::unique_ptr<Context> Thread::Deoptimize(DeoptimizationKind kind, + bool single_frame, + bool skip_method_exit_callbacks) { + Runtime::Current()->IncrementDeoptimizationCount(kind); + if (VLOG_IS_ON(deopt)) { + if (single_frame) { + // Deopt logging will be in DeoptimizeSingleFrame. It is there to take advantage of the + // specialized visitor that will show whether a method is Quick or Shadow. + } else { + LOG(INFO) << "Deopting:"; + Dump(LOG_STREAM(INFO)); + } + } + + AssertHasDeoptimizationContext(); + QuickExceptionHandler exception_handler(this, true); + if (single_frame) { + exception_handler.DeoptimizeSingleFrame(kind); + } else { + exception_handler.DeoptimizeStack(skip_method_exit_callbacks); + } + if (exception_handler.IsFullFragmentDone()) { + return exception_handler.PrepareLongJump(/*smash_caller_saves=*/ true); + } else { + exception_handler.DeoptimizePartialFragmentFixup(); + // We cannot smash the caller-saves, as we need the ArtMethod in a parameter register that would + // be caller-saved. This has the downside that we cannot track incorrect register usage down the + // line. + return exception_handler.PrepareLongJump(/*smash_caller_saves=*/ false); + } +} + ArtMethod* Thread::GetCurrentMethod(uint32_t* dex_pc_out, bool check_suspended, bool abort_on_error) const { |