Visit methods in stack frames during root visits.
This is necessary for a Baker-style read barrier to-space invariant to
hold. That is, an object either needs to be marked/forwarded as root
or it must be accessed only through a read barrier by mutators. Since
stack frames have direct pointers to methods that a mutator can access
without a read barrier, stack frame methods have to be visited as
root, which makes sense as stack frames are thread roots. This is the
case even if methods do not move as they have to be marked 'gray' for
the objects pointed to by them, which can move, to be recursively
marked/forwarded.
This also puts us in the right direction toward moving methods (and
fields) in the future.
Bug: 12687968
Change-Id: Id32b913c021a140073deea9149a8782e8f308303
diff --git a/runtime/thread.cc b/runtime/thread.cc
index d535118..085a8e7 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1962,7 +1962,10 @@
}
void VisitShadowFrame(ShadowFrame* shadow_frame) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::ArtMethod* m = shadow_frame->GetMethod();
+ mirror::ArtMethod** method_addr = shadow_frame->GetMethodAddress();
+ visitor_(reinterpret_cast<mirror::Object**>(method_addr), 0 /*ignored*/, this);
+ mirror::ArtMethod* m = *method_addr;
+ DCHECK(m != nullptr);
size_t num_regs = shadow_frame->NumberOfVRegs();
if (m->IsNative() || shadow_frame->HasReferenceArray()) {
// handle scope for JNI or References for interpreter.
@@ -2003,7 +2006,9 @@
private:
void VisitQuickFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::ArtMethod* m = GetMethod();
+ mirror::ArtMethod** method_addr = GetMethodAddress();
+ visitor_(reinterpret_cast<mirror::Object**>(method_addr), 0 /*ignored*/, this);
+ mirror::ArtMethod* m = *method_addr;
// Process register map (which native and runtime methods don't have)
if (!m->IsNative() && !m->IsRuntimeMethod() && !m->IsProxyMethod()) {
const uint8_t* native_gc_map = m->GetNativeGcMap();