Allow null self only in DecodeWeakGlobalDuringShutdown().

To follow up CL 169855, allow a null current thread only in
DecodeWeakGlobalDuringShutdown() as a special case rather than
DecodeWeakGlobal(). This is to prevent a bug where null is accidentally
passed to DecodeWeakGlobal().

Bug: 23897251

Change-Id: I5e7bb78ec739b8bfcf77284ed321d507737ee33e
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 73da2cb..bc8a9f4 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1505,7 +1505,7 @@
   JavaVMExt* const vm = Runtime::Current()->GetJavaVM();
   for (jweak weak_root : class_loaders_) {
     auto* const class_loader = down_cast<mirror::ClassLoader*>(
-        vm->DecodeWeakGlobal(self, weak_root));
+        vm->DecodeWeakGlobalDuringShutdown(self, weak_root));
     if (class_loader != nullptr) {
       delete class_loader->GetClassTable();
     }
diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc
index 63e8887..531e039 100644
--- a/runtime/java_vm_ext.cc
+++ b/runtime/java_vm_ext.cc
@@ -580,12 +580,10 @@
 }
 
 inline bool JavaVMExt::MayAccessWeakGlobalsUnlocked(Thread* self) const {
-  if (kUseReadBarrier) {
-    // self can be null during a runtime shutdown. ~Runtime()->~ClassLinker()->DecodeWeakGlobal().
-    return self != nullptr ? self->GetWeakRefAccessEnabled() : true;
-  } else {
-    return allow_accessing_weak_globals_.LoadSequentiallyConsistent();
-  }
+  DCHECK(self != nullptr);
+  return kUseReadBarrier ?
+      self->GetWeakRefAccessEnabled() :
+      allow_accessing_weak_globals_.LoadSequentiallyConsistent();
 }
 
 mirror::Object* JavaVMExt::DecodeWeakGlobal(Thread* self, IndirectRef ref) {
@@ -613,6 +611,19 @@
   return weak_globals_.Get(ref);
 }
 
+mirror::Object* JavaVMExt::DecodeWeakGlobalDuringShutdown(Thread* self, IndirectRef ref) {
+  DCHECK_EQ(GetIndirectRefKind(ref), kWeakGlobal);
+  DCHECK(Runtime::Current()->IsShuttingDown(self));
+  if (self != nullptr) {
+    return DecodeWeakGlobal(self, ref);
+  }
+  // self can be null during a runtime shutdown. ~Runtime()->~ClassLinker()->DecodeWeakGlobal().
+  if (!kUseReadBarrier) {
+    DCHECK(allow_accessing_weak_globals_.LoadSequentiallyConsistent());
+  }
+  return weak_globals_.SynchronizedGet(ref);
+}
+
 void JavaVMExt::UpdateWeakGlobal(Thread* self, IndirectRef ref, mirror::Object* result) {
   MutexLock mu(self, weak_globals_lock_);
   weak_globals_.Update(ref, result);
diff --git a/runtime/java_vm_ext.h b/runtime/java_vm_ext.h
index 87430c8..b539bbd 100644
--- a/runtime/java_vm_ext.h
+++ b/runtime/java_vm_ext.h
@@ -138,6 +138,12 @@
       SHARED_REQUIRES(Locks::mutator_lock_)
       REQUIRES(weak_globals_lock_);
 
+  // Like DecodeWeakGlobal() but to be used only during a runtime shutdown where self may be
+  // null.
+  mirror::Object* DecodeWeakGlobalDuringShutdown(Thread* self, IndirectRef ref)
+      SHARED_REQUIRES(Locks::mutator_lock_)
+      REQUIRES(!weak_globals_lock_);
+
   Mutex& WeakGlobalsLock() RETURN_CAPABILITY(weak_globals_lock_) {
     return weak_globals_lock_;
   }