Pull the Reference setup code into InitRefs.c.

The idea here is to make it obvious in the setup code that Reference
has to be set up specially, to make it less likely that it will get
erroneously combined with the other setup code in the future.

Since the class Reference itself isn't used, I took the opportunity
to just remove it from Globals.h.

Change-Id: I301c0ac2032e78e1e57cc3065eb0baa77f0d346f
diff --git a/vm/Globals.h b/vm/Globals.h
index fcfaae5..269ffc9 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -253,7 +253,6 @@
     ClassObject* classJavaLangReflectMethod;
     ClassObject* classJavaLangReflectMethodArray;
     ClassObject* classJavaLangReflectProxy;
-    ClassObject* classJavaLangRefReference;
     ClassObject* classJavaNioReadWriteDirectByteBuffer;
     ClassObject* classJavaSecurityAccessController;
     ClassObject* classOrgApacheHarmonyLangAnnotationAnnotationFactory;
diff --git a/vm/Init.h b/vm/Init.h
index 60f6bf3..4d85c2e 100644
--- a/vm/Init.h
+++ b/vm/Init.h
@@ -51,6 +51,14 @@
 bool dvmFindRequiredClassesAndMembers(void);
 
 /*
+ * Look up required members of the class Reference, and set the global
+ * reference to Reference itself too. This needs to be done separately
+ * from dvmFindRequiredClassesAndMembers(), during the course of
+ * linking the class Reference (which is done specially).
+ */
+bool dvmFindReferenceMembers(ClassObject* classReference);
+
+/*
  * Replacement for fprintf() when we want to send a message to the console.
  * This defaults to fprintf(), but will use the JNI fprintf callback if
  * one was provided.
diff --git a/vm/InitRefs.c b/vm/InitRefs.c
index 11bf04e..beca536 100644
--- a/vm/InitRefs.c
+++ b/vm/InitRefs.c
@@ -624,3 +624,41 @@
 
     return ok;
 }
+
+/* (documented in header) */
+bool dvmFindReferenceMembers(ClassObject* classReference) {
+    if (gDvm.methJavaLangRefReference_enqueueInternal != NULL) {
+        LOGE("Attempt to set up class Reference more than once\n");
+        return false;
+    }
+
+    if (strcmp(classReference->descriptor, "Ljava/lang/ref/Reference;") != 0) {
+        LOGE("Attempt to set up the wrong class as Reference\n");
+        return false;
+    }
+
+    bool ok = true;
+
+    gDvm.offJavaLangRefReference_referent =
+        dvmFindFieldOffset(classReference, "referent", "Ljava/lang/Object;");
+    ok &= (gDvm.offJavaLangRefReference_referent >= 0);
+
+    gDvm.offJavaLangRefReference_queue =
+        dvmFindFieldOffset(classReference, "queue", "Ljava/lang/ref/ReferenceQueue;");
+    ok &= (gDvm.offJavaLangRefReference_queue >= 0);
+
+    gDvm.offJavaLangRefReference_queueNext =
+        dvmFindFieldOffset(classReference, "queueNext", "Ljava/lang/ref/Reference;");
+    ok &= (gDvm.offJavaLangRefReference_queueNext >= 0);
+
+    gDvm.offJavaLangRefReference_pendingNext =
+        dvmFindFieldOffset(classReference, "pendingNext", "Ljava/lang/ref/Reference;");
+    ok &= (gDvm.offJavaLangRefReference_pendingNext >= 0);
+
+    /* enqueueInternal() is private and thus a direct method. */
+    Method *meth = dvmFindDirectMethodByDescriptor(classReference, "enqueueInternal", "()Z");
+    ok &= (meth != NULL);
+    gDvm.methJavaLangRefReference_enqueueInternal = meth;
+
+    return ok;
+}
diff --git a/vm/alloc/Copying.c b/vm/alloc/Copying.c
index 02eab93..f257ce3 100644
--- a/vm/alloc/Copying.c
+++ b/vm/alloc/Copying.c
@@ -2136,7 +2136,6 @@
     scavengeReference((Object **)(void *)&gDvm.classJavaLangReflectMethodArray);
     scavengeReference((Object **)(void *)&gDvm.classJavaLangReflectProxy);
     scavengeReference((Object **)(void *)&gDvm.classJavaLangExceptionInInitializerError);
-    scavengeReference((Object **)(void *)&gDvm.classJavaLangRefReference);
     scavengeReference((Object **)(void *)&gDvm.classJavaNioReadWriteDirectByteBuffer);
     scavengeReference((Object **)(void *)&gDvm.classJavaSecurityAccessController);
     scavengeReference((Object **)(void *)&gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory);
diff --git a/vm/oo/Class.c b/vm/oo/Class.c
index 16fb5d3..45f1016 100644
--- a/vm/oo/Class.c
+++ b/vm/oo/Class.c
@@ -2281,7 +2281,6 @@
  */
 static bool precacheReferenceOffsets(ClassObject* clazz)
 {
-    Method *meth;
     int i;
 
     /* We trick the GC object scanner by not counting
@@ -2332,36 +2331,14 @@
         return false;
     }
 
-    /* Cache pretty much everything about Reference so that
-     * we don't need to call interpreted code when clearing/enqueueing
-     * references.  This is fragile, so we'll be paranoid.
+    /*
+     * Now that the above has been done, it is safe to cache
+     * info about the class.
      */
-    gDvm.classJavaLangRefReference = clazz;
-
-    gDvm.offJavaLangRefReference_referent =
-        dvmFindFieldOffset(gDvm.classJavaLangRefReference,
-                "referent", "Ljava/lang/Object;");
-    assert(gDvm.offJavaLangRefReference_referent >= 0);
-
-    gDvm.offJavaLangRefReference_queue =
-        dvmFindFieldOffset(gDvm.classJavaLangRefReference,
-                "queue", "Ljava/lang/ref/ReferenceQueue;");
-    assert(gDvm.offJavaLangRefReference_queue >= 0);
-
-    gDvm.offJavaLangRefReference_queueNext =
-        dvmFindFieldOffset(gDvm.classJavaLangRefReference,
-                "queueNext", "Ljava/lang/ref/Reference;");
-    assert(gDvm.offJavaLangRefReference_queueNext >= 0);
-
-    gDvm.offJavaLangRefReference_pendingNext =
-        dvmFindFieldOffset(gDvm.classJavaLangRefReference,
-                "pendingNext", "Ljava/lang/ref/Reference;");
-    assert(gDvm.offJavaLangRefReference_pendingNext >= 0);
-
-    /* enqueueInternal() is private and thus a direct method. */
-    meth = dvmFindDirectMethodByDescriptor(clazz, "enqueueInternal", "()Z");
-    assert(meth != NULL);
-    gDvm.methJavaLangRefReference_enqueueInternal = meth;
+    if (!dvmFindReferenceMembers(clazz)) {
+        LOGE("Trouble with Reference setup\n");
+        return false;
+    }
 
     return true;
 }