diff options
Diffstat (limited to 'runtime/thread.cc')
| -rw-r--r-- | runtime/thread.cc | 82 |
1 files changed, 54 insertions, 28 deletions
diff --git a/runtime/thread.cc b/runtime/thread.cc index a33e150b93..63534b131b 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -162,27 +162,41 @@ void Thread::ResetQuickAllocEntryPointsForThread() { ResetQuickAllocEntryPoints(&tlsPtr_.quick_entrypoints); } -class DeoptimizationReturnValueRecord { +class DeoptimizationContextRecord { public: - DeoptimizationReturnValueRecord(const JValue& ret_val, - bool is_reference, - DeoptimizationReturnValueRecord* link) - : ret_val_(ret_val), is_reference_(is_reference), link_(link) {} + DeoptimizationContextRecord(const JValue& ret_val, bool is_reference, + mirror::Throwable* pending_exception, + DeoptimizationContextRecord* link) + : ret_val_(ret_val), is_reference_(is_reference), pending_exception_(pending_exception), + link_(link) {} JValue GetReturnValue() const { return ret_val_; } bool IsReference() const { return is_reference_; } - DeoptimizationReturnValueRecord* GetLink() const { return link_; } - mirror::Object** GetGCRoot() { + mirror::Throwable* GetPendingException() const { return pending_exception_; } + DeoptimizationContextRecord* GetLink() const { return link_; } + mirror::Object** GetReturnValueAsGCRoot() { DCHECK(is_reference_); return ret_val_.GetGCRoot(); } + mirror::Object** GetPendingExceptionAsGCRoot() { + return reinterpret_cast<mirror::Object**>(&pending_exception_); + } private: + // The value returned by the method at the top of the stack before deoptimization. JValue ret_val_; + + // Indicates whether the returned value is a reference. If so, the GC will visit it. const bool is_reference_; - DeoptimizationReturnValueRecord* const link_; - DISALLOW_COPY_AND_ASSIGN(DeoptimizationReturnValueRecord); + // The exception that was pending before deoptimization (or null if there was no pending + // exception). + mirror::Throwable* pending_exception_; + + // A link to the previous DeoptimizationContextRecord. + DeoptimizationContextRecord* const link_; + + DISALLOW_COPY_AND_ASSIGN(DeoptimizationContextRecord); }; class StackedShadowFrameRecord { @@ -206,22 +220,28 @@ class StackedShadowFrameRecord { DISALLOW_COPY_AND_ASSIGN(StackedShadowFrameRecord); }; -void Thread::PushAndClearDeoptimizationReturnValue() { - DeoptimizationReturnValueRecord* record = new DeoptimizationReturnValueRecord( - tls64_.deoptimization_return_value, - tls32_.deoptimization_return_value_is_reference, - tlsPtr_.deoptimization_return_value_stack); - tlsPtr_.deoptimization_return_value_stack = record; - ClearDeoptimizationReturnValue(); +void Thread::PushDeoptimizationContext(const JValue& return_value, bool is_reference, + mirror::Throwable* exception) { + DeoptimizationContextRecord* record = new DeoptimizationContextRecord( + return_value, + is_reference, + exception, + tlsPtr_.deoptimization_context_stack); + tlsPtr_.deoptimization_context_stack = record; +} + +void Thread::PopDeoptimizationContext(JValue* result, mirror::Throwable** exception) { + AssertHasDeoptimizationContext(); + DeoptimizationContextRecord* record = tlsPtr_.deoptimization_context_stack; + tlsPtr_.deoptimization_context_stack = record->GetLink(); + result->SetJ(record->GetReturnValue().GetJ()); + *exception = record->GetPendingException(); + delete record; } -JValue Thread::PopDeoptimizationReturnValue() { - DeoptimizationReturnValueRecord* record = tlsPtr_.deoptimization_return_value_stack; - DCHECK(record != nullptr); - tlsPtr_.deoptimization_return_value_stack = record->GetLink(); - JValue ret_val(record->GetReturnValue()); - delete record; - return ret_val; +void Thread::AssertHasDeoptimizationContext() { + CHECK(tlsPtr_.deoptimization_context_stack != nullptr) + << "No deoptimization context for thread " << *this; } void Thread::PushStackedShadowFrame(ShadowFrame* sf, StackedShadowFrameType type) { @@ -1575,6 +1595,9 @@ Thread::~Thread() { CHECK(tlsPtr_.flip_function == nullptr); CHECK_EQ(tls32_.suspended_at_suspend_check, false); + // Make sure we processed all deoptimization requests. + CHECK(tlsPtr_.deoptimization_context_stack == nullptr) << "Missed deoptimization"; + // We may be deleting a still born thread. SetStateUnsafe(kTerminated); @@ -2593,7 +2616,7 @@ void Thread::VisitRoots(RootVisitor* visitor) { visitor->VisitRootIfNonNull(&tlsPtr_.opeer, RootInfo(kRootThreadObject, thread_id)); if (tlsPtr_.exception != nullptr && tlsPtr_.exception != GetDeoptimizationException()) { visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&tlsPtr_.exception), - RootInfo(kRootNativeStack, thread_id)); + RootInfo(kRootNativeStack, thread_id)); } visitor->VisitRootIfNonNull(&tlsPtr_.monitor_enter_object, RootInfo(kRootNativeStack, thread_id)); tlsPtr_.jni_env->locals.VisitRoots(visitor, RootInfo(kRootJNILocal, thread_id)); @@ -2602,6 +2625,7 @@ void Thread::VisitRoots(RootVisitor* visitor) { if (tlsPtr_.debug_invoke_req != nullptr) { tlsPtr_.debug_invoke_req->VisitRoots(visitor, RootInfo(kRootDebugger, thread_id)); } + // Visit roots for deoptimization. if (tlsPtr_.stacked_shadow_frame_record != nullptr) { RootCallbackVisitor visitor_to_callback(visitor, thread_id); ReferenceMapVisitor<RootCallbackVisitor> mapper(this, nullptr, visitor_to_callback); @@ -2615,14 +2639,16 @@ void Thread::VisitRoots(RootVisitor* visitor) { } } } - if (tlsPtr_.deoptimization_return_value_stack != nullptr) { - for (DeoptimizationReturnValueRecord* record = tlsPtr_.deoptimization_return_value_stack; + if (tlsPtr_.deoptimization_context_stack != nullptr) { + for (DeoptimizationContextRecord* record = tlsPtr_.deoptimization_context_stack; record != nullptr; record = record->GetLink()) { if (record->IsReference()) { - visitor->VisitRootIfNonNull(record->GetGCRoot(), - RootInfo(kRootThreadObject, thread_id)); + visitor->VisitRootIfNonNull(record->GetReturnValueAsGCRoot(), + RootInfo(kRootThreadObject, thread_id)); } + visitor->VisitRootIfNonNull(record->GetPendingExceptionAsGCRoot(), + RootInfo(kRootThreadObject, thread_id)); } } for (auto* verifier = tlsPtr_.method_verifier; verifier != nullptr; verifier = verifier->link_) { |