ART: Fix forbidden thread state change in interpreter
While loading a type for assignability, it might happen that it's
not available yet locally and must be resolved. Formerly, we
disallowed a state change to ensure no GC taking place while a new
shadow frame has not been pushed on the stack yet.
As a fix, allow a "shadow frame under construction" in the thread,
which is visited during GC.
Change-Id: I973487a46b0e9e21fd6d49099d713b58f06d3b45
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 758944c..f89fada 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -122,6 +122,16 @@
return sf;
}
+void Thread::SetShadowFrameUnderConstruction(ShadowFrame* sf) {
+ sf->SetLink(tlsPtr_.shadow_frame_under_construction);
+ tlsPtr_.shadow_frame_under_construction = sf;
+}
+
+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();
+}
+
void Thread::InitTid() {
tls32_.tid = ::art::GetTid();
}
@@ -2128,6 +2138,15 @@
mapper.VisitShadowFrame(shadow_frame);
}
}
+ if (tlsPtr_.shadow_frame_under_construction != nullptr) {
+ RootCallbackVisitor visitorToCallback(visitor, arg, thread_id);
+ ReferenceMapVisitor<RootCallbackVisitor> mapper(this, nullptr, visitorToCallback);
+ for (ShadowFrame* shadow_frame = tlsPtr_.shadow_frame_under_construction;
+ shadow_frame != nullptr;
+ shadow_frame = shadow_frame->GetLink()) {
+ mapper.VisitShadowFrame(shadow_frame);
+ }
+ }
// Visit roots on this thread's stack
Context* context = GetLongJumpContext();
RootCallbackVisitor visitorToCallback(visitor, arg, thread_id);