Merge "Fix race condition for method root marking in VisitNativeRoots"
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 7f89b1d..15f2887 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -832,11 +832,21 @@
       f->VisitRoots(visitor);
     }
   }
-  for (auto& m : GetDirectMethods(pointer_size)) {
-    m.VisitRoots(visitor);
+  // We may see GetDirectMethodsPtr() == null with NumDirectMethods() != 0 if the root marking
+  // thread reads a null DirectMethodsBegin() but a non null DirectMethodsBegin() due to a race
+  // SetDirectMethodsPtr from class linking. Same for virtual methods.
+  // In this case, it is safe to avoid marking the roots since we must be either the CC or CMS. If
+  // we are CMS then the roots are already marked through other sources, otherwise the roots are
+  // already marked due to the to-space invariant.
+  if (GetDirectMethodsPtr() != nullptr) {
+    for (auto& m : GetDirectMethods(pointer_size)) {
+      m.VisitRoots(visitor);
+    }
   }
-  for (auto& m : GetVirtualMethods(pointer_size)) {
-    m.VisitRoots(visitor);
+  if (GetVirtualMethodsPtr() != nullptr) {
+    for (auto& m : GetVirtualMethods(pointer_size)) {
+      m.VisitRoots(visitor);
+    }
   }
 }