Changed the way errors are propagated through the verifier.

Changed the boolean "okay" to a "failure" enumeration.  Most failures are
"generic", but some are called out specially.  Added a more detailed
failure result from resolver functions.

In theory, no behavior has changed.
diff --git a/vm/analysis/CodeVerify.c b/vm/analysis/CodeVerify.c
index ed132e2..97d98d7 100644
--- a/vm/analysis/CodeVerify.c
+++ b/vm/analysis/CodeVerify.c
@@ -116,9 +116,10 @@
 static void checkMergeTab(void);
 static bool isInitMethod(const Method* meth);
 static RegType getInvocationThis(const RegType* insnRegs,\
-    const int insnRegCount, const DecodedInstruction* pDecInsn, bool* pOkay);
+    const int insnRegCount, const DecodedInstruction* pDecInsn,
+    VerifyError* pFailure);
 static void verifyRegisterType(const RegType* insnRegs, const int insnRegCount,\
-    u4 vsrc, RegType checkType, bool* pOkay);
+    u4 vsrc, RegType checkType, VerifyError* pFailure);
 static bool doCodeVerification(const Method* meth, InsnFlags* insnFlags,\
     RegisterTable* regTable, UninitInstanceMap* uninitMap);
 static bool verifyInstruction(const Method* meth, InsnFlags* insnFlags,\
@@ -545,9 +546,11 @@
 
 /*
  * Look up a class reference given as a simple string descriptor.
+ *
+ * If we can't find it, return a generic substitute when possible.
  */
 static ClassObject* lookupClassByDescriptor(const Method* meth,
-    const char* pDescriptor, bool* pOkay)
+    const char* pDescriptor, VerifyError* pFailure)
 {
     /*
      * The javac compiler occasionally puts references to nonexistent
@@ -585,7 +588,7 @@
             if (pDescriptor[1] != 'L' && pDescriptor[1] != '[') {
                 LOG_VFY("VFY: invalid char in signature in '%s'\n",
                     pDescriptor);
-                *pOkay = false;
+                *pFailure = VERIFY_ERROR_GENERIC;
             }
 
             /*
@@ -607,17 +610,17 @@
         } else {
             /* We are looking at a primitive type. */
             LOG_VFY("VFY: invalid char in signature in '%s'\n", pDescriptor);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         }
 
         if (clazz == NULL) {
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         }
     }
 
     if (dvmIsPrimitiveClass(clazz)) {
         LOG_VFY("VFY: invalid use of primitive type '%s'\n", pDescriptor);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         clazz = NULL;
     }
 
@@ -634,7 +637,7 @@
  * NOTE: this is also expected to verify the signature.
  */
 static ClassObject* lookupSignatureClass(const Method* meth, const char** pSig,
-    bool* pOkay)
+    VerifyError* pFailure)
 {
     const char* sig = *pSig;
     const char* endp = sig;
@@ -645,7 +648,7 @@
         ;
     if (*endp != ';') {
         LOG_VFY("VFY: bad signature component '%s' (missing ';')\n", sig);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         return NULL;
     }
 
@@ -657,7 +660,7 @@
 
     *pSig = endp - 1; /* - 1 so that *pSig points at, not past, the ';' */
 
-    return lookupClassByDescriptor(meth, typeStr, pOkay);
+    return lookupClassByDescriptor(meth, typeStr, pFailure);
 }
 
 /*
@@ -669,7 +672,7 @@
  * NOTE: this is also expected to verify the signature.
  */
 static ClassObject* lookupSignatureArrayClass(const Method* meth,
-    const char** pSig, bool* pOkay)
+    const char** pSig, VerifyError* pFailure)
 {
     const char* sig = *pSig;
     const char* endp = sig;
@@ -685,7 +688,7 @@
             ;
         if (*endp != ';') {
             LOG_VFY("VFY: bad signature component '%s' (missing ';')\n", sig);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
             return NULL;
         }
     }
@@ -697,7 +700,7 @@
 
     *pSig = endp;
 
-    return lookupClassByDescriptor(meth, typeStr, pOkay);
+    return lookupClassByDescriptor(meth, typeStr, pFailure);
 }
 
 /*
@@ -713,7 +716,7 @@
 {
     DexParameterIterator iterator;
     int actualArgs, expectedArgs, argStart;
-    bool okay = true;
+    VerifyError failure = VERIFY_ERROR_NONE;
 
     dexParameterIteratorInit(&iterator, &meth->prototype);
     argStart = meth->registersSize - meth->insSize;
@@ -768,8 +771,8 @@
              */
             {
                 ClassObject* clazz =
-                    lookupClassByDescriptor(meth, descriptor, &okay);
-                if (!okay)
+                    lookupClassByDescriptor(meth, descriptor, &failure);
+                if (!VERIFY_OK(failure))
                     goto bad_sig;
                 regTypes[argStart + actualArgs] = regTypeFromClass(clazz);
             }
@@ -926,10 +929,10 @@
     case 'L':
     case '[':
         {
-            bool okay = true;
+            VerifyError failure = VERIFY_ERROR_NONE;
             ClassObject* clazz =
-                lookupClassByDescriptor(meth, descriptor, &okay);
-            assert(okay);
+                lookupClassByDescriptor(meth, descriptor, &failure);
+            assert(VERIFY_OK(failure));
             type = regTypeFromClass(clazz);
         }
         break;
@@ -1012,13 +1015,13 @@
  * Widening conversions on integers and references are allowed, but
  * narrowing conversions are not.
  *
- * Returns the resolved method on success, NULL (and sets "*pOkay" to "false")
- * on failure.
+ * Returns the resolved method on success, NULL on failure (with *pFailure
+ * set appropriately).
  */
 static Method* verifyInvocationArgs(const Method* meth, const RegType* insnRegs,
     const int insnRegCount, const DecodedInstruction* pDecInsn,
     UninitInstanceMap* uninitMap, MethodType methodType, bool isRange,
-    bool isSuper, bool* pOkay)
+    bool isSuper, VerifyError* pFailure)
 {
     Method* resMethod;
     char* sigOriginal = NULL;
@@ -1030,7 +1033,8 @@
     if (methodType == METHOD_INTERFACE) {
         resMethod = dvmOptResolveInterfaceMethod(meth->clazz, pDecInsn->vB);
     } else {
-        resMethod = dvmOptResolveMethod(meth->clazz, pDecInsn->vB, methodType);
+        resMethod = dvmOptResolveMethod(meth->clazz, pDecInsn->vB, methodType,
+            pFailure);
     }
     if (resMethod == NULL) {
         /* failed; print a meaningful failure message */
@@ -1065,6 +1069,7 @@
             dvmMethodTypeStr(methodType), pDecInsn->vB,
             classDescriptor, methodName, methodDesc);
         free(methodDesc);
+        *pFailure = VERIFY_ERROR_NO_METHOD;
         goto fail;
     }
 
@@ -1095,6 +1100,7 @@
                     (super == NULL) ? "-" : super->descriptor,
                     resMethod->name, desc);
             free(desc);
+            *pFailure = VERIFY_ERROR_NO_METHOD;
             goto fail;
         }
     }
@@ -1135,8 +1141,8 @@
         RegType actualArgType;
 
         actualArgType = getInvocationThis(insnRegs, insnRegCount, pDecInsn,
-                            pOkay);
-        if (!*pOkay)
+                            pFailure);
+        if (!VERIFY_OK(*pFailure))
             goto fail;
 
         if (regTypeIsUninitReference(actualArgType) && resMethod->name[0] != '<')
@@ -1176,12 +1182,12 @@
         switch (*sig) {
         case 'L':
             {
-                ClassObject* clazz = lookupSignatureClass(meth, &sig, pOkay);
-                if (!*pOkay)
+                ClassObject* clazz = lookupSignatureClass(meth, &sig, pFailure);
+                if (!VERIFY_OK(*pFailure))
                     goto bad_sig;
                 verifyRegisterType(insnRegs, insnRegCount, getReg,
-                    regTypeFromClass(clazz), pOkay);
-                if (!*pOkay) {
+                    regTypeFromClass(clazz), pFailure);
+                if (!VERIFY_OK(*pFailure)) {
                     LOG_VFY("VFY: bad arg %d (into %s)\n",
                             actualArgs, clazz->descriptor);
                     goto bad_sig;
@@ -1192,12 +1198,12 @@
         case '[':
             {
                 ClassObject* clazz =
-                    lookupSignatureArrayClass(meth, &sig, pOkay);
-                if (!*pOkay)
+                    lookupSignatureArrayClass(meth, &sig, pFailure);
+                if (!VERIFY_OK(*pFailure))
                     goto bad_sig;
                 verifyRegisterType(insnRegs, insnRegCount, getReg,
-                    regTypeFromClass(clazz), pOkay);
-                if (!*pOkay) {
+                    regTypeFromClass(clazz), pFailure);
+                if (!VERIFY_OK(*pFailure)) {
                     LOG_VFY("VFY: bad arg %d (into %s)\n",
                             actualArgs, clazz->descriptor);
                     goto bad_sig;
@@ -1207,42 +1213,42 @@
             break;
         case 'Z':
             verifyRegisterType(insnRegs, insnRegCount, getReg,
-                kRegTypeBoolean, pOkay);
+                kRegTypeBoolean, pFailure);
             actualArgs++;
             break;
         case 'C':
             verifyRegisterType(insnRegs, insnRegCount, getReg,
-                kRegTypeChar, pOkay);
+                kRegTypeChar, pFailure);
             actualArgs++;
             break;
         case 'B':
             verifyRegisterType(insnRegs, insnRegCount, getReg,
-                kRegTypeByte, pOkay);
+                kRegTypeByte, pFailure);
             actualArgs++;
             break;
         case 'I':
             verifyRegisterType(insnRegs, insnRegCount, getReg,
-                kRegTypeInteger, pOkay);
+                kRegTypeInteger, pFailure);
             actualArgs++;
             break;
         case 'S':
             verifyRegisterType(insnRegs, insnRegCount, getReg,
-                kRegTypeShort, pOkay);
+                kRegTypeShort, pFailure);
             actualArgs++;
             break;
         case 'F':
             verifyRegisterType(insnRegs, insnRegCount, getReg,
-                kRegTypeFloat, pOkay);
+                kRegTypeFloat, pFailure);
             actualArgs++;
             break;
         case 'D':
             verifyRegisterType(insnRegs, insnRegCount, getReg,
-                kRegTypeDoubleLo, pOkay);
+                kRegTypeDoubleLo, pFailure);
             actualArgs += 2;
             break;
         case 'J':
             verifyRegisterType(insnRegs, insnRegCount, getReg,
-                kRegTypeLongLo, pOkay);
+                kRegTypeLongLo, pFailure);
             actualArgs += 2;
             break;
         default:
@@ -1272,13 +1278,14 @@
     if (resMethod != NULL) {
         char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype);
         LOG_VFY("VFY:  rejecting call to %s.%s %s\n",
-                resMethod->clazz->descriptor, resMethod->name, desc);
+            resMethod->clazz->descriptor, resMethod->name, desc);
         free(desc);
     }
 
 fail:
     free(sigOriginal);
-    *pOkay = false;
+    if (*pFailure == VERIFY_ERROR_NONE)
+        *pFailure = VERIFY_ERROR_GENERIC;
     return NULL;
 }
 
@@ -1324,15 +1331,15 @@
 /*
  * Get the type of register N, verifying that the register is valid.
  *
- * Sets "*pOkay" to false if the register number is out of range.
+ * Sets "*pFailure" appropriately if the register number is out of range.
  */
 static inline RegType getRegisterType(const RegType* insnRegs,
-    const int insnRegCount, u4 vsrc, bool* pOkay)
+    const int insnRegCount, u4 vsrc, VerifyError* pFailure)
 {
     RegType type;
 
     if (vsrc >= (u4) insnRegCount) {
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         return kRegTypeUnknown;
     } else {
         return insnRegs[vsrc];
@@ -1341,21 +1348,21 @@
 
 /*
  * Get the value from a register, and cast it to a ClassObject.  Sets
- * "pOkay" to false if something fails.
+ * "*pFailure" if something fails.
  *
  * This fails if the register holds an uninitialized class.
  *
  * If the register holds kRegTypeZero, this returns a NULL pointer.
  */
 static ClassObject* getClassFromRegister(const RegType* insnRegs,
-    const int insnRegCount, u4 vsrc, bool* pOkay)
+    const int insnRegCount, u4 vsrc, VerifyError* pFailure)
 {
     ClassObject* clazz = NULL;
     RegType type;
 
     /* get the element type of the array held in vsrc */
-    type = getRegisterType(insnRegs, insnRegCount, vsrc, pOkay);
-    if (!*pOkay)
+    type = getRegisterType(insnRegs, insnRegCount, vsrc, pFailure);
+    if (!VERIFY_OK(*pFailure))
         goto bail;
 
     /* if "always zero", we allow it to fail at runtime */
@@ -1365,12 +1372,12 @@
     if (!regTypeIsReference(type)) {
         LOG_VFY("VFY: tried to get class from non-ref register v%d (type=%d)\n",
             vsrc, type);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         goto bail;
     }
     if (regTypeIsUninitReference(type)) {
         LOG_VFY("VFY: register %u holds uninitialized reference\n", vsrc);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         goto bail;
     }
 
@@ -1391,27 +1398,28 @@
  * and then return vC.
  */
 static RegType getInvocationThis(const RegType* insnRegs,
-    const int insnRegCount, const DecodedInstruction* pDecInsn, bool* pOkay)
+    const int insnRegCount, const DecodedInstruction* pDecInsn,
+    VerifyError* pFailure)
 {
     RegType thisType = kRegTypeUnknown;
 
     if (pDecInsn->vA < 1) {
         LOG_VFY("VFY: invoke lacks 'this'\n");
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         goto bail;
     }
 
     /* get the element type of the array held in vsrc */
-    thisType = getRegisterType(insnRegs, insnRegCount, pDecInsn->vC, pOkay);
-    if (!*pOkay) {
-        LOG_VFY("VFY: failed to get this from register %u\n", pDecInsn->vC);
+    thisType = getRegisterType(insnRegs, insnRegCount, pDecInsn->vC, pFailure);
+    if (!VERIFY_OK(*pFailure)) {
+        LOG_VFY("VFY: failed to get 'this' from register %u\n", pDecInsn->vC);
         goto bail;
     }
 
     if (!regTypeIsReference(thisType)) {
         LOG_VFY("VFY: tried to get class from non-ref register v%d (type=%d)\n",
             pDecInsn->vC, thisType);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         goto bail;
     }
 
@@ -1424,10 +1432,10 @@
  * "newType" is the "Lo" part of a 64-bit value, register N+1 will be
  * set to "newType+1".
  *
- * Sets "*pOkay" to false if the register number is out of range.
+ * Sets "*pFailure" if the register number is out of range.
  */
 static void setRegisterType(RegType* insnRegs, const int insnRegCount,
-    u4 vdst, RegType newType, bool* pOkay)
+    u4 vdst, RegType newType, VerifyError* pFailure)
 {
     //LOGD("set-reg v%u = %d\n", vdst, newType);
     switch (newType) {
@@ -1443,7 +1451,7 @@
     case kRegTypeFloat:
     case kRegTypeZero:
         if (vdst >= (u4) insnRegCount) {
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         } else {
             insnRegs[vdst] = newType;
         }
@@ -1451,7 +1459,7 @@
     case kRegTypeLongLo:
     case kRegTypeDoubleLo:
         if (vdst+1 >= (u4) insnRegCount) {
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         } else {
             insnRegs[vdst] = newType;
             insnRegs[vdst+1] = newType+1;
@@ -1460,14 +1468,14 @@
     case kRegTypeLongHi:
     case kRegTypeDoubleHi:
         /* should never set these explicitly */
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         break;
 
     case kRegTypeUninit:
     default:
         if (regTypeIsReference(newType)) {
             if (vdst >= (u4) insnRegCount) {
-                *pOkay = false;
+                *pFailure = VERIFY_ERROR_GENERIC;
                 break;
             }
             insnRegs[vdst] = newType;
@@ -1490,7 +1498,7 @@
     case kRegTypeConflict:      // should only be set during a merge
         LOG_VFY("Unexpected set type %d\n", newType);
         assert(false);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         break;
     }
 }
@@ -1509,10 +1517,10 @@
  * interface, verify that the register implements checkType.
  */
 static void verifyRegisterType(const RegType* insnRegs, const int insnRegCount,
-    u4 vsrc, RegType checkType, bool* pOkay)
+    u4 vsrc, RegType checkType, VerifyError* pFailure)
 {
     if (vsrc >= (u4) insnRegCount) {
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         return;
     }
 
@@ -1531,7 +1539,7 @@
         if (!canConvertTo1nr(srcType, checkType)) {
             LOG_VFY("VFY: register1 v%u type %d, wanted %d\n",
                 vsrc, srcType, checkType);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         }
         break;
     case kRegTypeLongLo:
@@ -1539,15 +1547,15 @@
         if (vsrc+1 >= (u4) insnRegCount) {
             LOG_VFY("VFY: register2 v%u out of range (%d)\n",
                 vsrc, insnRegCount);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         } else if (insnRegs[vsrc+1] != srcType+1) {
             LOG_VFY("VFY: register2 v%u-%u values %d,%d\n",
                 vsrc, vsrc+1, insnRegs[vsrc], insnRegs[vsrc+1]);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         } else if (!canConvertTo2(srcType, checkType)) {
             LOG_VFY("VFY: register2 v%u type %d, wanted %d\n",
                 vsrc, srcType, checkType);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         }
         break;
 
@@ -1559,7 +1567,7 @@
     case kRegTypeConflict:
         /* should never be checking for these explicitly */
         assert(false);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         return;
     case kRegTypeUninit:
     default:
@@ -1567,23 +1575,23 @@
         if (!regTypeIsReference(checkType)) {
             LOG_VFY("VFY: unexpected check type %d\n", checkType);
             assert(false);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
             break;
         }
         if (regTypeIsUninitReference(checkType)) {
             LOG_VFY("VFY: uninitialized ref not expected as reg check\n");
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
             break;
         }
         /* make sure srcType is initialized reference or always-NULL */
         if (!regTypeIsReference(srcType)) {
             LOG_VFY("VFY: register1 v%u type %d, wanted ref\n", vsrc, srcType);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
             break;
         }
         if (regTypeIsUninitReference(srcType)) {
             LOG_VFY("VFY: register1 v%u holds uninitialized ref\n", vsrc);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
             break;
         }
         /* if the register isn't Zero, make sure it's an instance of check */
@@ -1605,14 +1613,14 @@
                 {
                     LOG_VFY("VFY: %s does not implement %s\n",
                             srcClass->descriptor, checkClass->descriptor);
-                    *pOkay = false;
+                    *pFailure = VERIFY_ERROR_GENERIC;
                 }
                 */
             } else {
                 if (!dvmInstanceof(srcClass, checkClass)) {
                     LOG_VFY("VFY: %s is not instance of %s\n",
                             srcClass->descriptor, checkClass->descriptor);
-                    *pOkay = false;
+                    *pFailure = VERIFY_ERROR_GENERIC;
                 }
             }
         }
@@ -1625,10 +1633,10 @@
  * "insnRegCount" to encompass the result register.
  */
 static void setResultRegisterType(RegType* insnRegs, const int insnRegCount,
-    RegType newType, bool* pOkay)
+    RegType newType, VerifyError* pFailure)
 {
     setRegisterType(insnRegs, insnRegCount + kExtraRegs,
-        RESULT_REGISTER(insnRegCount), newType, pOkay);
+        RESULT_REGISTER(insnRegCount), newType, pFailure);
 }
 
 
@@ -1639,7 +1647,7 @@
  * must be marked as initialized.
  */
 static void markRefsAsInitialized(RegType* insnRegs, int insnRegCount,
-    UninitInstanceMap* uninitMap, RegType uninitType, bool* pOkay)
+    UninitInstanceMap* uninitMap, RegType uninitType, VerifyError* pFailure)
 {
     ClassObject* clazz;
     RegType initType;
@@ -1649,7 +1657,7 @@
     if (clazz == NULL) {
         LOGE("VFY: unable to find type=0x%x (idx=%d)\n",
             uninitType, regTypeToUninitIndex(uninitType));
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         return;
     }
     initType = regTypeFromClass(clazz);
@@ -1748,9 +1756,10 @@
  *
  * For category 2 values, "type" must be the "low" half of the value.
  *
- * Sets "*pOkay" to false if not.
+ * Sets "*pFailure" if something looks wrong.
  */
-static void checkTypeCategory(RegType type, TypeCategory cat, bool* pOkay)
+static void checkTypeCategory(RegType type, TypeCategory cat,
+    VerifyError* pFailure)
 {
     switch (cat) {
     case kTypeCategory1nr:
@@ -1767,7 +1776,7 @@
         case kRegTypeInteger:
             break;
         default:
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
             break;
         }
         break;
@@ -1778,19 +1787,19 @@
         case kRegTypeDoubleLo:
             break;
         default:
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
             break;
         }
         break;
 
     case kTypeCategoryRef:
         if (type != kRegTypeZero && !regTypeIsReference(type))
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         break;
 
     default:
         assert(false);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         break;
     }
 }
@@ -1802,10 +1811,10 @@
  * Does not verify that "typel" is in fact the low part of a 64-bit
  * register pair.
  */
-static void checkWidePair(RegType typel, RegType typeh, bool* pOkay)
+static void checkWidePair(RegType typel, RegType typeh, VerifyError* pFailure)
 {
     if ((typeh != typel+1))
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
 }
 
 /*
@@ -1816,15 +1825,15 @@
  * "vsrc" values are checked against this.
  */
 static void copyRegister1(RegType* insnRegs, int insnRegCount, u4 vdst,
-    u4 vsrc, TypeCategory cat, bool* pOkay)
+    u4 vsrc, TypeCategory cat, VerifyError* pFailure)
 {
-    RegType type = getRegisterType(insnRegs, insnRegCount, vsrc, pOkay);
-    if (*pOkay)
-        checkTypeCategory(type, cat, pOkay);
-    if (*pOkay)
-        setRegisterType(insnRegs, insnRegCount, vdst, type, pOkay);
+    RegType type = getRegisterType(insnRegs, insnRegCount, vsrc, pFailure);
+    if (VERIFY_OK(*pFailure))
+        checkTypeCategory(type, cat, pFailure);
+    if (VERIFY_OK(*pFailure))
+        setRegisterType(insnRegs, insnRegCount, vdst, type, pFailure);
 
-    if (!*pOkay) {
+    if (!VERIFY_OK(*pFailure)) {
         LOG_VFY("VFY: copy1 v%u<-v%u type=%d cat=%d\n", vdst, vsrc, type, cat);
     }
 }
@@ -1834,18 +1843,18 @@
  * "vsrc" to "vdst".  This copies both halves of the register.
  */
 static void copyRegister2(RegType* insnRegs, int insnRegCount, u4 vdst,
-    u4 vsrc, bool* pOkay)
+    u4 vsrc, VerifyError* pFailure)
 {
-    RegType typel = getRegisterType(insnRegs, insnRegCount, vsrc, pOkay);
-    RegType typeh = getRegisterType(insnRegs, insnRegCount, vsrc+1, pOkay);
-    if (*pOkay) {
-        checkTypeCategory(typel, kTypeCategory2, pOkay);
-        checkWidePair(typel, typeh, pOkay);
+    RegType typel = getRegisterType(insnRegs, insnRegCount, vsrc, pFailure);
+    RegType typeh = getRegisterType(insnRegs, insnRegCount, vsrc+1, pFailure);
+    if (VERIFY_OK(*pFailure)) {
+        checkTypeCategory(typel, kTypeCategory2, pFailure);
+        checkWidePair(typel, typeh, pFailure);
     }
-    if (*pOkay)
-        setRegisterType(insnRegs, insnRegCount, vdst, typel, pOkay);
+    if (VERIFY_OK(*pFailure))
+        setRegisterType(insnRegs, insnRegCount, vdst, typel, pFailure);
 
-    if (!*pOkay) {
+    if (!VERIFY_OK(*pFailure)) {
         LOG_VFY("VFY: copy2 v%u<-v%u type=%d/%d\n", vdst, vsrc, typel, typeh);
     }
 }
@@ -1858,21 +1867,21 @@
  * because that would affect the test on "vdst" as well.
  */
 static void copyResultRegister1(RegType* insnRegs, const int insnRegCount,
-    u4 vdst, TypeCategory cat, bool* pOkay)
+    u4 vdst, TypeCategory cat, VerifyError* pFailure)
 {
     RegType type;
     u4 vsrc;
 
     vsrc = RESULT_REGISTER(insnRegCount);
-    type = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc, pOkay);
-    if (*pOkay)
-        checkTypeCategory(type, cat, pOkay);
-    if (*pOkay) {
-        setRegisterType(insnRegs, insnRegCount, vdst, type, pOkay);
+    type = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc, pFailure);
+    if (VERIFY_OK(*pFailure))
+        checkTypeCategory(type, cat, pFailure);
+    if (VERIFY_OK(*pFailure)) {
+        setRegisterType(insnRegs, insnRegCount, vdst, type, pFailure);
         insnRegs[vsrc] = kRegTypeUnknown;
     }
 
-    if (!*pOkay) {
+    if (!VERIFY_OK(*pFailure)) {
         LOG_VFY("VFY: copyRes1 v%u<-v%u cat=%d type=%d\n",
             vdst, vsrc, cat, type);
     }
@@ -1886,25 +1895,27 @@
  * because that would affect the test on "vdst" as well.
  */
 static void copyResultRegister2(RegType* insnRegs, const int insnRegCount,
-    u4 vdst, bool* pOkay)
+    u4 vdst, VerifyError* pFailure)
 {
     RegType typel, typeh;
     u4 vsrc;
 
     vsrc = RESULT_REGISTER(insnRegCount);
-    typel = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc, pOkay);
-    typeh = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc+1, pOkay);
-    if (*pOkay) {
-        checkTypeCategory(typel, kTypeCategory2, pOkay);
-        checkWidePair(typel, typeh, pOkay);
+    typel = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc,
+                pFailure);
+    typeh = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc+1,
+                pFailure);
+    if (VERIFY_OK(*pFailure)) {
+        checkTypeCategory(typel, kTypeCategory2, pFailure);
+        checkWidePair(typel, typeh, pFailure);
     }
-    if (*pOkay) {
-        setRegisterType(insnRegs, insnRegCount, vdst, typel, pOkay);
+    if (VERIFY_OK(*pFailure)) {
+        setRegisterType(insnRegs, insnRegCount, vdst, typel, pFailure);
         insnRegs[vsrc] = kRegTypeUnknown;
         insnRegs[vsrc+1] = kRegTypeUnknown;
     }
 
-    if (!*pOkay) {
+    if (!VERIFY_OK(*pFailure)) {
         LOG_VFY("VFY: copyRes2 v%u<-v%u type=%d/%d\n",
             vdst, vsrc, typel, typeh);
     }
@@ -1916,10 +1927,10 @@
  */
 static void checkUnop(RegType* insnRegs, const int insnRegCount,
     DecodedInstruction* pDecInsn, RegType dstType, RegType srcType,
-    bool* pOkay)
+    VerifyError* pFailure)
 {
-    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pOkay);
-    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pOkay);
+    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pFailure);
+    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
 }
 
 /*
@@ -1958,10 +1969,10 @@
  */
 static void checkLitop(RegType* insnRegs, const int insnRegCount,
     DecodedInstruction* pDecInsn, RegType dstType, RegType srcType,
-    bool checkBooleanOp, bool* pOkay)
+    bool checkBooleanOp, VerifyError* pFailure)
 {
-    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pOkay);
-    if (*pOkay && checkBooleanOp) {
+    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pFailure);
+    if (VERIFY_OK(*pFailure) && checkBooleanOp) {
         assert(dstType == kRegTypeInteger);
         /* check vB with the call, then check the constant manually */
         if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vB, pDecInsn->vB)
@@ -1970,7 +1981,7 @@
             dstType = kRegTypeBoolean;
         }
     }
-    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pOkay);
+    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
 }
 
 /*
@@ -1980,16 +1991,18 @@
  */
 static void checkBinop(RegType* insnRegs, const int insnRegCount,
     DecodedInstruction* pDecInsn, RegType dstType, RegType srcType1,
-    RegType srcType2, bool checkBooleanOp, bool* pOkay)
+    RegType srcType2, bool checkBooleanOp, VerifyError* pFailure)
 {
-    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType1, pOkay);
-    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vC, srcType2, pOkay);
-    if (*pOkay && checkBooleanOp) {
+    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType1,
+        pFailure);
+    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vC, srcType2,
+        pFailure);
+    if (VERIFY_OK(*pFailure) && checkBooleanOp) {
         assert(dstType == kRegTypeInteger);
         if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vB, pDecInsn->vC))
             dstType = kRegTypeBoolean;
     }
-    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pOkay);
+    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
 }
 
 /*
@@ -1998,16 +2011,18 @@
  */
 static void checkBinop2addr(RegType* insnRegs, const int insnRegCount,
     DecodedInstruction* pDecInsn, RegType dstType, RegType srcType1,
-    RegType srcType2, bool checkBooleanOp, bool* pOkay)
+    RegType srcType2, bool checkBooleanOp, VerifyError* pFailure)
 {
-    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vA, srcType1, pOkay);
-    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType2, pOkay);
-    if (*pOkay && checkBooleanOp) {
+    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vA, srcType1,
+        pFailure);
+    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType2,
+        pFailure);
+    if (VERIFY_OK(*pFailure) && checkBooleanOp) {
         assert(dstType == kRegTypeInteger);
         if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vA, pDecInsn->vB))
             dstType = kRegTypeBoolean;
     }
-    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pOkay);
+    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
 }
 
 
@@ -2329,28 +2344,28 @@
  * allow it to be uninitialized if this is an "<init>" method and the field
  * is declared within the "objType" class.
  *
- * Returns an InstField on success, returns NULL and sets "*pOkay" to false
+ * Returns an InstField on success, returns NULL and sets "*pFailure"
  * on failure.
  */
 static InstField* getInstField(const Method* meth,
     const UninitInstanceMap* uninitMap, RegType objType, int fieldIdx,
-    bool* pOkay)
+    VerifyError* pFailure)
 {
     InstField* instField = NULL;
     ClassObject* objClass;
     bool mustBeLocal = false;
 
     if (!regTypeIsReference(objType)) {
-        LOG_VFY("VFY: attempt to access field of non-reference type %d\n",
+        LOG_VFY("VFY: attempt to access field in non-reference type %d\n",
             objType);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         goto bail;
     }
 
-    instField = dvmOptResolveInstField(meth->clazz, fieldIdx);
+    instField = dvmOptResolveInstField(meth->clazz, fieldIdx, pFailure);
     if (instField == NULL) {
         LOG_VFY("VFY: unable to resolve instance field %u\n", fieldIdx);
-        *pOkay = false;
+        assert(!VERIFY_OK(*pFailure));
         goto bail;
     }
 
@@ -2367,7 +2382,7 @@
     if (regTypeIsUninitReference(objType)) {
         if (!isInitMethod(meth) || meth->clazz != objClass) {
             LOG_VFY("VFY: attempt to access field via uninitialized ref\n");
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
             goto bail;
         }
         mustBeLocal = true;
@@ -2377,7 +2392,7 @@
         LOG_VFY("VFY: invalid field access (field %s.%s, through %s ref)\n",
                 instField->field.clazz->descriptor, instField->field.name,
                 objClass->descriptor);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_NO_FIELD;
         goto bail;
     }
 
@@ -2388,7 +2403,7 @@
         {
             LOG_VFY("VFY: invalid constructor field access (field %s in %s)\n",
                     instField->field.name, objClass->descriptor);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
             goto bail;
         }
     }
@@ -2400,15 +2415,15 @@
 /*
  * Look up a static field.
  *
- * Returns a StaticField on success, returns NULL and sets "*pOkay" to false
+ * Returns a StaticField on success, returns NULL and sets "*pFailure"
  * on failure.
  */
 static StaticField* getStaticField(const Method* meth, int fieldIdx,
-    bool* pOkay)
+    VerifyError* pFailure)
 {
     StaticField* staticField;
 
-    staticField = dvmOptResolveStaticField(meth->clazz, fieldIdx);
+    staticField = dvmOptResolveStaticField(meth->clazz, fieldIdx, pFailure);
     if (staticField == NULL) {
         DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
         const DexFieldId* pFieldId;
@@ -2418,8 +2433,7 @@
         LOG_VFY("VFY: unable to resolve static field %u (%s) in %s\n", fieldIdx,
             dexStringById(pDexFile, pFieldId->nameIdx),
             dexStringByTypeIdx(pDexFile, pFieldId->classIdx));
-
-        *pOkay = false;
+        assert(!VERIFY_OK(*pFailure));
         goto bail;
     }
 
@@ -2431,10 +2445,10 @@
  * If "field" is marked "final", make sure this is the either <clinit>
  * or <init> as appropriate.
  *
- * Sets "*pOkay" to false on failure.
+ * Sets "*pFailure" on failure.
  */
 static void checkFinalFieldAccess(const Method* meth, const Field* field,
-    bool* pOkay)
+    VerifyError* pFailure)
 {
     if (!dvmIsFinalField(field))
         return;
@@ -2443,21 +2457,15 @@
     if (meth->clazz != field->clazz) {
         LOG_VFY_METH(meth, "VFY: can't modify final field %s.%s\n",
             field->clazz->descriptor, field->name);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_ACCESS;
         return;
     }
 
     /*
-     * The EMMA code coverage tool generates a static method that
-     * modifies a private static final field.  The method is only
-     * called by <clinit>, so the code is reasonable if not quite
-     * kosher.  (Attempting to *compile* code that does something
-     * like that will earn you a quick thumbs-down from javac.)
-     *
-     * The verifier in another popular VM doesn't complain about this,
-     * so we're going to allow classes to modify their own static
-     * final fields outside of class initializers.  Further testing
-     * showed that modifications to instance fields are also allowed.
+     * The VM spec descriptions of putfield and putstatic say that
+     * IllegalAccessError is only thrown when the instructions appear
+     * outside the declaring class.  Our earlier attempts to restrict
+     * final field modification to constructors are, therefore, wrong.
      */
 #if 0
     /* make sure we're in the right kind of constructor */
@@ -2465,13 +2473,13 @@
         if (!isClassInitMethod(meth)) {
             LOG_VFY_METH(meth,
                 "VFY: can't modify final static field outside <clinit>\n");
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         }
     } else {
         if (!isInitMethod(meth)) {
             LOG_VFY_METH(meth,
                 "VFY: can't modify final field outside <init>\n");
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         }
     }
 #endif
@@ -2480,19 +2488,19 @@
 /*
  * Make sure that the register type is suitable for use as an array index.
  *
- * Sets "*pOkay" to false if not.
+ * Sets "*pFailure" if not.
  */
 static void checkArrayIndexType(const Method* meth, RegType regType,
-    bool* pOkay)
+    VerifyError* pFailure)
 {
-    if (*pOkay) {
+    if (VERIFY_OK(*pFailure)) {
         /*
          * The 1nr types are interchangeable at this level.  We could
          * do something special if we can definitively identify it as a
          * float, but there's no real value in doing so.
          */
-        checkTypeCategory(regType, kTypeCategory1nr, pOkay);
-        if (!*pOkay) {
+        checkTypeCategory(regType, kTypeCategory1nr, pFailure);
+        if (!VERIFY_OK(*pFailure)) {
             LOG_VFY_METH(meth, "Invalid reg type for array index (%d)\n",
                 regType);
         }
@@ -2560,11 +2568,14 @@
  * Returns NULL if no matching exception handler can be found, or if the
  * exception is not a subclass of Throwable.
  */
-static ClassObject* getCaughtExceptionType(const Method* meth, int insnIdx)
+static ClassObject* getCaughtExceptionType(const Method* meth, int insnIdx,
+    VerifyError* pFailure)
 {
+    VerifyError localFailure;
     const DexCode* pCode;
     DexFile* pDexFile;
     ClassObject* commonSuper = NULL;
+    bool foundPossibleHandler = false;
     u4 handlersSize;
     u4 offset;
     u4 i;
@@ -2593,16 +2604,22 @@
 
             if (handler->address == (u4) insnIdx) {
                 ClassObject* clazz;
+                foundPossibleHandler = true;
 
                 if (handler->typeIdx == kDexNoIndex)
                     clazz = gDvm.classJavaLangThrowable;
                 else
-                    clazz = dvmOptResolveClass(meth->clazz, handler->typeIdx);
+                    clazz = dvmOptResolveClass(meth->clazz, handler->typeIdx,
+                                &localFailure);
 
                 if (clazz == NULL) {
                     LOG_VFY("VFY: unable to resolve exception class %u (%s)\n",
                         handler->typeIdx,
                         dexStringByTypeIdx(pDexFile, handler->typeIdx));
+                    /* TODO: do we want to keep going?  If we don't fail
+                     * this we run the risk of having a non-Throwable
+                     * introduced at runtime.  However, that won't pass
+                     * an instanceof test, so is essentially harmless. */
                 } else {
                     if (commonSuper == NULL)
                         commonSuper = clazz;
@@ -2616,8 +2633,12 @@
     }
 
     if (commonSuper == NULL) {
+        /* no catch blocks, or no catches with classes we can find */
         LOG_VFY_METH(meth,
             "VFY: unable to find exception handler at addr 0x%x\n", insnIdx);
+        *pFailure = VERIFY_ERROR_GENERIC;
+    } else {
+        // TODO: verify the class is an instance of Throwable?
     }
 
     return commonSuper;
@@ -2732,7 +2753,7 @@
 static void verifyFilledNewArrayRegs(const Method* meth,
     const RegType* insnRegs, const int insnRegCount,
     const DecodedInstruction* pDecInsn, ClassObject* resClass, bool isRange,
-    bool* pOkay)
+    VerifyError* pFailure)
 {
     u4 argCount = pDecInsn->vA;
     RegType expectedType;
@@ -2761,8 +2782,9 @@
         else
             getReg = pDecInsn->arg[ui];
 
-        verifyRegisterType(insnRegs, insnRegCount, getReg, expectedType, pOkay);
-        if (!*pOkay) {
+        verifyRegisterType(insnRegs, insnRegCount, getReg, expectedType,
+            pFailure);
+        if (!VERIFY_OK(*pFailure)) {
             LOG_VFY("VFY: filled-new-array arg %u(%u) not valid\n", ui, getReg);
             return;
         }
@@ -3194,7 +3216,7 @@
     RegType tmpType;
     DecodedInstruction decInsn;
     bool justSetResult = false;
-    bool okay = true;
+    VerifyError failure = VERIFY_ERROR_NONE;
 
 #ifndef NDEBUG
     memset(&decInsn, 0x81, sizeof(decInsn));
@@ -3229,7 +3251,7 @@
          */
         if (decInsn.vA != 0) {
             LOG_VFY("VFY: encountered data table in instruction stream\n");
-            okay = false;
+            failure = VERIFY_ERROR_GENERIC;
         }
         break;
 
@@ -3237,18 +3259,18 @@
     case OP_MOVE_FROM16:
     case OP_MOVE_16:
         copyRegister1(workRegs, insnRegCount, decInsn.vA, decInsn.vB,
-            kTypeCategory1nr, &okay);
+            kTypeCategory1nr, &failure);
         break;
     case OP_MOVE_WIDE:
     case OP_MOVE_WIDE_FROM16:
     case OP_MOVE_WIDE_16:
-        copyRegister2(workRegs, insnRegCount, decInsn.vA, decInsn.vB, &okay);
+        copyRegister2(workRegs, insnRegCount, decInsn.vA, decInsn.vB, &failure);
         break;
     case OP_MOVE_OBJECT:
     case OP_MOVE_OBJECT_FROM16:
     case OP_MOVE_OBJECT_16:
         copyRegister1(workRegs, insnRegCount, decInsn.vA, decInsn.vB,
-            kTypeCategoryRef, &okay);
+            kTypeCategoryRef, &failure);
         break;
 
     /*
@@ -3264,14 +3286,14 @@
      */
     case OP_MOVE_RESULT:
         copyResultRegister1(workRegs, insnRegCount, decInsn.vA,
-            kTypeCategory1nr, &okay);
+            kTypeCategory1nr, &failure);
         break;
     case OP_MOVE_RESULT_WIDE:
-        copyResultRegister2(workRegs, insnRegCount, decInsn.vA, &okay);
+        copyResultRegister2(workRegs, insnRegCount, decInsn.vA, &failure);
         break;
     case OP_MOVE_RESULT_OBJECT:
         copyResultRegister1(workRegs, insnRegCount, decInsn.vA,
-            kTypeCategoryRef, &okay);
+            kTypeCategoryRef, &failure);
         break;
 
     case OP_MOVE_EXCEPTION:
@@ -3284,71 +3306,75 @@
          * "resClass" will hold the closest common superclass of all
          * exceptions that can be handled here.
          */
-        resClass = getCaughtExceptionType(meth, insnIdx);
+        resClass = getCaughtExceptionType(meth, insnIdx, &failure);
         if (resClass == NULL) {
-            okay = false;
+            assert(!VERIFY_OK(failure));
         } else {
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                regTypeFromClass(resClass), &okay);
+                regTypeFromClass(resClass), &failure);
         }
         break;
 
     case OP_RETURN_VOID:
-        okay = checkConstructorReturn(meth, workRegs, insnRegCount);
-        if (okay && getMethodReturnType(meth) != kRegTypeUnknown) {
+        if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
+            failure = VERIFY_ERROR_GENERIC;
+        } else if (getMethodReturnType(meth) != kRegTypeUnknown) {
             LOG_VFY("VFY: return-void not expected\n");
-            okay = false;
+            failure = VERIFY_ERROR_GENERIC;
         }
         break;
     case OP_RETURN:
-        okay = checkConstructorReturn(meth, workRegs, insnRegCount);
-        if (okay) {
+        if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
+            failure = VERIFY_ERROR_GENERIC;
+        } else {
             /* check the method signature */
             RegType returnType = getMethodReturnType(meth);
-            checkTypeCategory(returnType, kTypeCategory1nr, &okay);
-            if (!okay)
+            checkTypeCategory(returnType, kTypeCategory1nr, &failure);
+            if (!VERIFY_OK(failure))
                 LOG_VFY("VFY: return-32 not expected\n");
 
             /* check the register contents */
             returnType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
-                &okay);
-            checkTypeCategory(returnType, kTypeCategory1nr, &okay);
-            if (!okay)
+                &failure);
+            checkTypeCategory(returnType, kTypeCategory1nr, &failure);
+            if (!VERIFY_OK(failure))
                 LOG_VFY("VFY: return-32 on invalid register v%d\n", decInsn.vA);
         }
         break;
     case OP_RETURN_WIDE:
-        okay = checkConstructorReturn(meth, workRegs, insnRegCount);
-        if (okay) {
+        if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
+            failure = VERIFY_ERROR_GENERIC;
+        } else {
             RegType returnType, returnTypeHi;
 
             /* check the method signature */
             returnType = getMethodReturnType(meth);
-            checkTypeCategory(returnType, kTypeCategory2, &okay);
-            if (!okay)
+            checkTypeCategory(returnType, kTypeCategory2, &failure);
+            if (!VERIFY_OK(failure))
                 LOG_VFY("VFY: return-wide not expected\n");
 
             /* check the register contents */
             returnType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
-                &okay);
+                &failure);
             returnTypeHi = getRegisterType(workRegs, insnRegCount,
-                decInsn.vA +1, &okay);
-            if (okay) {
-                checkTypeCategory(returnType, kTypeCategory2, &okay);
-                checkWidePair(returnType, returnTypeHi, &okay);
+                decInsn.vA +1, &failure);
+            if (VERIFY_OK(failure)) {
+                checkTypeCategory(returnType, kTypeCategory2, &failure);
+                checkWidePair(returnType, returnTypeHi, &failure);
             }
-            if (!okay) {
+            if (!VERIFY_OK(failure)) {
                 LOG_VFY("VFY: return-wide on invalid register pair v%d\n",
                     decInsn.vA);
             }
         }
         break;
     case OP_RETURN_OBJECT:
-        okay = checkConstructorReturn(meth, workRegs, insnRegCount);
-        if (okay) {
+        if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
+            failure = VERIFY_ERROR_GENERIC;
+        } else {
             RegType returnType = getMethodReturnType(meth);
-            checkTypeCategory(returnType, kTypeCategoryRef, &okay);
-            if (!okay) {
+            checkTypeCategory(returnType, kTypeCategoryRef, &failure);
+            if (!VERIFY_OK(failure)) {
                 LOG_VFY("VFY: return-object not expected\n");
                 break;
             }
@@ -3371,8 +3397,8 @@
 
             declClass = regTypeInitializedReferenceToClass(returnType);
             resClass = getClassFromRegister(workRegs, insnRegCount,
-                            decInsn.vA, &okay);
-            if (!okay)
+                            decInsn.vA, &failure);
+            if (!VERIFY_OK(failure))
                 break;
             if (resClass != NULL) {
                 if (!dvmIsInterfaceClass(declClass) &&
@@ -3380,7 +3406,7 @@
                 {
                     LOG_VFY("VFY: returning %s, declared %s\n",
                             resClass->descriptor, declClass->descriptor);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
             }
@@ -3392,12 +3418,12 @@
     case OP_CONST:
         /* could be boolean, int, float, or a null reference */
         setRegisterType(workRegs, insnRegCount, decInsn.vA,
-            dvmDetermineCat1Const((s4)decInsn.vB), &okay);
+            dvmDetermineCat1Const((s4)decInsn.vB), &failure);
         break;
     case OP_CONST_HIGH16:
         /* could be boolean, int, float, or a null reference */
         setRegisterType(workRegs, insnRegCount, decInsn.vA,
-            dvmDetermineCat1Const((s4) decInsn.vB << 16), &okay);
+            dvmDetermineCat1Const((s4) decInsn.vB << 16), &failure);
         break;
     case OP_CONST_WIDE_16:
     case OP_CONST_WIDE_32:
@@ -3405,36 +3431,38 @@
     case OP_CONST_WIDE_HIGH16:
         /* could be long or double; default to long and allow conversion */
         setRegisterType(workRegs, insnRegCount, decInsn.vA,
-            kRegTypeLongLo, &okay);
+            kRegTypeLongLo, &failure);
         break;
     case OP_CONST_STRING:
     case OP_CONST_STRING_JUMBO:
         assert(gDvm.classJavaLangString != NULL);
         setRegisterType(workRegs, insnRegCount, decInsn.vA,
-            regTypeFromClass(gDvm.classJavaLangString), &okay);
+            regTypeFromClass(gDvm.classJavaLangString), &failure);
         break;
     case OP_CONST_CLASS:
         assert(gDvm.classJavaLangClass != NULL);
         /* make sure we can resolve the class; access check is important */
-        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB);
+        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
         if (resClass == NULL) {
             const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
             dvmLogUnableToResolveClass(badClassDesc, meth);
             LOG_VFY("VFY: unable to resolve const-class %d (%s) in %s\n",
                 decInsn.vB, badClassDesc, meth->clazz->descriptor);
-            okay = false;
+            assert(failure != VERIFY_ERROR_GENERIC);
         } else {
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                regTypeFromClass(gDvm.classJavaLangClass), &okay);
+                regTypeFromClass(gDvm.classJavaLangClass), &failure);
         }
         break;
 
     case OP_MONITOR_ENTER:
     case OP_MONITOR_EXIT:
-        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
-        if (okay && !regTypeIsReference(tmpType)) {
-            LOG_VFY("VFY: monitor op on non-object\n");
-            okay = false;
+        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+        if (VERIFY_OK(failure)) {
+            if (!regTypeIsReference(tmpType)) {
+                LOG_VFY("VFY: monitor op on non-object\n");
+                failure = VERIFY_ERROR_GENERIC;
+            }
         }
         break;
 
@@ -3447,67 +3475,67 @@
          * If it fails, an exception is thrown, which we deal with later
          * by ignoring the update to decInsn.vA when branching to a handler.
          */
-        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB);
+        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
         if (resClass == NULL) {
             const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
             dvmLogUnableToResolveClass(badClassDesc, meth);
             LOG_VFY("VFY: unable to resolve check-cast %d (%s) in %s\n",
                 decInsn.vB, badClassDesc, meth->clazz->descriptor);
-            okay = false;
+            assert(failure != VERIFY_ERROR_GENERIC);
         } else {
             RegType origType;
 
             origType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
-                        &okay);
-            if (!okay)
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
             if (!regTypeIsReference(origType)) {
                 LOG_VFY("VFY: check-cast on non-reference in v%u\n",decInsn.vA);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                regTypeFromClass(resClass), &okay);
+                regTypeFromClass(resClass), &failure);
         }
         break;
     case OP_INSTANCE_OF:
         /* make sure we're checking a reference type */
-        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB, &okay);
-        if (!okay)
+        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB, &failure);
+        if (!VERIFY_OK(failure))
             break;
         if (!regTypeIsReference(tmpType)) {
             LOG_VFY("VFY: vB not a reference (%d)\n", tmpType);
-            okay = false;
+            failure = VERIFY_ERROR_GENERIC;
             break;
         }
 
         /* make sure we can resolve the class; access check is important */
-        resClass = dvmOptResolveClass(meth->clazz, decInsn.vC);
+        resClass = dvmOptResolveClass(meth->clazz, decInsn.vC, &failure);
         if (resClass == NULL) {
             const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vC);
             dvmLogUnableToResolveClass(badClassDesc, meth);
             LOG_VFY("VFY: unable to resolve instanceof %d (%s) in %s\n",
                 decInsn.vC, badClassDesc, meth->clazz->descriptor);
-            okay = false;
+            assert(failure != VERIFY_ERROR_GENERIC);
         } else {
             /* result is boolean */
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                kRegTypeBoolean, &okay);
+                kRegTypeBoolean, &failure);
         }
         break;
 
     case OP_ARRAY_LENGTH:
         resClass = getClassFromRegister(workRegs, insnRegCount,
-                        decInsn.vB, &okay);
-        if (!okay)
+                        decInsn.vB, &failure);
+        if (!VERIFY_OK(failure))
             break;
         if (resClass != NULL && !dvmIsArrayClass(resClass)) {
             LOG_VFY("VFY: array-length on non-array\n");
-            okay = false;
+            failure = VERIFY_ERROR_GENERIC;
             break;
         }
         setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeInteger,
-            &okay);
+            &failure);
         break;
 
     case OP_NEW_INSTANCE:
@@ -3517,13 +3545,13 @@
          * instructions with a magic "always throw InstantiationError"
          * instruction.  (Not enough bytes to sub in a method call.)
          */
-        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB);
+        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
         if (resClass == NULL) {
             const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
             dvmLogUnableToResolveClass(badClassDesc, meth);
             LOG_VFY("VFY: unable to resolve new-instance %d (%s) in %s\n",
                 decInsn.vB, badClassDesc, meth->clazz->descriptor);
-            okay = false;
+            assert(failure != VERIFY_ERROR_GENERIC);
         } else {
             RegType uninitType;
 
@@ -3541,50 +3569,50 @@
 
             /* add the new uninitialized reference to the register ste */
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                uninitType, &okay);
+                uninitType, &failure);
         }
         break;
     case OP_NEW_ARRAY:
-        resClass = dvmOptResolveClass(meth->clazz, decInsn.vC);
+        resClass = dvmOptResolveClass(meth->clazz, decInsn.vC, &failure);
         if (resClass == NULL) {
             const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vC);
             dvmLogUnableToResolveClass(badClassDesc, meth);
             LOG_VFY("VFY: unable to resolve new-array %d (%s) in %s\n",
                 decInsn.vC, badClassDesc, meth->clazz->descriptor);
-            okay = false;
+            assert(failure != VERIFY_ERROR_GENERIC);
         } else if (!dvmIsArrayClass(resClass)) {
             LOG_VFY("VFY: new-array on non-array class\n");
-            okay = false;
+            failure = VERIFY_ERROR_GENERIC;
         } else {
             /* make sure "size" register is valid type */
             verifyRegisterType(workRegs, insnRegCount, decInsn.vB,
-                kRegTypeInteger, &okay);
+                kRegTypeInteger, &failure);
             /* set register type to array class */
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                regTypeFromClass(resClass), &okay);
+                regTypeFromClass(resClass), &failure);
         }
         break;
     case OP_FILLED_NEW_ARRAY:
     case OP_FILLED_NEW_ARRAY_RANGE:
-        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB);
+        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
         if (resClass == NULL) {
             const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
             dvmLogUnableToResolveClass(badClassDesc, meth);
             LOG_VFY("VFY: unable to resolve filled-array %d (%s) in %s\n",
                 decInsn.vB, badClassDesc, meth->clazz->descriptor);
-            okay = false;
+            assert(failure != VERIFY_ERROR_GENERIC);
         } else if (!dvmIsArrayClass(resClass)) {
             LOG_VFY("VFY: filled-new-array on non-array class\n");
-            okay = false;
+            failure = VERIFY_ERROR_GENERIC;
         } else {
             bool isRange = (decInsn.opCode == OP_FILLED_NEW_ARRAY_RANGE);
 
             /* check the arguments to the instruction */
             verifyFilledNewArrayRegs(meth, workRegs, insnRegCount, &decInsn,
-                resClass, isRange, &okay);
+                resClass, isRange, &failure);
             /* filled-array result goes into "result" register */
             setResultRegisterType(workRegs, insnRegCount,
-                regTypeFromClass(resClass), &okay);
+                regTypeFromClass(resClass), &failure);
             justSetResult = true;
         }
         break;
@@ -3592,38 +3620,38 @@
     case OP_CMPL_FLOAT:
     case OP_CMPG_FLOAT:
         verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeFloat,
-            &okay);
+            &failure);
         verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeFloat,
-            &okay);
+            &failure);
         setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean,
-            &okay);
+            &failure);
         break;
     case OP_CMPL_DOUBLE:
     case OP_CMPG_DOUBLE:
         verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeDoubleLo,
-            &okay);
+            &failure);
         verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeDoubleLo,
-            &okay);
+            &failure);
         setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean,
-            &okay);
+            &failure);
         break;
     case OP_CMP_LONG:
         verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeLongLo,
-            &okay);
+            &failure);
         verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeLongLo,
-            &okay);
+            &failure);
         setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean,
-            &okay);
+            &failure);
         break;
 
     case OP_THROW:
         resClass = getClassFromRegister(workRegs, insnRegCount,
-                        decInsn.vA, &okay);
-        if (okay && resClass != NULL) {
+                        decInsn.vA, &failure);
+        if (VERIFY_OK(failure) && resClass != NULL) {
             if (!dvmInstanceof(resClass, gDvm.classJavaLangThrowable)) {
                 LOG_VFY("VFY: thrown class %s not instanceof Throwable\n",
                         resClass->descriptor);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
             }
         }
         break;
@@ -3638,7 +3666,7 @@
     case OP_SPARSE_SWITCH:
         /* verify that vAA is an integer, or can be converted to one */
         verifyRegisterType(workRegs, insnRegCount, decInsn.vA,
-            kRegTypeInteger, &okay);
+            kRegTypeInteger, &failure);
         break;
 
     case OP_FILL_ARRAY_DATA:
@@ -3649,8 +3677,8 @@
 
             /* Similar to the verification done for APUT */
             resClass = getClassFromRegister(workRegs, insnRegCount,
-                            decInsn.vA, &okay);
-            if (!okay)
+                            decInsn.vA, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /* resClass can be null if the reg type is Zero */
@@ -3663,7 +3691,7 @@
             {
                 LOG_VFY("VFY: invalid fill-array-data on %s\n",
                         resClass->descriptor);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
@@ -3678,7 +3706,7 @@
             arrayData = insns + (insns[1] | (((s4)insns[2]) << 16));
             if (arrayData[0] != kArrayDataSignature) {
                 LOG_VFY("VFY: invalid magic for array-data\n");
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
@@ -3712,7 +3740,7 @@
             if (arrayData[1] != elemWidth) {
                 LOG_VFY("VFY: array-data size mismatch (%d vs %d)\n",
                         arrayData[1], elemWidth);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
             }
         }
         break;
@@ -3723,9 +3751,11 @@
             RegType type1, type2;
             bool tmpResult;
 
-            type1 = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
-            type2 = getRegisterType(workRegs, insnRegCount, decInsn.vB, &okay);
-            if (!okay)
+            type1 = getRegisterType(workRegs, insnRegCount, decInsn.vA,
+                        &failure);
+            type2 = getRegisterType(workRegs, insnRegCount, decInsn.vB,
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /* both references? */
@@ -3733,9 +3763,9 @@
                 break;
 
             /* both category-1nr? */
-            checkTypeCategory(type1, kTypeCategory1nr, &okay);
-            checkTypeCategory(type2, kTypeCategory1nr, &okay);
-            if (!okay) {
+            checkTypeCategory(type1, kTypeCategory1nr, &failure);
+            checkTypeCategory(type2, kTypeCategory1nr, &failure);
+            if (!VERIFY_OK(failure)) {
                 LOG_VFY("VFY: args to if-eq/if-ne must both be refs or cat1\n");
                 break;
             }
@@ -3745,43 +3775,43 @@
     case OP_IF_GE:
     case OP_IF_GT:
     case OP_IF_LE:
-        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
-        if (!okay)
+        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+        if (!VERIFY_OK(failure))
             break;
-        checkTypeCategory(tmpType, kTypeCategory1nr, &okay);
-        if (!okay) {
+        checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
+        if (!VERIFY_OK(failure)) {
             LOG_VFY("VFY: args to 'if' must be cat-1nr\n");
             break;
         }
-        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB,&okay);
-        if (!okay)
+        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB, &failure);
+        if (!VERIFY_OK(failure))
             break;
-        checkTypeCategory(tmpType, kTypeCategory1nr, &okay);
-        if (!okay) {
+        checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
+        if (!VERIFY_OK(failure)) {
             LOG_VFY("VFY: args to 'if' must be cat-1nr\n");
             break;
         }
         break;
     case OP_IF_EQZ:
     case OP_IF_NEZ:
-        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
-        if (!okay)
+        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+        if (!VERIFY_OK(failure))
             break;
         if (regTypeIsReference(tmpType))
             break;
-        checkTypeCategory(tmpType, kTypeCategory1nr, &okay);
-        if (!okay)
+        checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
+        if (!VERIFY_OK(failure))
             LOG_VFY("VFY: expected cat-1 arg to if\n");
         break;
     case OP_IF_LTZ:
     case OP_IF_GEZ:
     case OP_IF_GTZ:
     case OP_IF_LEZ:
-        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
-        if (!okay)
+        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+        if (!VERIFY_OK(failure))
             break;
-        checkTypeCategory(tmpType, kTypeCategory1nr, &okay);
-        if (!okay)
+        checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
+        if (!VERIFY_OK(failure))
             LOG_VFY("VFY: expected cat-1 arg to if\n");
         break;
 
@@ -3805,14 +3835,14 @@
             RegType srcType, indexType;
 
             indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
-                            &okay);
-            checkArrayIndexType(meth, indexType, &okay);
-            if (!okay)
+                            &failure);
+            checkArrayIndexType(meth, indexType, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             resClass = getClassFromRegister(workRegs, insnRegCount,
-                            decInsn.vB, &okay);
-            if (!okay)
+                            decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
             if (resClass != NULL) {
                 /* verify the class */
@@ -3821,7 +3851,7 @@
                 {
                     LOG_VFY("VFY: invalid aget-1nr target %s\n",
                         resClass->descriptor);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
@@ -3833,13 +3863,13 @@
                     LOG_VFY("VFY: invalid aget-1nr, array type=%d with"
                             " inst type=%d (on %s)\n",
                         srcType, tmpType, resClass->descriptor);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
             }
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                tmpType, &okay);
+                tmpType, &failure);
         }
         break;
 
@@ -3848,14 +3878,14 @@
             RegType dstType, indexType;
 
             indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
-                            &okay);
-            checkArrayIndexType(meth, indexType, &okay);
-            if (!okay)
+                            &failure);
+            checkArrayIndexType(meth, indexType, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             resClass = getClassFromRegister(workRegs, insnRegCount,
-                            decInsn.vB, &okay);
-            if (!okay)
+                            decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
             if (resClass != NULL) {
                 /* verify the class */
@@ -3864,7 +3894,7 @@
                 {
                     LOG_VFY("VFY: invalid aget-wide target %s\n",
                         resClass->descriptor);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
@@ -3880,7 +3910,7 @@
                     LOG_VFY("VFY: invalid aget-wide on %s\n",
                         resClass->descriptor);
                     dstType = kRegTypeUnknown;
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
             } else {
@@ -3893,7 +3923,7 @@
                 dstType = kRegTypeLongLo;
             }
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                dstType, &okay);
+                dstType, &failure);
         }
         break;
 
@@ -3902,15 +3932,15 @@
             RegType dstType, indexType;
 
             indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
-                            &okay);
-            checkArrayIndexType(meth, indexType, &okay);
-            if (!okay)
+                            &failure);
+            checkArrayIndexType(meth, indexType, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /* get the class of the array we're pulling an object from */
             resClass = getClassFromRegister(workRegs, insnRegCount,
-                            decInsn.vB, &okay);
-            if (!okay)
+                            decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
             if (resClass != NULL) {
                 ClassObject* elementClass;
@@ -3918,7 +3948,7 @@
                 assert(resClass != NULL);
                 if (!dvmIsArrayClass(resClass)) {
                     LOG_VFY("VFY: aget-object on non-array class\n");
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
                 assert(resClass->elementClass != NULL);
@@ -3938,7 +3968,7 @@
                 } else {
                     LOG_VFY("VFY: aget-object on non-ref array class (%s)\n",
                         resClass->descriptor);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
@@ -3954,7 +3984,7 @@
                 dstType = kRegTypeZero;
             }
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                dstType, &okay);
+                dstType, &failure);
         }
         break;
     case OP_APUT:
@@ -3977,24 +4007,24 @@
             RegType srcType, dstType, indexType;
 
             indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
-                            &okay);
-            checkArrayIndexType(meth, indexType, &okay);
-            if (!okay)
+                            &failure);
+            checkArrayIndexType(meth, indexType, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /* make sure the source register has the correct type */
             srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
-                            &okay);
+                            &failure);
             if (!canConvertTo1nr(srcType, tmpType)) {
                 LOG_VFY("VFY: invalid reg type %d on aput instr (need %d)\n",
                     srcType, tmpType);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
             resClass = getClassFromRegister(workRegs, insnRegCount,
-                            decInsn.vB, &okay);
-            if (!okay)
+                            decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /* resClass can be null if the reg type is Zero */
@@ -4005,7 +4035,7 @@
                 resClass->elementClass->primitiveType == PRIM_NOT)
             {
                 LOG_VFY("VFY: invalid aput-1nr on %s\n", resClass->descriptor);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
@@ -4017,31 +4047,31 @@
             if (!checkFieldArrayStore1nr(tmpType, dstType)) {
                 LOG_VFY("VFY: invalid aput-1nr on %s (inst=%d dst=%d)\n",
                         resClass->descriptor, tmpType, dstType);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
         }
         break;
     case OP_APUT_WIDE:
         tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
-                        &okay);
-        checkArrayIndexType(meth, tmpType, &okay);
-        if (!okay)
+                        &failure);
+        checkArrayIndexType(meth, tmpType, &failure);
+        if (!VERIFY_OK(failure))
             break;
 
-        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
-        if (okay) {
+        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+        if (VERIFY_OK(failure)) {
             RegType typeHi =
-                getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &okay);
-            checkTypeCategory(tmpType, kTypeCategory2, &okay);
-            checkWidePair(tmpType, typeHi, &okay);
+                getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &failure);
+            checkTypeCategory(tmpType, kTypeCategory2, &failure);
+            checkWidePair(tmpType, typeHi, &failure);
         }
-        if (!okay)
+        if (!VERIFY_OK(failure))
             break;
 
         resClass = getClassFromRegister(workRegs, insnRegCount,
-                        decInsn.vB, &okay);
-        if (!okay)
+                        decInsn.vB, &failure);
+        if (!VERIFY_OK(failure))
             break;
         if (resClass != NULL) {
             /* verify the class and try to refine "dstType" */
@@ -4050,7 +4080,7 @@
             {
                 LOG_VFY("VFY: invalid aput-wide on %s\n",
                         resClass->descriptor);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
@@ -4062,22 +4092,22 @@
             default:
                 LOG_VFY("VFY: invalid aput-wide on %s\n",
                         resClass->descriptor);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
         }
         break;
     case OP_APUT_OBJECT:
         tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
-                        &okay);
-        checkArrayIndexType(meth, tmpType, &okay);
-        if (!okay)
+                        &failure);
+        checkArrayIndexType(meth, tmpType, &failure);
+        if (!VERIFY_OK(failure))
             break;
 
         /* get the ref we're storing; Zero is okay, Uninit is not */
         resClass = getClassFromRegister(workRegs, insnRegCount,
-                        decInsn.vA, &okay);
-        if (!okay)
+                        decInsn.vA, &failure);
+        if (!VERIFY_OK(failure))
             break;
         if (resClass != NULL) {
             ClassObject* arrayClass;
@@ -4089,14 +4119,14 @@
              * null pointer exception).
              */
             arrayClass = getClassFromRegister(workRegs, insnRegCount,
-                            decInsn.vB, &okay);
+                            decInsn.vB, &failure);
 
             if (arrayClass != NULL) {
                 /* see if the array holds a compatible type */
                 if (!dvmIsArrayClass(arrayClass)) {
                     LOG_VFY("VFY: invalid aput-object on %s\n",
                             arrayClass->descriptor);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
@@ -4121,7 +4151,7 @@
                 if (elementClass->primitiveType != PRIM_NOT) {
                     LOG_VFY("VFY: invalid aput-object of %s into %s\n",
                             resClass->descriptor, arrayClass->descriptor);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
             }
@@ -4150,12 +4180,12 @@
             RegType objType, fieldType;
 
             objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
-                        &okay);
-            if (!okay)
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
             instField = getInstField(meth, uninitMap, objType, decInsn.vC,
-                            &okay);
-            if (!okay)
+                            &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /* make sure the field's type is compatible with expectation */
@@ -4166,11 +4196,12 @@
                 LOG_VFY("VFY: invalid iget-1nr of %s.%s (inst=%d field=%d)\n",
                         instField->field.clazz->descriptor,
                         instField->field.name, tmpType, fieldType);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
-            setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType, &okay);
+            setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType,
+                &failure);
         }
         break;
     case OP_IGET_WIDE:
@@ -4181,12 +4212,12 @@
             RegType objType;
 
             objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
-                        &okay);
-            if (!okay)
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
             instField = getInstField(meth, uninitMap, objType, decInsn.vC,
-                            &okay);
-            if (!okay)
+                            &failure);
+            if (!VERIFY_OK(failure))
                 break;
             /* check the type, which should be prim */
             switch (instField->field.signature[0]) {
@@ -4201,12 +4232,12 @@
                         instField->field.clazz->descriptor,
                         instField->field.name);
                 dstType = kRegTypeUnknown;
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
-            if (okay) {
+            if (VERIFY_OK(failure)) {
                 setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                    dstType, &okay);
+                    dstType, &failure);
             }
         }
         break;
@@ -4217,25 +4248,25 @@
             RegType objType;
 
             objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
-                        &okay);
-            if (!okay)
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
             instField = getInstField(meth, uninitMap, objType, decInsn.vC,
-                            &okay);
-            if (!okay)
+                            &failure);
+            if (!VERIFY_OK(failure))
                 break;
             fieldClass = getFieldClass(meth, &instField->field);
             if (fieldClass == NULL) {
                 /* class not found or primitive type */
                 LOG_VFY("VFY: unable to recover field class from '%s'\n",
                     instField->field.signature);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
-            if (okay) {
+            if (VERIFY_OK(failure)) {
                 assert(!dvmIsPrimitiveClass(fieldClass));
                 setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                    regTypeFromClass(fieldClass), &okay);
+                    regTypeFromClass(fieldClass), &failure);
             }
         }
         break;
@@ -4262,24 +4293,24 @@
 
             /* make sure the source register has the correct type */
             srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
-                        &okay);
+                        &failure);
             if (!canConvertTo1nr(srcType, tmpType)) {
                 LOG_VFY("VFY: invalid reg type %d on iput instr (need %d)\n",
                     srcType, tmpType);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
             objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
-                        &okay);
-            if (!okay)
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
             instField = getInstField(meth, uninitMap, objType, decInsn.vC,
-                            &okay);
-            if (!okay)
+                            &failure);
+            if (!VERIFY_OK(failure))
                 break;
-            checkFinalFieldAccess(meth, &instField->field, &okay);
-            if (!okay)
+            checkFinalFieldAccess(meth, &instField->field, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /* get type of field we're storing into */
@@ -4290,34 +4321,34 @@
                 LOG_VFY("VFY: invalid iput-1nr of %s.%s (inst=%d field=%d)\n",
                         instField->field.clazz->descriptor,
                         instField->field.name, tmpType, fieldType);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
         }
         break;
     case OP_IPUT_WIDE:
-        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
-        if (okay) {
+        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+        if (VERIFY_OK(failure)) {
             RegType typeHi =
-                getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &okay);
-            checkTypeCategory(tmpType, kTypeCategory2, &okay);
-            checkWidePair(tmpType, typeHi, &okay);
+                getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &failure);
+            checkTypeCategory(tmpType, kTypeCategory2, &failure);
+            checkWidePair(tmpType, typeHi, &failure);
         }
-        if (okay) {
+        if (VERIFY_OK(failure)) {
             ClassObject* fieldClass;
             InstField* instField;
             RegType objType;
 
             objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
-                        &okay);
-            if (!okay)
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
             instField = getInstField(meth, uninitMap, objType, decInsn.vC,
-                            &okay);
-            if (!okay)
+                            &failure);
+            if (!VERIFY_OK(failure))
                 break;
-            checkFinalFieldAccess(meth, &instField->field, &okay);
-            if (!okay)
+            checkFinalFieldAccess(meth, &instField->field, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /* check the type, which should be prim */
@@ -4330,7 +4361,7 @@
                 LOG_VFY("VFY: invalid iput-wide of %s.%s\n",
                         instField->field.clazz->descriptor,
                         instField->field.name);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
         }
@@ -4343,34 +4374,34 @@
             RegType objType, valueType;
 
             objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
-                        &okay);
-            if (!okay)
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
             instField = getInstField(meth, uninitMap, objType, decInsn.vC,
-                            &okay);
-            if (!okay)
+                            &failure);
+            if (!VERIFY_OK(failure))
                 break;
-            checkFinalFieldAccess(meth, &instField->field, &okay);
-            if (!okay)
+            checkFinalFieldAccess(meth, &instField->field, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             fieldClass = getFieldClass(meth, &instField->field);
             if (fieldClass == NULL) {
                 LOG_VFY("VFY: unable to recover field class from '%s'\n",
                     instField->field.signature);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
             valueType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
-                        &okay);
-            if (!okay)
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
             if (!regTypeIsReference(valueType)) {
                 LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)\n",
                         decInsn.vA, instField->field.name,
                         fieldClass->descriptor);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
             if (valueType != kRegTypeZero) {
@@ -4378,7 +4409,7 @@
                 if (valueClass == NULL) {
                     LOG_VFY("VFY: storing uninit ref v%d into ref field\n",
                         decInsn.vA);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
                 /* allow if field is any interface or field is base class */
@@ -4389,7 +4420,7 @@
                             valueClass->descriptor, fieldClass->descriptor,
                             instField->field.clazz->descriptor,
                             instField->field.name);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
             }
@@ -4416,8 +4447,8 @@
             StaticField* staticField;
             RegType fieldType;
 
-            staticField = getStaticField(meth, decInsn.vB, &okay);
-            if (!okay)
+            staticField = getStaticField(meth, decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /*
@@ -4433,11 +4464,12 @@
                 LOG_VFY("VFY: invalid sget-1nr of %s.%s (inst=%d actual=%d)\n",
                     staticField->field.clazz->descriptor,
                     staticField->field.name, tmpType, fieldType);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
-            setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType, &okay);
+            setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType,
+                &failure);
         }
         break;
     case OP_SGET_WIDE:
@@ -4445,8 +4477,8 @@
             StaticField* staticField;
             RegType dstType;
 
-            staticField = getStaticField(meth, decInsn.vB, &okay);
-            if (!okay)
+            staticField = getStaticField(meth, decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
             /* check the type, which should be prim */
             switch (staticField->field.signature[0]) {
@@ -4461,12 +4493,12 @@
                         staticField->field.clazz->descriptor,
                         staticField->field.name);
                 dstType = kRegTypeUnknown;
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
-            if (okay) {
+            if (VERIFY_OK(failure)) {
                 setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                    dstType, &okay);
+                    dstType, &failure);
             }
         }
         break;
@@ -4475,23 +4507,23 @@
             StaticField* staticField;
             ClassObject* fieldClass;
 
-            staticField = getStaticField(meth, decInsn.vB, &okay);
-            if (!okay)
+            staticField = getStaticField(meth, decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
             fieldClass = getFieldClass(meth, &staticField->field);
             if (fieldClass == NULL) {
                 LOG_VFY("VFY: unable to recover field class from '%s'\n",
                     staticField->field.signature);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
             if (dvmIsPrimitiveClass(fieldClass)) {
                 LOG_VFY("VFY: attempt to get prim field with sget-object\n");
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                regTypeFromClass(fieldClass), &okay);
+                regTypeFromClass(fieldClass), &failure);
         }
         break;
     case OP_SPUT:
@@ -4516,19 +4548,19 @@
 
             /* make sure the source register has the correct type */
             srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
-                        &okay);
+                        &failure);
             if (!canConvertTo1nr(srcType, tmpType)) {
                 LOG_VFY("VFY: invalid reg type %d on iput instr (need %d)\n",
                     srcType, tmpType);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
-            staticField = getStaticField(meth, decInsn.vB, &okay);
-            if (!okay)
+            staticField = getStaticField(meth, decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
-            checkFinalFieldAccess(meth, &staticField->field, &okay);
-            if (!okay)
+            checkFinalFieldAccess(meth, &staticField->field, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /*
@@ -4543,27 +4575,27 @@
                 LOG_VFY("VFY: invalid sput-1nr of %s.%s (inst=%d actual=%d)\n",
                     staticField->field.clazz->descriptor,
                     staticField->field.name, tmpType, fieldType);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
         }
         break;
     case OP_SPUT_WIDE:
-        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
-        if (okay) {
+        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+        if (VERIFY_OK(failure)) {
             RegType typeHi =
-                getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &okay);
-            checkTypeCategory(tmpType, kTypeCategory2, &okay);
-            checkWidePair(tmpType, typeHi, &okay);
+                getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &failure);
+            checkTypeCategory(tmpType, kTypeCategory2, &failure);
+            checkWidePair(tmpType, typeHi, &failure);
         }
-        if (okay) {
+        if (VERIFY_OK(failure)) {
             StaticField* staticField;
 
-            staticField = getStaticField(meth, decInsn.vB, &okay);
-            if (!okay)
+            staticField = getStaticField(meth, decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
-            checkFinalFieldAccess(meth, &staticField->field, &okay);
-            if (!okay)
+            checkFinalFieldAccess(meth, &staticField->field, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /* check the type, which should be prim */
@@ -4576,7 +4608,7 @@
                 LOG_VFY("VFY: invalid sput-wide of %s.%s\n",
                         staticField->field.clazz->descriptor,
                         staticField->field.name);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
         }
@@ -4588,30 +4620,30 @@
             StaticField* staticField;
             RegType valueType;
 
-            staticField = getStaticField(meth, decInsn.vB, &okay);
-            if (!okay)
+            staticField = getStaticField(meth, decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
-            checkFinalFieldAccess(meth, &staticField->field, &okay);
-            if (!okay)
+            checkFinalFieldAccess(meth, &staticField->field, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             fieldClass = getFieldClass(meth, &staticField->field);
             if (fieldClass == NULL) {
                 LOG_VFY("VFY: unable to recover field class from '%s'\n",
                     staticField->field.signature);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
             valueType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
-                        &okay);
-            if (!okay)
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
             if (!regTypeIsReference(valueType)) {
                 LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)\n",
                         decInsn.vA, staticField->field.name,
                         fieldClass->descriptor);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
             if (valueType != kRegTypeZero) {
@@ -4619,7 +4651,7 @@
                 if (valueClass == NULL) {
                     LOG_VFY("VFY: storing uninit ref v%d into ref field\n",
                         decInsn.vA);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
                 /* allow if field is any interface or field is base class */
@@ -4630,7 +4662,7 @@
                             valueClass->descriptor, fieldClass->descriptor,
                             staticField->field.clazz->descriptor,
                             staticField->field.name);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
             }
@@ -4654,11 +4686,11 @@
 
             calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
                             &decInsn, uninitMap, METHOD_VIRTUAL, isRange,
-                            isSuper, &okay);
-            if (!okay)
+                            isSuper, &failure);
+            if (!VERIFY_OK(failure))
                 break;
             returnType = getMethodReturnType(calledMethod);
-            setResultRegisterType(workRegs, insnRegCount, returnType, &okay);
+            setResultRegisterType(workRegs, insnRegCount, returnType, &failure);
             justSetResult = true;
         }
         break;
@@ -4672,8 +4704,8 @@
             isRange =  (decInsn.opCode == OP_INVOKE_DIRECT_RANGE);
             calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
                             &decInsn, uninitMap, METHOD_DIRECT, isRange,
-                            false, &okay);
-            if (!okay)
+                            false, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /*
@@ -4688,14 +4720,14 @@
             if (isInitMethod(calledMethod)) {
                 RegType thisType;
                 thisType = getInvocationThis(workRegs, insnRegCount,
-                            &decInsn, &okay);
-                if (!okay)
+                            &decInsn, &failure);
+                if (!VERIFY_OK(failure))
                     break;
 
                 /* no null refs allowed (?) */
                 if (thisType == kRegTypeZero) {
                     LOG_VFY("VFY: unable to initialize null ref\n");
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
@@ -4709,20 +4741,20 @@
                     if (thisClass != meth->clazz) {
                         LOG_VFY("VFY: invoke-direct <init> on super only "
                             "allowed for 'this' in <init>");
-                        okay = false;
+                        failure = VERIFY_ERROR_GENERIC;
                         break;
                     }
                 }  else if (calledMethod->clazz != thisClass) {
                     LOG_VFY("VFY: invoke-direct <init> must be on current "
                             "class or super\n");
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
                 /* arg must be an uninitialized reference */
                 if (!regTypeIsUninitReference(thisType)) {
                     LOG_VFY("VFY: can only initialize the uninitialized\n");
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
@@ -4734,13 +4766,13 @@
                  */
                 int uidx = regTypeToUninitIndex(thisType);
                 markRefsAsInitialized(workRegs, insnRegCount, uninitMap,
-                    thisType, &okay);
-                if (!okay)
+                    thisType, &failure);
+                if (!VERIFY_OK(failure))
                     break;
             }
             returnType = getMethodReturnType(calledMethod);
             setResultRegisterType(workRegs, insnRegCount,
-                returnType, &okay);
+                returnType, &failure);
             justSetResult = true;
         }
         break;
@@ -4754,12 +4786,12 @@
             isRange =  (decInsn.opCode == OP_INVOKE_STATIC_RANGE);
             calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
                             &decInsn, uninitMap, METHOD_STATIC, isRange,
-                            false, &okay);
-            if (!okay)
+                            false, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             returnType = getMethodReturnType(calledMethod);
-            setResultRegisterType(workRegs, insnRegCount, returnType, &okay);
+            setResultRegisterType(workRegs, insnRegCount, returnType, &failure);
             justSetResult = true;
         }
         break;
@@ -4773,8 +4805,8 @@
             isRange =  (decInsn.opCode == OP_INVOKE_INTERFACE_RANGE);
             absMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
                             &decInsn, uninitMap, METHOD_INTERFACE, isRange,
-                            false, &okay);
-            if (!okay)
+                            false, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
 #if 0       /* can't do this here, fails on dalvik test 052-verifier-fun */
@@ -4784,8 +4816,8 @@
              * interface classes, this might have reduced to Object.
              */
             thisType = getInvocationThis(workRegs, insnRegCount,
-                        &decInsn, &okay);
-            if (!okay)
+                        &decInsn, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             if (thisType == kRegTypeZero) {
@@ -4796,7 +4828,7 @@
                 thisClass = regTypeInitializedReferenceToClass(thisType);
                 if (thisClass == NULL) {
                     LOG_VFY("VFY: interface call on uninitialized\n");
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
@@ -4812,7 +4844,7 @@
                 {
                     LOG_VFY("VFY: unable to match absMethod '%s' with %s interfaces\n",
                             absMethod->name, thisClass->descriptor);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
             }
@@ -4824,7 +4856,7 @@
              * in the abstract method, so we're good.
              */
             returnType = getMethodReturnType(absMethod);
-            setResultRegisterType(workRegs, insnRegCount, returnType, &okay);
+            setResultRegisterType(workRegs, insnRegCount, returnType, &failure);
             justSetResult = true;
         }
         break;
@@ -4832,80 +4864,80 @@
     case OP_NEG_INT:
     case OP_NOT_INT:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, &okay);
+            kRegTypeInteger, kRegTypeInteger, &failure);
         break;
     case OP_NEG_LONG:
     case OP_NOT_LONG:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeLongLo, kRegTypeLongLo, &okay);
+            kRegTypeLongLo, kRegTypeLongLo, &failure);
         break;
     case OP_NEG_FLOAT:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeFloat, kRegTypeFloat, &okay);
+            kRegTypeFloat, kRegTypeFloat, &failure);
         break;
     case OP_NEG_DOUBLE:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeDoubleLo, kRegTypeDoubleLo, &okay);
+            kRegTypeDoubleLo, kRegTypeDoubleLo, &failure);
         break;
     case OP_INT_TO_LONG:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeLongLo, kRegTypeInteger, &okay);
+            kRegTypeLongLo, kRegTypeInteger, &failure);
         break;
     case OP_INT_TO_FLOAT:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeFloat, kRegTypeInteger, &okay);
+            kRegTypeFloat, kRegTypeInteger, &failure);
         break;
     case OP_INT_TO_DOUBLE:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeDoubleLo, kRegTypeInteger, &okay);
+            kRegTypeDoubleLo, kRegTypeInteger, &failure);
         break;
     case OP_LONG_TO_INT:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeLongLo, &okay);
+            kRegTypeInteger, kRegTypeLongLo, &failure);
         break;
     case OP_LONG_TO_FLOAT:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeFloat, kRegTypeLongLo, &okay);
+            kRegTypeFloat, kRegTypeLongLo, &failure);
         break;
     case OP_LONG_TO_DOUBLE:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeDoubleLo, kRegTypeLongLo, &okay);
+            kRegTypeDoubleLo, kRegTypeLongLo, &failure);
         break;
     case OP_FLOAT_TO_INT:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeFloat, &okay);
+            kRegTypeInteger, kRegTypeFloat, &failure);
         break;
     case OP_FLOAT_TO_LONG:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeLongLo, kRegTypeFloat, &okay);
+            kRegTypeLongLo, kRegTypeFloat, &failure);
         break;
     case OP_FLOAT_TO_DOUBLE:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeDoubleLo, kRegTypeFloat, &okay);
+            kRegTypeDoubleLo, kRegTypeFloat, &failure);
         break;
     case OP_DOUBLE_TO_INT:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeDoubleLo, &okay);
+            kRegTypeInteger, kRegTypeDoubleLo, &failure);
         break;
     case OP_DOUBLE_TO_LONG:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeLongLo, kRegTypeDoubleLo, &okay);
+            kRegTypeLongLo, kRegTypeDoubleLo, &failure);
         break;
     case OP_DOUBLE_TO_FLOAT:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeFloat, kRegTypeDoubleLo, &okay);
+            kRegTypeFloat, kRegTypeDoubleLo, &failure);
         break;
     case OP_INT_TO_BYTE:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeByte, kRegTypeInteger, &okay);
+            kRegTypeByte, kRegTypeInteger, &failure);
         break;
     case OP_INT_TO_CHAR:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeChar, kRegTypeInteger, &okay);
+            kRegTypeChar, kRegTypeInteger, &failure);
         break;
     case OP_INT_TO_SHORT:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeShort, kRegTypeInteger, &okay);
+            kRegTypeShort, kRegTypeInteger, &failure);
         break;
 
     case OP_ADD_INT:
@@ -4917,13 +4949,13 @@
     case OP_SHR_INT:
     case OP_USHR_INT:
         checkBinop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &okay);
+            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure);
         break;
     case OP_AND_INT:
     case OP_OR_INT:
     case OP_XOR_INT:
         checkBinop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &okay);
+            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &failure);
         break;
     case OP_ADD_LONG:
     case OP_SUB_LONG:
@@ -4934,14 +4966,14 @@
     case OP_OR_LONG:
     case OP_XOR_LONG:
         checkBinop(workRegs, insnRegCount, &decInsn,
-            kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &okay);
+            kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &failure);
         break;
     case OP_SHL_LONG:
     case OP_SHR_LONG:
     case OP_USHR_LONG:
         /* shift distance is Int, making these different from other binops */
         checkBinop(workRegs, insnRegCount, &decInsn,
-            kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &okay);
+            kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &failure);
         break;
     case OP_ADD_FLOAT:
     case OP_SUB_FLOAT:
@@ -4949,7 +4981,7 @@
     case OP_DIV_FLOAT:
     case OP_REM_FLOAT:
         checkBinop(workRegs, insnRegCount, &decInsn,
-            kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &okay);
+            kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &failure);
         break;
     case OP_ADD_DOUBLE:
     case OP_SUB_DOUBLE:
@@ -4957,7 +4989,8 @@
     case OP_DIV_DOUBLE:
     case OP_REM_DOUBLE:
         checkBinop(workRegs, insnRegCount, &decInsn,
-            kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false, &okay);
+            kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false,
+            &failure);
         break;
     case OP_ADD_INT_2ADDR:
     case OP_SUB_INT_2ADDR:
@@ -4967,17 +5000,17 @@
     case OP_SHR_INT_2ADDR:
     case OP_USHR_INT_2ADDR:
         checkBinop2addr(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &okay);
+            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure);
         break;
     case OP_AND_INT_2ADDR:
     case OP_OR_INT_2ADDR:
     case OP_XOR_INT_2ADDR:
         checkBinop2addr(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &okay);
+            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &failure);
         break;
     case OP_DIV_INT_2ADDR:
         checkBinop2addr(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &okay);
+            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure);
         break;
     case OP_ADD_LONG_2ADDR:
     case OP_SUB_LONG_2ADDR:
@@ -4988,13 +5021,13 @@
     case OP_OR_LONG_2ADDR:
     case OP_XOR_LONG_2ADDR:
         checkBinop2addr(workRegs, insnRegCount, &decInsn,
-            kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &okay);
+            kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &failure);
         break;
     case OP_SHL_LONG_2ADDR:
     case OP_SHR_LONG_2ADDR:
     case OP_USHR_LONG_2ADDR:
         checkBinop2addr(workRegs, insnRegCount, &decInsn,
-            kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &okay);
+            kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &failure);
         break;
     case OP_ADD_FLOAT_2ADDR:
     case OP_SUB_FLOAT_2ADDR:
@@ -5002,7 +5035,7 @@
     case OP_DIV_FLOAT_2ADDR:
     case OP_REM_FLOAT_2ADDR:
         checkBinop2addr(workRegs, insnRegCount, &decInsn,
-            kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &okay);
+            kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &failure);
         break;
     case OP_ADD_DOUBLE_2ADDR:
     case OP_SUB_DOUBLE_2ADDR:
@@ -5010,7 +5043,8 @@
     case OP_DIV_DOUBLE_2ADDR:
     case OP_REM_DOUBLE_2ADDR:
         checkBinop2addr(workRegs, insnRegCount, &decInsn,
-            kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false, &okay);
+            kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false,
+            &failure);
         break;
     case OP_ADD_INT_LIT16:
     case OP_RSUB_INT:
@@ -5018,13 +5052,13 @@
     case OP_DIV_INT_LIT16:
     case OP_REM_INT_LIT16:
         checkLitop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, false, &okay);
+            kRegTypeInteger, kRegTypeInteger, false, &failure);
         break;
     case OP_AND_INT_LIT16:
     case OP_OR_INT_LIT16:
     case OP_XOR_INT_LIT16:
         checkLitop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, true, &okay);
+            kRegTypeInteger, kRegTypeInteger, true, &failure);
         break;
     case OP_ADD_INT_LIT8:
     case OP_RSUB_INT_LIT8:
@@ -5035,13 +5069,13 @@
     case OP_SHR_INT_LIT8:
     case OP_USHR_INT_LIT8:
         checkLitop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, false, &okay);
+            kRegTypeInteger, kRegTypeInteger, false, &failure);
         break;
     case OP_AND_INT_LIT8:
     case OP_OR_INT_LIT8:
     case OP_XOR_INT_LIT8:
         checkLitop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, true, &okay);
+            kRegTypeInteger, kRegTypeInteger, true, &failure);
         break;
 
 
@@ -5089,7 +5123,7 @@
     case OP_INVOKE_VIRTUAL_QUICK_RANGE:
     case OP_INVOKE_SUPER_QUICK:
     case OP_INVOKE_SUPER_QUICK_RANGE:
-        okay = false;
+        failure = VERIFY_ERROR_GENERIC;
         break;
 
     /* these should never appear */
@@ -5119,7 +5153,7 @@
     case OP_UNUSED_FD:
     case OP_UNUSED_FE:
     case OP_UNUSED_FF:
-        okay = false;
+        failure = VERIFY_ERROR_GENERIC;
         break;
 
     /*
@@ -5128,7 +5162,7 @@
      */
     }
 
-    if (!okay) {
+    if (!VERIFY_OK(failure)) {
         LOG_VFY_METH(meth, "VFY:  rejecting opcode 0x%02x at 0x%04x\n",
             decInsn.opCode, insnIdx);
         goto bail;
diff --git a/vm/analysis/DexOptimize.c b/vm/analysis/DexOptimize.c
index 3ab6216..d420043 100644
--- a/vm/analysis/DexOptimize.c
+++ b/vm/analysis/DexOptimize.c
@@ -1658,8 +1658,11 @@
  * file.
  *
  * Exceptions caused by failures are cleared before returning.
+ *
+ * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
  */
-ClassObject* dvmOptResolveClass(ClassObject* referrer, u4 classIdx)
+ClassObject* dvmOptResolveClass(ClassObject* referrer, u4 classIdx,
+    VerifyError* pFailure)
 {
     DvmDex* pDvmDex = referrer->pDvmDex;
     ClassObject* resClass;
@@ -1682,6 +1685,8 @@
                 classIdx,
                 dexStringByTypeIdx(pDvmDex->pDexFile, classIdx));
             dvmClearOptException(dvmThreadSelf());
+            if (pFailure != NULL)
+                *pFailure = VERIFY_ERROR_NO_CLASS;
             return NULL;
         }
 
@@ -1695,6 +1700,8 @@
     if (IS_CLASS_FLAG_SET(resClass, CLASS_MULTIPLE_DEFS)) {
         LOGI("DexOpt: not resolving ambiguous class '%s'\n",
             resClass->descriptor);
+        if (pFailure != NULL)
+            *pFailure = VERIFY_ERROR_NO_CLASS;
         return NULL;
     }
 
@@ -1705,6 +1712,8 @@
     if (!allowed) {
         LOGW("DexOpt: resolve class illegal access: %s -> %s\n",
             referrer->descriptor, resClass->descriptor);
+        if (pFailure != NULL)
+            *pFailure = VERIFY_ERROR_ACCESS;
         return NULL;
     }
 
@@ -1713,8 +1722,11 @@
 
 /*
  * Alternate version of dvmResolveInstField().
+ *
+ * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
  */
-InstField* dvmOptResolveInstField(ClassObject* referrer, u4 ifieldIdx)
+InstField* dvmOptResolveInstField(ClassObject* referrer, u4 ifieldIdx,
+    VerifyError* pFailure)
 {
     DvmDex* pDvmDex = referrer->pDvmDex;
     InstField* resField;
@@ -1729,10 +1741,12 @@
         /*
          * Find the field's class.
          */
-        resClass = dvmOptResolveClass(referrer, pFieldId->classIdx);
+        resClass = dvmOptResolveClass(referrer, pFieldId->classIdx, pFailure);
         if (resClass == NULL) {
             //dvmClearOptException(dvmThreadSelf());
             assert(!dvmCheckException(dvmThreadSelf()));
+            if (pFailure != NULL)
+                *pFailure = VERIFY_ERROR_NO_FIELD;
             return NULL;
         }
 
@@ -1743,6 +1757,8 @@
             LOGD("DexOpt: couldn't find field %s.%s\n",
                 resClass->descriptor,
                 dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
+            if (pFailure != NULL)
+                *pFailure = VERIFY_ERROR_NO_FIELD;
             return NULL;
         }
 
@@ -1760,6 +1776,8 @@
         LOGI("DexOpt: access denied from %s to field %s.%s\n",
             referrer->descriptor, resField->field.clazz->descriptor,
             resField->field.name);
+        if (pFailure != NULL)
+            *pFailure = VERIFY_ERROR_ACCESS;
         return NULL;
     }
 
@@ -1770,8 +1788,11 @@
  * Alternate version of dvmResolveStaticField().
  *
  * Does not force initialization of the resolved field's class.
+ *
+ * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
  */
-StaticField* dvmOptResolveStaticField(ClassObject* referrer, u4 sfieldIdx)
+StaticField* dvmOptResolveStaticField(ClassObject* referrer, u4 sfieldIdx,
+    VerifyError* pFailure)
 {
     DvmDex* pDvmDex = referrer->pDvmDex;
     StaticField* resField;
@@ -1786,10 +1807,12 @@
         /*
          * Find the field's class.
          */
-        resClass = dvmOptResolveClass(referrer, pFieldId->classIdx);
+        resClass = dvmOptResolveClass(referrer, pFieldId->classIdx, pFailure);
         if (resClass == NULL) {
             //dvmClearOptException(dvmThreadSelf());
             assert(!dvmCheckException(dvmThreadSelf()));
+            if (pFailure != NULL)
+                *pFailure = VERIFY_ERROR_NO_FIELD;
             return NULL;
         }
 
@@ -1798,6 +1821,8 @@
                     dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx));
         if (resField == NULL) {
             LOGD("DexOpt: couldn't find static field\n");
+            if (pFailure != NULL)
+                *pFailure = VERIFY_ERROR_NO_FIELD;
             return NULL;
         }
 
@@ -1820,6 +1845,8 @@
         LOGI("DexOpt: access denied from %s to field %s.%s\n",
             referrer->descriptor, resField->field.clazz->descriptor,
             resField->field.name);
+        if (pFailure != NULL)
+            *pFailure = VERIFY_ERROR_ACCESS;
         return NULL;
     }
 
@@ -1845,7 +1872,7 @@
     InstField* field;
     int byteOffset;
 
-    field = dvmOptResolveInstField(clazz, fieldIdx);
+    field = dvmOptResolveInstField(clazz, fieldIdx, NULL);
     if (field == NULL) {
         LOGI("DexOpt: unable to optimize field ref 0x%04x at 0x%02x in %s.%s\n",
             fieldIdx, (int) (insns - method->insns), clazz->descriptor,
@@ -1869,9 +1896,11 @@
  * Alternate version of dvmResolveMethod().
  *
  * Doesn't throw exceptions, and checks access on every lookup.
+ *
+ * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
  */
 Method* dvmOptResolveMethod(ClassObject* referrer, u4 methodIdx,
-    MethodType methodType)
+    MethodType methodType, VerifyError* pFailure)
 {
     DvmDex* pDvmDex = referrer->pDvmDex;
     Method* resMethod;
@@ -1888,16 +1917,20 @@
 
         pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx);
 
-        resClass = dvmOptResolveClass(referrer, pMethodId->classIdx);
+        resClass = dvmOptResolveClass(referrer, pMethodId->classIdx, pFailure);
         if (resClass == NULL) {
             /* can't find the class that the method is a part of */
             LOGV("DexOpt: can't find called method's class (?.%s)\n",
                 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx));
+            if (pFailure != NULL)
+                *pFailure = VERIFY_ERROR_NO_METHOD;
             return NULL;
         }
         if (dvmIsInterfaceClass(resClass)) {
             /* method is part of an interface; this is wrong method for that */
             LOGW("DexOpt: method is in an interface\n");
+            if (pFailure != NULL)
+                *pFailure = VERIFY_ERROR_GENERIC;
             return NULL;
         }
 
@@ -1923,6 +1956,8 @@
         if (resMethod == NULL) {
             LOGV("DexOpt: couldn't find method '%s'\n",
                 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx));
+            if (pFailure != NULL)
+                *pFailure = VERIFY_ERROR_NO_METHOD;
             return NULL;
         }
 
@@ -1931,6 +1966,8 @@
             LOGW("DexOpt: pure-abstract method '%s' in %s\n",
                 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx),
                 resClass->descriptor);
+            if (pFailure != NULL)
+                *pFailure = VERIFY_ERROR_GENERIC;
             return NULL;
         }
 
@@ -1961,6 +1998,8 @@
                 referrer->descriptor);
             free(desc);
         }
+        if (pFailure != NULL)
+            *pFailure = VERIFY_ERROR_ACCESS;
         return NULL;
     }
 
@@ -1981,7 +2020,7 @@
     Method* baseMethod;
     u2 methodIdx = insns[1];
 
-    baseMethod = dvmOptResolveMethod(clazz, methodIdx, METHOD_VIRTUAL);
+    baseMethod = dvmOptResolveMethod(clazz, methodIdx, METHOD_VIRTUAL, NULL);
     if (baseMethod == NULL) {
         LOGD("DexOpt: unable to optimize virt call 0x%04x at 0x%02x in %s.%s\n",
             methodIdx,
@@ -2025,7 +2064,7 @@
     Method* calledMethod;
     u2 methodIdx = insns[1];
 
-    calledMethod = dvmOptResolveMethod(clazz, methodIdx, METHOD_DIRECT);
+    calledMethod = dvmOptResolveMethod(clazz, methodIdx, METHOD_DIRECT, NULL);
     if (calledMethod == NULL) {
         LOGD("DexOpt: unable to opt direct call 0x%04x at 0x%02x in %s.%s\n",
             methodIdx,
@@ -2057,6 +2096,8 @@
 /*
  * Resolve an interface method reference.
  *
+ * No method access check here -- interface methods are always public.
+ *
  * Returns NULL if the method was not found.  Does not throw an exception.
  */
 Method* dvmOptResolveInterfaceMethod(ClassObject* referrer, u4 methodIdx)
@@ -2075,7 +2116,7 @@
 
         pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx);
 
-        resClass = dvmOptResolveClass(referrer, pMethodId->classIdx);
+        resClass = dvmOptResolveClass(referrer, pMethodId->classIdx, NULL);
         if (resClass == NULL) {
             /* can't find the class that the method is a part of */
             dvmClearOptException(dvmThreadSelf());
@@ -2151,7 +2192,7 @@
 
     //return false;
 
-    calledMethod = dvmOptResolveMethod(clazz, methodIdx, methodType);
+    calledMethod = dvmOptResolveMethod(clazz, methodIdx, methodType, NULL);
     if (calledMethod == NULL) {
         LOGV("+++ DexOpt inline: can't find %d\n", methodIdx);
         return false;
diff --git a/vm/analysis/DexOptimize.h b/vm/analysis/DexOptimize.h
index 4b6ab6b..27ab327 100644
--- a/vm/analysis/DexOptimize.h
+++ b/vm/analysis/DexOptimize.h
@@ -37,6 +37,22 @@
 };
 
 /*
+ * An enumeration of problems that can turn up during verification.
+ */
+typedef enum VerifyError {
+    VERIFY_ERROR_NONE = 0,      /* no error; must be zero */
+    VERIFY_ERROR_GENERIC,       /* failed, details not important */
+
+    VERIFY_ERROR_NO_CLASS,      /* NoClassDefFoundError */
+    VERIFY_ERROR_NO_METHOD,     /* NoSuchMethodError */
+    VERIFY_ERROR_NO_FIELD,      /* NoSuchFieldError */
+    VERIFY_ERROR_CLASS_CHANGE,  /* IncompatibleClassChangeError */
+    VERIFY_ERROR_ACCESS,        /* IllegalAccessError */
+} VerifyError;
+
+#define VERIFY_OK(_failure) ((_failure) == VERIFY_ERROR_NONE)
+
+/*
  * Given the full path to a DEX or Jar file, and (if appropriate) the name
  * within the Jar, open the optimized version from the cache.
  *
@@ -82,11 +98,14 @@
  * Abbreviated resolution functions, for use by optimization and verification
  * code.
  */
-ClassObject* dvmOptResolveClass(ClassObject* referrer, u4 classIdx);
+ClassObject* dvmOptResolveClass(ClassObject* referrer, u4 classIdx,
+    VerifyError* pFailure);
 Method* dvmOptResolveMethod(ClassObject* referrer, u4 methodIdx,
-        MethodType methodType);
+    MethodType methodType, VerifyError* pFailure);
 Method* dvmOptResolveInterfaceMethod(ClassObject* referrer, u4 methodIdx);
-InstField* dvmOptResolveInstField(ClassObject* referrer, u4 ifieldIdx);
-StaticField* dvmOptResolveStaticField(ClassObject* referrer, u4 sfieldIdx);
+InstField* dvmOptResolveInstField(ClassObject* referrer, u4 ifieldIdx,
+    VerifyError* pFailure);
+StaticField* dvmOptResolveStaticField(ClassObject* referrer, u4 sfieldIdx,
+    VerifyError* pFailure);
 
 #endif /*_DALVIK_DEXOPTIMIZE*/