ART: Correct static invariant checks

Instances of initializing classes may leak to other threads. It is
legal to execute methods and access fields, as long as they are not
static. However, the class should still be initializing (or already
be erroneous). Replace checks with this weaker invariant.

Follow-up to commit 4e99b3d8955131f3fc71aa113f0fa71f0092cb6f.

Bug: 15899971
Bug: 62478025
Bug: 67719550
Test: m test-art-host
Change-Id: I63190253759df95ca54e40fd4117a24e12e0c069
diff --git a/runtime/common_dex_operations.h b/runtime/common_dex_operations.h
index 4d5bd3f..6a78637 100644
--- a/runtime/common_dex_operations.h
+++ b/runtime/common_dex_operations.h
@@ -71,6 +71,18 @@
   }
 }
 
+template <typename T>
+inline void DCheckStaticState(Thread* self, T* entity) REQUIRES_SHARED(Locks::mutator_lock_) {
+  if (kIsDebugBuild) {
+    ObjPtr<mirror::Class> klass = entity->GetDeclaringClass();
+    if (entity->IsStatic()) {
+      klass->AssertInitializedOrInitializingInThread(self);
+    } else {
+      CHECK(klass->IsInitializing() || klass->IsErroneousResolved());
+    }
+  }
+}
+
 template<Primitive::Type field_type>
 static ALWAYS_INLINE bool DoFieldGetCommon(Thread* self,
                                            const ShadowFrame& shadow_frame,
@@ -78,7 +90,7 @@
                                            ArtField* field,
                                            JValue* result)
     REQUIRES_SHARED(Locks::mutator_lock_) {
-  field->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self);
+  DCheckStaticState(self, field);
 
   // Report this field access to instrumentation if needed.
   instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
@@ -136,7 +148,7 @@
                                     ArtField* field,
                                     JValue& value)
     REQUIRES_SHARED(Locks::mutator_lock_) {
-  field->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self);
+  DCheckStaticState(self, field);
 
   // Report this field access to instrumentation if needed. Since we only have the offset of
   // the field from the base of the object, we need to look for it first.
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 68a75b0..2deb3b7 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -18,6 +18,7 @@
 
 #include <limits>
 
+#include "common_dex_operations.h"
 #include "common_throws.h"
 #include "dex_file_types.h"
 #include "interpreter_common.h"
@@ -287,11 +288,12 @@
     }
   }
 
-  shadow_frame.GetMethod()->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self);
+  ArtMethod* method = shadow_frame.GetMethod();
+
+  DCheckStaticState(self, method);
 
   // Lock counting is a special version of accessibility checks, and for simplicity and
   // reduction of template parameters, we gate it behind access-checks mode.
-  ArtMethod* method = shadow_frame.GetMethod();
   DCHECK(!method->SkipAccessChecks() || !method->MustCountLocks());
 
   bool transaction_active = Runtime::Current()->IsActiveTransaction();