diff options
Diffstat (limited to 'runtime/thread.cc')
| -rw-r--r-- | runtime/thread.cc | 118 |
1 files changed, 88 insertions, 30 deletions
diff --git a/runtime/thread.cc b/runtime/thread.cc index 4203b96f24..fe8b0d8c60 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -147,29 +147,82 @@ void Thread::ResetQuickAllocEntryPointsForThread() { ResetQuickAllocEntryPoints(&tlsPtr_.quick_entrypoints); } -void Thread::SetDeoptimizationShadowFrame(ShadowFrame* sf) { - tlsPtr_.deoptimization_shadow_frame = sf; -} +class DeoptimizationReturnValueRecord { + public: + DeoptimizationReturnValueRecord(const JValue& ret_val, + bool is_reference, + DeoptimizationReturnValueRecord* link) + : ret_val_(ret_val), is_reference_(is_reference), link_(link) {} + + JValue GetReturnValue() const { return ret_val_; } + bool IsReference() const { return is_reference_; } + DeoptimizationReturnValueRecord* GetLink() const { return link_; } + mirror::Object** GetGCRoot() { + DCHECK(is_reference_); + return ret_val_.GetGCRoot(); + } + + private: + JValue ret_val_; + const bool is_reference_; + DeoptimizationReturnValueRecord* const link_; + + DISALLOW_COPY_AND_ASSIGN(DeoptimizationReturnValueRecord); +}; + +class StackedShadowFrameRecord { + public: + StackedShadowFrameRecord(ShadowFrame* shadow_frame, + StackedShadowFrameType type, + StackedShadowFrameRecord* link) + : shadow_frame_(shadow_frame), + type_(type), + link_(link) {} -void Thread::SetDeoptimizationReturnValue(const JValue& ret_val) { - tls64_.deoptimization_return_value.SetJ(ret_val.GetJ()); + ShadowFrame* GetShadowFrame() const { return shadow_frame_; } + StackedShadowFrameType GetType() const { return type_; } + StackedShadowFrameRecord* GetLink() const { return link_; } + + private: + ShadowFrame* const shadow_frame_; + const StackedShadowFrameType type_; + StackedShadowFrameRecord* const link_; + + 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(); } -ShadowFrame* Thread::GetAndClearDeoptimizationShadowFrame(JValue* ret_val) { - ShadowFrame* sf = tlsPtr_.deoptimization_shadow_frame; - tlsPtr_.deoptimization_shadow_frame = nullptr; - ret_val->SetJ(tls64_.deoptimization_return_value.GetJ()); - return sf; +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::SetShadowFrameUnderConstruction(ShadowFrame* sf) { - sf->SetLink(tlsPtr_.shadow_frame_under_construction); - tlsPtr_.shadow_frame_under_construction = sf; +void Thread::PushStackedShadowFrame(ShadowFrame* sf, StackedShadowFrameType type) { + StackedShadowFrameRecord* record = new StackedShadowFrameRecord( + sf, type, tlsPtr_.stacked_shadow_frame_record); + tlsPtr_.stacked_shadow_frame_record = record; } -void Thread::ClearShadowFrameUnderConstruction() { - CHECK_NE(static_cast<ShadowFrame*>(nullptr), tlsPtr_.shadow_frame_under_construction); - tlsPtr_.shadow_frame_under_construction = tlsPtr_.shadow_frame_under_construction->GetLink(); +ShadowFrame* Thread::PopStackedShadowFrame(StackedShadowFrameType type) { + StackedShadowFrameRecord* record = tlsPtr_.stacked_shadow_frame_record; + DCHECK(record != nullptr); + DCHECK_EQ(record->GetType(), type); + tlsPtr_.stacked_shadow_frame_record = record->GetLink(); + ShadowFrame* shadow_frame = record->GetShadowFrame(); + delete record; + return shadow_frame; } void Thread::InitTid() { @@ -2387,21 +2440,27 @@ void Thread::VisitRoots(RootVisitor* visitor) { if (tlsPtr_.debug_invoke_req != nullptr) { tlsPtr_.debug_invoke_req->VisitRoots(visitor, RootInfo(kRootDebugger, thread_id)); } - if (tlsPtr_.deoptimization_shadow_frame != nullptr) { + if (tlsPtr_.stacked_shadow_frame_record != nullptr) { RootCallbackVisitor visitor_to_callback(visitor, thread_id); ReferenceMapVisitor<RootCallbackVisitor> mapper(this, nullptr, visitor_to_callback); - for (ShadowFrame* shadow_frame = tlsPtr_.deoptimization_shadow_frame; shadow_frame != nullptr; - shadow_frame = shadow_frame->GetLink()) { - mapper.VisitShadowFrame(shadow_frame); + for (StackedShadowFrameRecord* record = tlsPtr_.stacked_shadow_frame_record; + record != nullptr; + record = record->GetLink()) { + for (ShadowFrame* shadow_frame = record->GetShadowFrame(); + shadow_frame != nullptr; + shadow_frame = shadow_frame->GetLink()) { + mapper.VisitShadowFrame(shadow_frame); + } } } - if (tlsPtr_.shadow_frame_under_construction != nullptr) { - RootCallbackVisitor visitor_to_callback(visitor, thread_id); - ReferenceMapVisitor<RootCallbackVisitor> mapper(this, nullptr, visitor_to_callback); - for (ShadowFrame* shadow_frame = tlsPtr_.shadow_frame_under_construction; - shadow_frame != nullptr; - shadow_frame = shadow_frame->GetLink()) { - mapper.VisitShadowFrame(shadow_frame); + if (tlsPtr_.deoptimization_return_value_stack != nullptr) { + for (DeoptimizationReturnValueRecord* record = tlsPtr_.deoptimization_return_value_stack; + record != nullptr; + record = record->GetLink()) { + if (record->IsReference()) { + visitor->VisitRootIfNonNull(record->GetGCRoot(), + RootInfo(kRootThreadObject, thread_id)); + } } } for (auto* verifier = tlsPtr_.method_verifier; verifier != nullptr; verifier = verifier->link_) { @@ -2519,12 +2578,11 @@ void Thread::SetDebugInvokeReq(DebugInvokeReq* req) { } void Thread::ClearDebugInvokeReq() { - CHECK(Dbg::IsDebuggerActive()); CHECK(GetInvokeReq() != nullptr) << "Debug invoke req not active in thread " << *this; CHECK(Thread::Current() == this) << "Debug invoke must be finished by the thread itself"; - // We do not own the DebugInvokeReq* so we must not delete it, it is the responsibility of - // the owner (the JDWP thread). + DebugInvokeReq* req = tlsPtr_.debug_invoke_req; tlsPtr_.debug_invoke_req = nullptr; + delete req; } void Thread::PushVerifier(verifier::MethodVerifier* verifier) { |