Some more InitRefs-ing

Uncaught exception handling and FileDescriptor.descriptor.

Change-Id: Ia7429417a47e9a3e3d327b246c3ad33c6c77dfa0
diff --git a/vm/Globals.h b/vm/Globals.h
index efd0366..a197fd7 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -324,6 +324,7 @@
     int         offJavaLangThread_daemon;
     int         offJavaLangThread_name;
     int         offJavaLangThread_priority;
+    int         offJavaLangThread_uncaughtHandler;
 
     /* method offsets - Thread */
     int         voffJavaLangThread_run;
@@ -384,6 +385,9 @@
     /* field offsets - java.lang.reflect.Proxy */
     int         offJavaLangReflectProxy_h;
 
+    /* field offsets - java.io.FileDescriptor */
+    int         offJavaIoFileDescriptor_descriptor;
+
     /* fake native entry point method */
     Method*     methFakeNativeEntry;
 
diff --git a/vm/InitRefs.c b/vm/InitRefs.c
index 2bcd077..a1ca1b1 100644
--- a/vm/InitRefs.c
+++ b/vm/InitRefs.c
@@ -264,6 +264,11 @@
         const char* type;
     };
 
+    static struct FieldInfo infoFileDescriptor[] = {
+        { &gDvm.offJavaIoFileDescriptor_descriptor, "descriptor", "I" },
+        { NULL, NULL, NULL }
+    };
+
     static struct FieldInfo infoString[] = {
         { &gDvm.offJavaLangString_value,    "value",    "[C" },
         { &gDvm.offJavaLangString_count,    "count",    "I" },
@@ -273,11 +278,12 @@
     };
 
     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_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;" },
         { NULL, NULL, NULL }
     };
 
@@ -334,6 +340,7 @@
     };
 
     static struct { const char* name; const struct FieldInfo* fields; } classes[] = {
+        { "Ljava/io/FileDescriptor;",             infoFileDescriptor },
         { "Ljava/lang/String;",                   infoString },
         { "Ljava/lang/Thread;",                   infoThread },
         { "Ljava/lang/ThreadGroup;",              infoThreadGroup },
diff --git a/vm/Thread.c b/vm/Thread.c
index b347834..a1558ce 100644
--- a/vm/Thread.c
+++ b/vm/Thread.c
@@ -1614,13 +1614,15 @@
  * Version 1.5 added the per-thread handler.  We need to call
  * "uncaughtException" in the handler object, which is either the
  * ThreadGroup object or the Thread-specific handler.
+ *
+ * This should only be called when an exception is pending.  Before
+ * returning, the exception will be cleared.
  */
 static void threadExitUncaughtException(Thread* self, Object* group)
 {
     Object* exception;
     Object* handlerObj;
-    Method* uncaughtHandler = NULL;
-    InstField* threadHandler;
+    Method* uncaughtHandler;
 
     LOGW("threadid=%d: thread exiting with uncaught exception (group=%p)\n",
         self->threadId, group);
@@ -1631,25 +1633,24 @@
      * thread.  We don't want to have it set when executing interpreted code.
      */
     exception = dvmGetException(self);
+    assert(exception != NULL);
     dvmAddTrackedAlloc(exception, self);
     dvmClearException(self);
 
     /*
      * Get the Thread's "uncaughtHandler" object.  Use it if non-NULL;
      * else use "group" (which is an instance of UncaughtExceptionHandler).
+     * The ThreadGroup will handle it directly or call the default
+     * uncaught exception handler.
      */
-    threadHandler = dvmFindInstanceField(gDvm.classJavaLangThread,
-            "uncaughtHandler", "Ljava/lang/Thread$UncaughtExceptionHandler;");
-    if (threadHandler == NULL) {
-        LOGW("WARNING: no 'uncaughtHandler' field in java/lang/Thread\n");
-        goto bail;
-    }
-    handlerObj = dvmGetFieldObject(self->threadObj, threadHandler->byteOffset);
+    handlerObj = dvmGetFieldObject(self->threadObj,
+            gDvm.offJavaLangThread_uncaughtHandler);
     if (handlerObj == NULL)
         handlerObj = group;
 
     /*
-     * Find the "uncaughtHandler" field in this object.
+     * Find the "uncaughtException" method in this object.  The method
+     * was declared in the Thread.UncaughtExceptionHandler interface.
      */
     uncaughtHandler = dvmFindVirtualMethodHierByDescriptor(handlerObj->clazz,
             "uncaughtException", "(Ljava/lang/Thread;Ljava/lang/Throwable;)V");
@@ -1661,19 +1662,22 @@
         dvmCallMethod(self, uncaughtHandler, handlerObj, &unused,
             self->threadObj, exception);
     } else {
-        /* restore it and dump a stack trace */
+        /* should be impossible, but handle it anyway */
         LOGW("WARNING: no 'uncaughtException' method in class %s\n",
             handlerObj->clazz->descriptor);
         dvmSetException(self, exception);
         dvmLogExceptionStackTrace();
     }
 
-bail:
+    /* if the uncaught handler threw, clear it */
+    dvmClearException(self);
+
+    dvmReleaseTrackedAlloc(exception, self);
+
     /* Remove this thread's suspendCount from global suspendCount sum */
     lockThreadSuspendCount();
     dvmAddToSuspendCounts(self, -self->interpBreak.ctl.suspendCount, 0);
     unlockThreadSuspendCount();
-    dvmReleaseTrackedAlloc(exception, self);
 }
 
 
diff --git a/vm/native/dalvik_system_VMDebug.c b/vm/native/dalvik_system_VMDebug.c
index d511a8f..146f562 100644
--- a/vm/native/dalvik_system_VMDebug.c
+++ b/vm/native/dalvik_system_VMDebug.c
@@ -38,13 +38,7 @@
     assert(obj != NULL);
     assert(strcmp(obj->clazz->descriptor, "Ljava/io/FileDescriptor;") == 0);
 
-    InstField* field = dvmFindInstanceField(obj->clazz, "descriptor", "I");
-    if (field == NULL) {
-        dvmThrowNoSuchFieldException("No FileDescriptor.descriptor field");
-        return -1;
-    }
-
-    int fd = dvmGetFieldInt(obj, field->byteOffset);
+    int fd = dvmGetFieldInt(obj, gDvm.offJavaIoFileDescriptor_descriptor);
     if (fd < 0) {
         dvmThrowRuntimeException("Invalid file descriptor");
         return -1;