Fix test 046.

Looks like a recent change put us on an untested code path, and we need
to start distinguishing callers' intentions. We can also remove some
unnecessary duplication.

Change-Id: I950139e6fdc8656b89d8e1520e8b50f681c7f7b2
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index f680d2b..0fe52c8 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -920,7 +920,7 @@
   EXPECT_EQ(Aj2, A->FindVirtualMethodForVirtualOrInterface(Jj2));
 }
 
-TEST_F(ClassLinkerTest, InitializeStaticStorageFromCode) {
+TEST_F(ClassLinkerTest, ResolveVerifyAndClinit) {
   // pretend we are trying to get the static storage for the StaticsFromCode class.
 
   // case 1, get the uninitialized storage from StaticsFromCode.<clinit>
@@ -939,10 +939,10 @@
   ASSERT_TRUE(type_id != NULL);
   uint32_t type_idx = dex_file->GetIndexForTypeId(*type_id);
   EXPECT_TRUE(clinit->GetDexCacheInitializedStaticStorage()->Get(type_idx) == NULL);
-  StaticStorageBase* uninit = InitializeStaticStorage(type_idx, clinit, Thread::Current());
+  StaticStorageBase* uninit = ResolveVerifyAndClinit(type_idx, clinit, Thread::Current(), true, false);
   EXPECT_TRUE(uninit != NULL);
   EXPECT_TRUE(clinit->GetDexCacheInitializedStaticStorage()->Get(type_idx) == NULL);
-  StaticStorageBase* init = InitializeStaticStorage(type_idx, getS0, Thread::Current());
+  StaticStorageBase* init = ResolveVerifyAndClinit(type_idx, getS0, Thread::Current(), true, false);
   EXPECT_TRUE(init != NULL);
   EXPECT_EQ(init, clinit->GetDexCacheInitializedStaticStorage()->Get(type_idx));
 }
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 160ca49..f73e621 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -785,43 +785,25 @@
   }
 }
 
-Class* InitializeStaticStorage(uint32_t type_idx, const Method* referrer, Thread* self) {
+Class* ResolveVerifyAndClinit(uint32_t type_idx, const Method* referrer, Thread* self,
+                               bool can_run_clinit, bool verify_access) {
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   Class* klass = class_linker->ResolveType(type_idx, referrer);
   if (UNLIKELY(klass == NULL)) {
     CHECK(self->IsExceptionPending());
     return NULL;  // Failure - Indicate to caller to deliver exception
   }
-  DCHECK(referrer->GetDeclaringClass()->CanAccess(klass));
-  // If we are the <clinit> of this class, just return our storage.
-  //
-  // Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished
-  // running.
-  if (klass == referrer->GetDeclaringClass() && MethodHelper(referrer).IsClassInitializer()) {
-    return klass;
-  }
-  if (!class_linker->EnsureInitialized(klass, true)) {
-    CHECK(self->IsExceptionPending());
-    return NULL;  // Failure - Indicate to caller to deliver exception
-  }
-  referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass);
-  return klass;
-}
-
-Class* InitializeStaticStorageAndVerifyAccess(uint32_t type_idx, const Method* referrer,
-                                              Thread* self) {
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  Class* klass = class_linker->ResolveType(type_idx, referrer);
-  if (UNLIKELY(klass == NULL)) {
-    CHECK(self->IsExceptionPending());
-    return NULL;  // Failure - Indicate to caller to deliver exception
-  }
-  // Perform access check
-  if (UNLIKELY(!referrer->GetDeclaringClass()->CanAccess(klass))) {
+  // Perform access check if necessary.
+  if (verify_access && !referrer->GetDeclaringClass()->CanAccess(klass)) {
     self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
-        "Class %s is inaccessible to method %s",
-        PrettyDescriptor(klass).c_str(),
-        PrettyMethod(referrer, true).c_str());
+                             "Class %s is inaccessible to method %s",
+                             PrettyDescriptor(klass).c_str(),
+                             PrettyMethod(referrer, true).c_str());
+    return NULL;  // Failure - Indicate to caller to deliver exception
+  }
+  // If we're just implementing const-class, we shouldn't call <clinit>.
+  if (!can_run_clinit) {
+    return klass;
   }
   // If we are the <clinit> of this class, just return our storage.
   //
@@ -841,14 +823,14 @@
 extern "C" Class* artInitializeStaticStorageFromCode(uint32_t type_idx, const Method* referrer,
                                                      Thread* self, Method** sp) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  return InitializeStaticStorage(type_idx, referrer, self);
+  return ResolveVerifyAndClinit(type_idx, referrer, self, true, true);
 }
 
 extern "C" Class* artInitializeTypeFromCode(uint32_t type_idx, const Method* referrer, Thread* self,
                                             Method** sp) {
   // Called when method->dex_cache_resolved_types_[] misses
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  return InitializeStaticStorage(type_idx, referrer, self);
+  return ResolveVerifyAndClinit(type_idx, referrer, self, false, false);
 }
 
 extern "C" Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx,
@@ -857,7 +839,7 @@
   // Called when caller isn't guaranteed to have access to a type and the dex cache may be
   // unpopulated
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  return InitializeStaticStorageAndVerifyAccess(type_idx, referrer, self);
+  return ResolveVerifyAndClinit(type_idx, referrer, self, false, true);
 }
 
 // Helper function to resolve virtual method
diff --git a/src/runtime_support.h b/src/runtime_support.h
index 876abd7..a7c40c4 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -19,9 +19,8 @@
 extern void* FindNativeMethod(Thread* thread);
 extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp);
 void* UnresolvedDirectMethodTrampolineFromCode(int32_t, Method**, Thread*, Runtime::TrampolineType);
-extern Class* InitializeStaticStorage(uint32_t type_idx, const Method* referrer, Thread* self);
-extern Class* InitializeStaticStorageAndVerifyAccess(uint32_t type_idx, const Method* referrer,
-                                                     Thread* self);
+extern Class* ResolveVerifyAndClinit(uint32_t type_idx, const Method* referrer, Thread* self,
+                                     bool can_run_clinit, bool verify_access);
 extern Class* InitializeTypeFromCode(uint32_t type_idx, Method* method);
 uint32_t IsAssignableFromCode(const Class* klass, const Class* ref_class);
 void ObjectInitFromCode(Object* o);
diff --git a/test/046-reflect/expected.txt b/test/046-reflect/expected.txt
index b2bb176..240be94 100644
--- a/test/046-reflect/expected.txt
+++ b/test/046-reflect/expected.txt
@@ -93,6 +93,8 @@
 ReflectTest done!
 checkType invoking null
 checkType got expected exception
+calling const-class NoisyInitUser.class
+called const-class NoisyInitUser.class
 got methods
 NoisyInitUser is initializing
 NoisyInit is initializing
diff --git a/test/046-reflect/src/Main.java b/test/046-reflect/src/Main.java
index 7b6036b..9269e11 100644
--- a/test/046-reflect/src/Main.java
+++ b/test/046-reflect/src/Main.java
@@ -341,8 +341,10 @@
     }
 
     public static void checkInit() {
-        Class niuClass = NoisyInitUser.class;
-        Method[] methods;
+      System.out.println("calling const-class NoisyInitUser.class");
+      Class niuClass = NoisyInitUser.class;
+      System.out.println("called const-class NoisyInitUser.class");
+      Method[] methods;
 
         methods = niuClass.getDeclaredMethods();
         System.out.println("got methods");