Yet more InitRefs-ing

Fix up some early initialization stuff.

Also, stop pretending that the top of non-main-thread stacks is a
Runnable.

Change-Id: I3e89c6320351c160cfa0bea3cf6bbfd26a5b7c12
diff --git a/vm/Globals.h b/vm/Globals.h
index a197fd7..9d697ce 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -325,6 +325,7 @@
     int         offJavaLangThread_name;
     int         offJavaLangThread_priority;
     int         offJavaLangThread_uncaughtHandler;
+    int         offJavaLangThread_contextClassLoader;
 
     /* method offsets - Thread */
     int         voffJavaLangThread_run;
@@ -347,6 +348,9 @@
     /* method offsets - ClassLoader */
     int         voffJavaLangClassLoader_loadClass;
 
+    /* direct method pointers - ClassLoader */
+    Method*     methJavaLangClassLoader_getSystemClassLoader;
+
     /* field offsets - java.lang.reflect.* */
     int         offJavaLangReflectAccessibleObject_flag;
     int         offJavaLangReflectConstructor_slot;
@@ -366,7 +370,7 @@
     Method*     methJavaLangRefReference_enqueueInternal;
 
     /* more method pointers - java.lang.ref.FinalizerReference */
-    Method* methJavaLangRefFinalizerReferenceAdd;
+    Method*     methJavaLangRefFinalizerReferenceAdd;
 
     /* constructor method pointers; no vtable involved, so use Method* */
     Method*     methJavaLangStackTraceElement_init;
@@ -388,8 +392,9 @@
     /* field offsets - java.io.FileDescriptor */
     int         offJavaIoFileDescriptor_descriptor;
 
-    /* fake native entry point method */
-    Method*     methFakeNativeEntry;
+    /* direct method pointers - dalvik.system.NativeStart */
+    Method*     methDalvikSystemNativeStart_main;
+    Method*     methDalvikSystemNativeStart_run;
 
     /* assorted direct buffer helpers */
     Method*     methJavaNioReadWriteDirectByteBuffer_init;
diff --git a/vm/InitRefs.c b/vm/InitRefs.c
index a1ca1b1..4855697 100644
--- a/vm/InitRefs.c
+++ b/vm/InitRefs.c
@@ -278,12 +278,13 @@
     };
 
     static struct FieldInfo infoThread[] = {
-        { &gDvm.offJavaLangThread_vmThread,        "vmThread",        "Ljava/lang/VMThread;" },
-        { &gDvm.offJavaLangThread_group,           "group",           "Ljava/lang/ThreadGroup;" },
-        { &gDvm.offJavaLangThread_daemon,          "daemon",          "Z" },
-        { &gDvm.offJavaLangThread_name,            "name",            "Ljava/lang/String;" },
-        { &gDvm.offJavaLangThread_priority,        "priority",        "I" },
-        { &gDvm.offJavaLangThread_uncaughtHandler, "uncaughtHandler", "Ljava/lang/Thread$UncaughtExceptionHandler;" },
+        { &gDvm.offJavaLangThread_vmThread,           "vmThread",           "Ljava/lang/VMThread;" },
+        { &gDvm.offJavaLangThread_group,              "group",              "Ljava/lang/ThreadGroup;" },
+        { &gDvm.offJavaLangThread_daemon,             "daemon",             "Z" },
+        { &gDvm.offJavaLangThread_name,               "name",               "Ljava/lang/String;" },
+        { &gDvm.offJavaLangThread_priority,           "priority",           "I" },
+        { &gDvm.offJavaLangThread_uncaughtHandler,    "uncaughtHandler",    "Ljava/lang/Thread$UncaughtExceptionHandler;" },
+        { &gDvm.offJavaLangThread_contextClassLoader, "contextClassLoader", "Ljava/lang/ClassLoader;" },
         { NULL, NULL, NULL }
     };
 
@@ -440,6 +441,8 @@
         const char* name;
         const char* descriptor;
     } methods[] = {
+        { &gDvm.methJavaLangClassLoader_getSystemClassLoader, "Ljava/lang/ClassLoader;",
+          "getSystemClassLoader", "()Ljava/lang/ClassLoader;" },
         { &gDvm.methJavaLangReflectProxy_constructorPrototype, "Ljava/lang/reflect/Proxy;",
           "constructorPrototype", "(Ljava/lang/reflect/InvocationHandler;)V" },
         { &gDvm.methodTraceGcMethod, "Ldalvik/system/VMDebug;", "startGC", "()V" },
@@ -449,6 +452,8 @@
           "(Ljava/lang/Class;[Lorg/apache/harmony/lang/annotation/AnnotationMember;)"
           "Ljava/lang/annotation/Annotation;" },
         { &gDvm.methodTraceClassPrepMethod, "Ldalvik/system/VMDebug;", "startClassPrep", "()V" },
+        { &gDvm.methDalvikSystemNativeStart_main, "Ldalvik/system/NativeStart;", "main", "([Ljava/lang/String;)V" },
+        { &gDvm.methDalvikSystemNativeStart_run, "Ldalvik/system/NativeStart;", "run", "()V" },
         { &gDvm.methJavaLangRefFinalizerReferenceAdd,
           "Ljava/lang/ref/FinalizerReference;", "add", "(Ljava/lang/Object;)V" },
         { NULL, NULL, NULL, NULL }
diff --git a/vm/Jni.c b/vm/Jni.c
index e39a065..58e5459 100644
--- a/vm/Jni.c
+++ b/vm/Jni.c
@@ -1462,7 +1462,7 @@
         /* hack for JNI_OnLoad */
         assert(strcmp(thisMethod->name, "nativeLoad") == 0);
         loader = _self->classLoaderOverride;
-    } else if (thisMethod == gDvm.methFakeNativeEntry) {
+    } else if (thisMethod == gDvm.methDalvikSystemNativeStart_main) {
         /* start point of invocation interface */
         if (!gDvm.initializing)
             loader = trackedLoader = dvmGetSystemClassLoader();
diff --git a/vm/Thread.c b/vm/Thread.c
index a1558ce..cc3d1c4 100644
--- a/vm/Thread.c
+++ b/vm/Thread.c
@@ -774,27 +774,22 @@
     thread->threadObj = threadObj;
 
     /*
-     * Set the context class loader.  This invokes a ClassLoader method,
-     * which could conceivably call Thread.currentThread(), so we want the
-     * Thread to be fully configured before we do this.
+     * Set the "context class loader" field in the system class loader.
+     *
+     * Retrieving the system class loader will cause invocation of
+     * ClassLoader.getSystemClassLoader(), which could conceivably call
+     * Thread.currentThread(), so we want the Thread to be fully configured
+     * before we do this.
      */
     Object* systemLoader = dvmGetSystemClassLoader();
     if (systemLoader == NULL) {
         LOGW("WARNING: system class loader is NULL (setting main ctxt)\n");
-        /* keep going */
+        /* keep going? */
+    } else {
+        dvmSetFieldObject(threadObj, gDvm.offJavaLangThread_contextClassLoader,
+            systemLoader);
+        dvmReleaseTrackedAlloc(systemLoader, NULL);
     }
-    int ctxtClassLoaderOffset = dvmFindFieldOffset(gDvm.classJavaLangThread,
-        "contextClassLoader", "Ljava/lang/ClassLoader;");
-    if (ctxtClassLoaderOffset < 0) {
-        LOGE("Unable to find contextClassLoader field in Thread\n");
-        return false;
-    }
-    dvmSetFieldObject(threadObj, ctxtClassLoaderOffset, systemLoader);
-    dvmReleaseTrackedAlloc(systemLoader, NULL);
-
-    /*
-     * Finish our thread prep.
-     */
 
     /* include self in non-daemon threads (mainly for AttachCurrentThread) */
     gDvm.nonDaemonThreadCount++;
@@ -1136,54 +1131,31 @@
  */
 static bool createFakeEntryFrame(Thread* thread)
 {
-    assert(thread->threadId == kMainThreadId);      // main thread only
+    /*
+     * Because we are creating a frame that represents application code, we
+     * want to stuff the application class loader into the method's class
+     * loader field, even though we're using the system class loader to
+     * load it.  This makes life easier over in JNI FindClass (though it
+     * could bite us in other ways).
+     *
+     * Unfortunately this is occurring too early in the initialization,
+     * of necessity coming before JNI is initialized, and we're not quite
+     * ready to set up the application class loader.  Also, overwriting
+     * the class' defining classloader pointer seems unwise.
+     *
+     * Instead, we save a pointer to the method and explicitly check for
+     * it in FindClass.  The method is private so nobody else can call it.
+     */
 
-    /* find the method on first use */
-    if (gDvm.methFakeNativeEntry == NULL) {
-        ClassObject* nativeStart;
-        Method* mainMeth;
+    assert(thread->threadId == kMainThreadId);      /* main thread only */
 
-        nativeStart = dvmFindSystemClassNoInit(
-                "Ldalvik/system/NativeStart;");
-        if (nativeStart == NULL) {
-            LOGE("Unable to find dalvik.system.NativeStart class\n");
-            return false;
-        }
-
-        /*
-         * Because we are creating a frame that represents application code, we
-         * want to stuff the application class loader into the method's class
-         * loader field, even though we're using the system class loader to
-         * load it.  This makes life easier over in JNI FindClass (though it
-         * could bite us in other ways).
-         *
-         * Unfortunately this is occurring too early in the initialization,
-         * of necessity coming before JNI is initialized, and we're not quite
-         * ready to set up the application class loader.
-         *
-         * So we save a pointer to the method in gDvm.methFakeNativeEntry
-         * and check it in FindClass.  The method is private so nobody else
-         * can call it.
-         */
-        //nativeStart->classLoader = dvmGetSystemClassLoader();
-
-        mainMeth = dvmFindDirectMethodByDescriptor(nativeStart,
-                    "main", "([Ljava/lang/String;)V");
-        if (mainMeth == NULL) {
-            LOGE("Unable to find 'main' in dalvik.system.NativeStart\n");
-            return false;
-        }
-
-        gDvm.methFakeNativeEntry = mainMeth;
-    }
-
-    if (!dvmPushJNIFrame(thread, gDvm.methFakeNativeEntry))
+    if (!dvmPushJNIFrame(thread, gDvm.methDalvikSystemNativeStart_main))
         return false;
 
     /*
      * Null out the "String[] args" argument.
      */
-    assert(gDvm.methFakeNativeEntry->registersSize == 1);
+    assert(gDvm.methDalvikSystemNativeStart_main->registersSize == 1);
     u4* framePtr = (u4*) thread->curFrame;
     framePtr[0] = 0;
 
@@ -1198,41 +1170,7 @@
  */
 static bool createFakeRunFrame(Thread* thread)
 {
-    ClassObject* nativeStart;
-    Method* runMeth;
-
-    /*
-     * TODO: cache this result so we don't have to dig for it every time
-     * somebody attaches a thread to the VM.  Also consider changing this
-     * to a static method so we don't have a null "this" pointer in the
-     * "ins" on the stack.  (Does it really need to look like a Runnable?)
-     */
-    nativeStart = dvmFindSystemClassNoInit("Ldalvik/system/NativeStart;");
-    if (nativeStart == NULL) {
-        LOGE("Unable to find dalvik.system.NativeStart class\n");
-        return false;
-    }
-
-    runMeth = dvmFindVirtualMethodByDescriptor(nativeStart, "run", "()V");
-    if (runMeth == NULL) {
-        LOGE("Unable to find 'run' in dalvik.system.NativeStart\n");
-        return false;
-    }
-
-    if (!dvmPushJNIFrame(thread, runMeth))
-        return false;
-
-    /*
-     * Provide a NULL 'this' argument.  The method we've put at the top of
-     * the stack looks like a virtual call to run() in a Runnable class.
-     * (If we declared the method static, it wouldn't take any arguments
-     * and we wouldn't have to do this.)
-     */
-    assert(runMeth->registersSize == 1);
-    u4* framePtr = (u4*) thread->curFrame;
-    framePtr[0] = 0;
-
-    return true;
+    return dvmPushJNIFrame(thread, gDvm.methDalvikSystemNativeStart_run);
 }
 
 /*
@@ -3441,14 +3379,9 @@
     groupObj = (Object*) dvmGetFieldObject(threadObj,
                 gDvm.offJavaLangThread_group);
     if (groupObj != NULL) {
-        int offset = dvmFindFieldOffset(gDvm.classJavaLangThreadGroup,
-            "name", "Ljava/lang/String;");
-        if (offset < 0) {
-            LOGW("Unable to find 'name' field in ThreadGroup\n");
-        } else {
-            nameStr = (StringObject*) dvmGetFieldObject(groupObj, offset);
-            groupName = dvmCreateCstrFromString(nameStr);
-        }
+        nameStr = (StringObject*)
+            dvmGetFieldObject(groupObj, gDvm.offJavaLangThreadGroup_name);
+        groupName = dvmCreateCstrFromString(nameStr);
     }
     if (groupName == NULL)
         groupName = strdup("(null; initializing?)");
diff --git a/vm/oo/Class.c b/vm/oo/Class.c
index a054bdc..1206383 100644
--- a/vm/oo/Class.c
+++ b/vm/oo/Class.c
@@ -4656,22 +4656,15 @@
 Object* dvmGetSystemClassLoader(void)
 {
     Thread* self = dvmThreadSelf();
-    ClassObject* clazz;
-    Method* getSysMeth;
-    Object* loader;
+    ClassObject* clClass = gDvm.classJavaLangClassLoader;
 
-    clazz = dvmFindSystemClass("Ljava/lang/ClassLoader;");
-    if (clazz == NULL)
-        return NULL;
-
-    getSysMeth = dvmFindDirectMethodByDescriptor(clazz, "getSystemClassLoader",
-        "()Ljava/lang/ClassLoader;");
-    if (getSysMeth == NULL)
+    if (!dvmIsClassInitialized(clClass) && !dvmInitClass(clClass))
         return NULL;
 
     JValue result;
-    dvmCallMethod(self, getSysMeth, NULL, &result);
-    loader = (Object*)result.l;
+    dvmCallMethod(self, gDvm.methJavaLangClassLoader_getSystemClassLoader,
+        NULL, &result);
+    Object* loader = (Object*)result.l;
     dvmAddTrackedAlloc(loader, self);
     return loader;
 }