Support for unresolved types in new-instance during verification.

Also, ensure that classes that don't load are erroneous, warn early
about exceptions left on a thread by the verifier/compiler, factor out
slowpath checks for the compiler and fix the slowpath selector for
const-class.

This change causes more dex cache misses at runtime (more slowpath
execution). It also requires a "mm clean-oat".

Change-Id: I014b49ebdd7d8f7dd2e39cc0958fc0b708d58c4c
diff --git a/src/class_linker.cc b/src/class_linker.cc
index f49f546..8f4029a 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1039,6 +1039,7 @@
   if (!LoadSuperAndInterfaces(klass, dex_file)) {
     // Loading failed.
     CHECK(self->IsExceptionPending());
+    klass->SetStatus(Class::kStatusError);
     lock.NotifyAll();
     return NULL;
   }
@@ -1048,6 +1049,7 @@
   if (!LinkClass(klass)) {
     // Linking failed.
     CHECK(self->IsExceptionPending());
+    klass->SetStatus(Class::kStatusError);
     lock.NotifyAll();
     return NULL;
   }
diff --git a/src/compiler.cc b/src/compiler.cc
index cbfd35c..ba61b4d 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -333,6 +333,9 @@
   // TODO: this fails if we have an abstract method defined in more than one input dex file.
   CHECK(compiled_invoke_stubs_.find(method) == compiled_invoke_stubs_.end()) << PrettyMethod(method);
   compiled_invoke_stubs_[method] = compiled_invoke_stub;
+
+  Thread* self = Thread::Current();
+  CHECK(!self->IsExceptionPending()) << PrettyMethod(method);
 }
 
 const CompiledMethod* Compiler::GetCompiledMethod(const Method* method) const {
diff --git a/src/compiler.h b/src/compiler.h
index 0fc68df..55bab59 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -55,6 +55,21 @@
   const CompiledMethod* GetCompiledMethod(const Method* method) const;
   const CompiledInvokeStub* GetCompiledInvokeStub(const Method* method) const;
 
+  // Callbacks from OAT/ART compiler to see what runtime checks must be generated
+  bool CanAssumeTypeIsPresentInDexCache(const Method* referrer, uint32_t type_idx) const {
+    return IsImage() && referrer->GetDexCacheResolvedTypes()->Get(type_idx) != NULL;
+  }
+  bool CanAssumeStringIsPresentInDexCache(const Method* referrer, uint32_t string_idx) const {
+    return IsImage() && referrer->GetDexCacheStrings()->Get(string_idx) != NULL;
+  }
+  bool CanAccessTypeWithoutChecks(const Method* referrer, uint32_t type_idx) const {
+    Class* resolved_class = referrer->GetDexCacheResolvedTypes()->Get(type_idx);
+    // We should never ask whether a type needs access checks to raise a verification error,
+    // all other cases where this following test could fail should have been rewritten by the
+    // verifier to verification errors.
+    DCHECK(resolved_class == NULL || referrer->GetDeclaringClass()->CanAccess(resolved_class));
+    return resolved_class != NULL;
+  }
  private:
   // Attempt to resolve all type, methods, fields, and strings
   // referenced from code in the dex file following PathClassLoader
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index 7ea7d69..4326a9e 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -46,10 +46,19 @@
                         RegLocation rlSrc)
 {
     oatFlushAllRegs(cUnit);    /* Everything to home location */
-    loadWordDisp(cUnit, rSELF,
-                 OFFSETOF_MEMBER(Thread, pAllocArrayFromCode), rLR);
+    uint32_t type_idx = mir->dalvikInsn.vC;
+    if (cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method, type_idx)) {
+        loadWordDisp(cUnit, rSELF,
+                     OFFSETOF_MEMBER(Thread, pAllocArrayFromCode), rLR);
+    } else {
+        UNIMPLEMENTED(WARNING) << "Need to check access of '"
+                               << PrettyMethod(cUnit->method)
+                               << "' to unresolved type " << type_idx;
+        loadWordDisp(cUnit, rSELF,
+                     OFFSETOF_MEMBER(Thread, pAllocArrayFromCode), rLR);
+    }
     loadCurrMethodDirect(cUnit, r1);              // arg1 <- Method*
-    loadConstant(cUnit, r0, mir->dalvikInsn.vC);  // arg0 <- type_id
+    loadConstant(cUnit, r0, type_idx);            // arg0 <- type_id
     loadValueDirectFixed(cUnit, rlSrc, r2);       // arg2 <- count
     callRuntimeHelper(cUnit, rLR);
     RegLocation rlResult = oatGetReturn(cUnit);
@@ -70,6 +79,10 @@
     oatFlushAllRegs(cUnit);    /* Everything to home location */
     loadWordDisp(cUnit, rSELF,
                  OFFSETOF_MEMBER(Thread, pCheckAndAllocArrayFromCode), rLR);
+    if (!cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method, typeId)) {
+        UNIMPLEMENTED(WARNING) << "Need to check access of '" << PrettyMethod(cUnit->method)
+                               << "' to unresolved type " << typeId;
+    }
     loadCurrMethodDirect(cUnit, r1);              // arg1 <- Method*
     loadConstant(cUnit, r0, typeId);              // arg0 <- type_id
     loadConstant(cUnit, r2, elems);               // arg2 <- count
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index 7098188..4e3888d 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -442,7 +442,7 @@
     loadWordDisp(cUnit, rSELF,
                  OFFSETOF_MEMBER(Thread, pFindInstanceFieldFromCode), rLR);
     loadConstant(cUnit, r0, fieldIdx);
-    callRuntimeHelper(cUnit, rLR);  // resolveTypeFromCode(idx, method)
+    callRuntimeHelper(cUnit, rLR);  // FindInstanceFieldFromCoderesolveTypeFromCode(idx, method)
     ArmLIR* target = newLIR0(cUnit, kArmPseudoTargetLabel);
     target->defMask = ENCODE_ALL;
     if (!EXERCISE_SLOWEST_FIELD_PATH) {
@@ -606,42 +606,46 @@
 STATIC void genConstClass(CompilationUnit* cUnit, MIR* mir,
                           RegLocation rlDest, RegLocation rlSrc)
 {
-    art::Class* classPtr = cUnit->method->GetDexCacheResolvedTypes()->
-        Get(mir->dalvikInsn.vB);
+    uint32_t type_idx = mir->dalvikInsn.vB;
     int mReg = loadCurrMethod(cUnit);
     int resReg = oatAllocTemp(cUnit);
     RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
-    loadWordDisp(cUnit, mReg, Method::DexCacheResolvedTypesOffset().Int32Value(),
-                 resReg);
-    loadWordDisp(cUnit, resReg, Array::DataOffset().Int32Value() +
-                 (sizeof(String*) * mir->dalvikInsn.vB), rlResult.lowReg);
-    if (SLOW_TYPE_PATH || (classPtr == NULL)) {
-        // Fast path, we're done - just store result
-        storeValue(cUnit, rlDest, rlResult);
+    if (!cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method, type_idx)) {
+        // Check we have access to type_idx and if not throw IllegalAccessError
+        UNIMPLEMENTED(FATAL);
     } else {
-        // Slow path.  Must test at runtime
-        oatFlushAllRegs(cUnit);
-        ArmLIR* branch1 = genCmpImmBranch(cUnit, kArmCondEq, rlResult.lowReg,
-                                          0);
-        // Resolved, store and hop over following code
-        storeValue(cUnit, rlDest, rlResult);
-        ArmLIR* branch2 = genUnconditionalBranch(cUnit,0);
-        // TUNING: move slow path to end & remove unconditional branch
-        ArmLIR* target1 = newLIR0(cUnit, kArmPseudoTargetLabel);
-        target1->defMask = ENCODE_ALL;
-        // Call out to helper, which will return resolved type in r0
-        loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pInitializeTypeFromCode), rLR);
-        genRegCopy(cUnit, r1, mReg);
-        loadConstant(cUnit, r0, mir->dalvikInsn.vB);
-        callRuntimeHelper(cUnit, rLR);
-        RegLocation rlResult = oatGetReturn(cUnit);
-        storeValue(cUnit, rlDest, rlResult);
-        // Rejoin code paths
-        ArmLIR* target2 = newLIR0(cUnit, kArmPseudoTargetLabel);
-        target2->defMask = ENCODE_ALL;
-        branch1->generic.target = (LIR*)target1;
-        branch2->generic.target = (LIR*)target2;
+        // We're don't need access checks, load type from dex cache
+        int32_t dex_cache_offset = Method::DexCacheResolvedTypesOffset().Int32Value();
+        loadWordDisp(cUnit, mReg, dex_cache_offset, resReg);
+        int32_t offset_of_type = Array::DataOffset().Int32Value() + (sizeof(Class*) * type_idx);
+        loadWordDisp(cUnit, resReg, offset_of_type, rlResult.lowReg);
+        if (!cUnit->compiler->CanAssumeTypeIsPresentInDexCache(cUnit->method, type_idx) ||
+            SLOW_TYPE_PATH) {
+            // Slow path, at runtime test if the type is null and if so initialize
+            oatFlushAllRegs(cUnit);
+            ArmLIR* branch1 = genCmpImmBranch(cUnit, kArmCondEq, rlResult.lowReg, 0);
+            // Resolved, store and hop over following code
+            storeValue(cUnit, rlDest, rlResult);
+            ArmLIR* branch2 = genUnconditionalBranch(cUnit,0);
+            // TUNING: move slow path to end & remove unconditional branch
+            ArmLIR* target1 = newLIR0(cUnit, kArmPseudoTargetLabel);
+            target1->defMask = ENCODE_ALL;
+            // Call out to helper, which will return resolved type in r0
+            loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pInitializeTypeFromCode), rLR);
+            genRegCopy(cUnit, r1, mReg);
+            loadConstant(cUnit, r0, type_idx);
+            callRuntimeHelper(cUnit, rLR);
+            RegLocation rlResult = oatGetReturn(cUnit);
+            storeValue(cUnit, rlDest, rlResult);
+            // Rejoin code paths
+            ArmLIR* target2 = newLIR0(cUnit, kArmPseudoTargetLabel);
+            target2->defMask = ENCODE_ALL;
+            branch1->generic.target = (LIR*)target1;
+            branch2->generic.target = (LIR*)target2;
+        } else {
+            // Fast path, we're done - just store result
+            storeValue(cUnit, rlDest, rlResult);
+        }
     }
 }
 
@@ -649,20 +653,19 @@
                            RegLocation rlDest, RegLocation rlSrc)
 {
     /* NOTE: Most strings should be available at compile time */
-    const art::String* str = cUnit->method->GetDexCacheStrings()->
-        Get(mir->dalvikInsn.vB);
-    if (SLOW_STRING_PATH || (str == NULL) || !cUnit->compiler->IsImage()) {
+    uint32_t string_idx = mir->dalvikInsn.vB;
+    int32_t offset_of_string = Array::DataOffset().Int32Value() + (sizeof(String*) * string_idx);
+    if (!cUnit->compiler->CanAssumeStringIsPresentInDexCache(cUnit->method, string_idx) ||
+        SLOW_STRING_PATH) {
+        // slow path, resolve string if not in dex cache
         oatFlushAllRegs(cUnit);
         oatLockCallTemps(cUnit); // Using explicit registers
         loadCurrMethodDirect(cUnit, r2);
-        loadWordDisp(cUnit, r2, Method::DexCacheStringsOffset().Int32Value(),
-                     r0);
+        loadWordDisp(cUnit, r2, Method::DexCacheStringsOffset().Int32Value(), r0);
         // Might call out to helper, which will return resolved string in r0
-        loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pResolveStringFromCode), rLR);
-        loadWordDisp(cUnit, r0, Array::DataOffset().Int32Value() +
-                 (sizeof(String*) * mir->dalvikInsn.vB), r0);
-        loadConstant(cUnit, r1, mir->dalvikInsn.vB);
+        loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pResolveStringFromCode), rLR);
+        loadWordDisp(cUnit, r0, offset_of_string, r0);
+        loadConstant(cUnit, r1, string_idx);
         opRegImm(cUnit, kOpCmp, r0, 0);  // Is resolved?
         genBarrier(cUnit);
         // For testing, always force through helper
@@ -677,10 +680,8 @@
         int mReg = loadCurrMethod(cUnit);
         int resReg = oatAllocTemp(cUnit);
         RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
-        loadWordDisp(cUnit, mReg, Method::DexCacheStringsOffset().Int32Value(),
-                     resReg);
-        loadWordDisp(cUnit, resReg, Array::DataOffset().Int32Value() +
-                    (sizeof(String*) * mir->dalvikInsn.vB), rlResult.lowReg);
+        loadWordDisp(cUnit, mReg, Method::DexCacheStringsOffset().Int32Value(), resReg);
+        loadWordDisp(cUnit, resReg, offset_of_string, rlResult.lowReg);
         storeValue(cUnit, rlDest, rlResult);
     }
 }
@@ -693,13 +694,17 @@
                            RegLocation rlDest)
 {
     oatFlushAllRegs(cUnit);    /* Everything to home location */
-    art::Class* classPtr = cUnit->method->GetDexCacheResolvedTypes()->
-        Get(mir->dalvikInsn.vB);
-    loadWordDisp(cUnit, rSELF, (classPtr != NULL)
-                 ? OFFSETOF_MEMBER(Thread, pAllocObjectFromCode)
-                 : OFFSETOF_MEMBER(Thread, pAllocObjectFromCodeSlowPath), rLR);
-    loadCurrMethodDirect(cUnit, r1);              // arg1 <= Method*
-    loadConstant(cUnit, r0, mir->dalvikInsn.vB);  // arg0 <- type_id
+    uint32_t type_idx = mir->dalvikInsn.vB;
+    // alloc will always check for resolution, do we also need to verify access because the
+    // verifier was unable to?
+    if (cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method, type_idx)) {
+        loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pAllocObjectFromCode), rLR);
+    } else {
+        loadWordDisp(cUnit, rSELF,
+                     OFFSETOF_MEMBER(Thread, pAllocObjectFromCodeWithAccessCheck), rLR);
+    }
+    loadCurrMethodDirect(cUnit, r1);    // arg1 <= Method*
+    loadConstant(cUnit, r0, type_idx);  // arg0 <- type_idx
     callRuntimeHelper(cUnit, rLR);
     RegLocation rlResult = oatGetReturn(cUnit);
     storeValue(cUnit, rlDest, rlResult);
@@ -708,8 +713,7 @@
 void genThrow(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
 {
     oatFlushAllRegs(cUnit);
-    loadWordDisp(cUnit, rSELF,
-                 OFFSETOF_MEMBER(Thread, pDeliverException), rLR);
+    loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pDeliverException), rLR);
     loadValueDirectFixed(cUnit, rlSrc, r0);  // Get exception object
     callRuntimeHelper(cUnit, rLR);  // art_deliver_exception(exception);
 }
@@ -720,30 +724,33 @@
     oatFlushAllRegs(cUnit);
     // May generate a call - use explicit registers
     oatLockCallTemps(cUnit);
-    art::Class* classPtr = cUnit->method->GetDexCacheResolvedTypes()->
-        Get(mir->dalvikInsn.vC);
-    int classReg = r2;   // Fixed usage
+    uint32_t type_idx = mir->dalvikInsn.vC;
     loadCurrMethodDirect(cUnit, r1);  // r1 <= current Method*
-    loadValueDirectFixed(cUnit, rlSrc, r0);  /* Ref */
-    loadWordDisp(cUnit, r1, Method::DexCacheResolvedTypesOffset().Int32Value(),
-                 classReg);
-    loadWordDisp(cUnit, classReg, Array::DataOffset().Int32Value() +
-                 (sizeof(String*) * mir->dalvikInsn.vC), classReg);
-    if (classPtr == NULL) {
-        // Generate a runtime test
-        ArmLIR* hopBranch = genCmpImmBranch(cUnit, kArmCondNe, classReg, 0);
-        // Not resolved
-        // Call out to helper, which will return resolved type in r0
-        loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pInitializeTypeFromCode), rLR);
-        loadConstant(cUnit, r0, mir->dalvikInsn.vC);
-        callRuntimeHelper(cUnit, rLR);  // resolveTypeFromCode(idx, method)
-        genRegCopy(cUnit, r2, r0); // Align usage with fast path
-        loadValueDirectFixed(cUnit, rlSrc, r0);  /* reload Ref */
-        // Rejoin code paths
-        ArmLIR* hopTarget = newLIR0(cUnit, kArmPseudoTargetLabel);
-        hopTarget->defMask = ENCODE_ALL;
-        hopBranch->generic.target = (LIR*)hopTarget;
+    loadValueDirectFixed(cUnit, rlSrc, r0);  // r0 <= ref
+    int classReg = r2;  // r2 will hold the Class*
+    if (!cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method, type_idx)) {
+        // Check we have access to type_idx and if not throw IllegalAccessError
+        UNIMPLEMENTED(FATAL);
+    } else {
+        // Load dex cache entry into classReg (r2)
+        loadWordDisp(cUnit, r1, Method::DexCacheResolvedTypesOffset().Int32Value(), classReg);
+        int32_t offset_of_type = Array::DataOffset().Int32Value() + (sizeof(Class*) * type_idx);
+        loadWordDisp(cUnit, classReg, offset_of_type, classReg);
+        if (!cUnit->compiler->CanAssumeTypeIsPresentInDexCache(cUnit->method, type_idx)) {
+            // Need to test presence of type in dex cache at runtime
+            ArmLIR* hopBranch = genCmpImmBranch(cUnit, kArmCondNe, classReg, 0);
+            // Not resolved
+            // Call out to helper, which will return resolved type in r0
+            loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pInitializeTypeFromCode), rLR);
+            loadConstant(cUnit, r0, type_idx);
+            callRuntimeHelper(cUnit, rLR);  // resolveTypeFromCode(idx, method)
+            genRegCopy(cUnit, r2, r0); // Align usage with fast path
+            loadValueDirectFixed(cUnit, rlSrc, r0);  /* reload Ref */
+            // Rejoin code paths
+            ArmLIR* hopTarget = newLIR0(cUnit, kArmPseudoTargetLabel);
+            hopTarget->defMask = ENCODE_ALL;
+            hopBranch->generic.target = (LIR*)hopTarget;
+        }
     }
     /* r0 is ref, r2 is class.  If ref==null, use directly as bool result */
     ArmLIR* branch1 = genCmpImmBranch(cUnit, kArmCondEq, r0, 0);
@@ -751,8 +758,7 @@
     DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
     loadWordDisp(cUnit, r0,  Object::ClassOffset().Int32Value(), r1);
     /* r0 is ref, r1 is ref->clazz, r2 is class */
-    loadWordDisp(cUnit, rSELF,
-                 OFFSETOF_MEMBER(Thread, pInstanceofNonTrivialFromCode), rLR);
+    loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pInstanceofNonTrivialFromCode), rLR);
     opRegReg(cUnit, kOpCmp, r1, r2);  // Same?
     genBarrier(cUnit);
     genIT(cUnit, kArmCondEq, "EE");   // if-convert the test
@@ -774,39 +780,41 @@
     oatFlushAllRegs(cUnit);
     // May generate a call - use explicit registers
     oatLockCallTemps(cUnit);
-    art::Class* classPtr = cUnit->method->GetDexCacheResolvedTypes()->
-        Get(mir->dalvikInsn.vB);
-    int classReg = r2;   // Fixed usage
+    uint32_t type_idx = mir->dalvikInsn.vB;
     loadCurrMethodDirect(cUnit, r1);  // r1 <= current Method*
-    loadWordDisp(cUnit, r1, Method::DexCacheResolvedTypesOffset().Int32Value(),
-                 classReg);
-    loadWordDisp(cUnit, classReg, Array::DataOffset().Int32Value() +
-                 (sizeof(String*) * mir->dalvikInsn.vB), classReg);
-    if (classPtr == NULL) {
-        // Generate a runtime test
-        ArmLIR* hopBranch = genCmpImmBranch(cUnit, kArmCondNe, classReg, 0);
-        // Not resolved
-        // Call out to helper, which will return resolved type in r0
-        loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pInitializeTypeFromCode), rLR);
-        loadConstant(cUnit, r0, mir->dalvikInsn.vB);
-        callRuntimeHelper(cUnit, rLR);  // resolveTypeFromCode(idx, method)
-        genRegCopy(cUnit, r2, r0); // Align usage with fast path
-        // Rejoin code paths
-        ArmLIR* hopTarget = newLIR0(cUnit, kArmPseudoTargetLabel);
-        hopTarget->defMask = ENCODE_ALL;
-        hopBranch->generic.target = (LIR*)hopTarget;
+    int classReg = r2;  // r2 will hold the Class*
+    if (!cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method, type_idx)) {
+        // Check we have access to type_idx and if not throw IllegalAccessError
+        UNIMPLEMENTED(FATAL);
+    } else {
+        // Load dex cache entry into classReg (r2)
+        loadWordDisp(cUnit, r1, Method::DexCacheResolvedTypesOffset().Int32Value(), classReg);
+        int32_t offset_of_type = Array::DataOffset().Int32Value() + (sizeof(Class*) * type_idx);
+        loadWordDisp(cUnit, classReg, offset_of_type, classReg);
+        if (!cUnit->compiler->CanAssumeTypeIsPresentInDexCache(cUnit->method, type_idx)) {
+            // Need to test presence of type in dex cache at runtime
+            ArmLIR* hopBranch = genCmpImmBranch(cUnit, kArmCondNe, classReg, 0);
+            // Not resolved
+            // Call out to helper, which will return resolved type in r0
+            loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pInitializeTypeFromCode), rLR);
+            loadConstant(cUnit, r0, type_idx);
+            callRuntimeHelper(cUnit, rLR);  // resolveTypeFromCode(idx, method)
+            genRegCopy(cUnit, r2, r0); // Align usage with fast path
+            // Rejoin code paths
+            ArmLIR* hopTarget = newLIR0(cUnit, kArmPseudoTargetLabel);
+            hopTarget->defMask = ENCODE_ALL;
+            hopBranch->generic.target = (LIR*)hopTarget;
+        }
     }
-    // At this point, r2 has class
-    loadValueDirectFixed(cUnit, rlSrc, r0);  /* Ref */
+    // At this point, classReg (r2) has class
+    loadValueDirectFixed(cUnit, rlSrc, r0);  // r0 <= ref
     /* Null is OK - continue */
     ArmLIR* branch1 = genCmpImmBranch(cUnit, kArmCondEq, r0, 0);
     /* load object->clazz */
     DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
     loadWordDisp(cUnit, r0,  Object::ClassOffset().Int32Value(), r1);
     /* r1 now contains object->clazz */
-    loadWordDisp(cUnit, rSELF,
-                 OFFSETOF_MEMBER(Thread, pCheckCastFromCode), rLR);
+    loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pCheckCastFromCode), rLR);
     opRegReg(cUnit, kOpCmp, r1, r2);
     ArmLIR* branch2 = opCondBranch(cUnit, kArmCondEq); /* If equal, trivial yes */
     genRegCopy(cUnit, r0, r1);
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index 79a455e..79f90e7 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -43,7 +43,7 @@
     "Unresolved Reference",
     "Uninitialized Reference",
     "Uninitialized This Reference",
-    "Unresolved And Uninitialized This Reference",
+    "Unresolved And Uninitialized Reference",
     "Reference",
 };
 
@@ -65,7 +65,7 @@
     result = type_strings[type_];
     if (IsReferenceTypes()) {
       result += ": ";
-      if (IsUnresolvedReference()) {
+      if (IsUnresolvedTypes()) {
         result += PrettyDescriptor(GetDescriptor());
       } else {
         result += PrettyDescriptor(GetClass()->GetDescriptor());
@@ -370,15 +370,23 @@
       entries_.push_back(entry);
       return *entry;
     } else {
+      // TODO: we assume unresolved, but we may be able to do better by validating whether the
+      // descriptor string is valid
       // Unable to resolve so create unresolved register type
       DCHECK(Thread::Current()->IsExceptionPending());
       Thread::Current()->ClearException();
-      String* string_descriptor =
-          Runtime::Current()->GetInternTable()->InternStrong(descriptor.c_str());
-      RegType* entry = new RegType(RegType::kRegTypeUnresolvedReference, string_descriptor, 0,
-                                   entries_.size());
-      entries_.push_back(entry);
-      return *entry;
+      if (IsValidDescriptor(descriptor.c_str())) {
+        String* string_descriptor =
+            Runtime::Current()->GetInternTable()->InternStrong(descriptor.c_str());
+        RegType* entry = new RegType(RegType::kRegTypeUnresolvedReference, string_descriptor, 0,
+                                     entries_.size());
+        entries_.push_back(entry);
+        return *entry;
+      } else {
+        // The descriptor is broken return the unknown type as there's nothing sensible that
+        // could be done at runtime
+        return Unknown();
+      }
     }
   }
 }
@@ -407,15 +415,58 @@
   }
 }
 
-const RegType& RegTypeCache::Uninitialized(Class* klass, uint32_t allocation_pc) {
-  for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
-    RegType* cur_entry = entries_[i];
-    if (cur_entry->IsUninitializedReference() && cur_entry->GetAllocationPc() == allocation_pc &&
-        cur_entry->GetClass() == klass) {
-      return *cur_entry;
+const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) {
+  RegType* entry;
+  if (type.IsUnresolvedTypes()) {
+    String* descriptor = type.GetDescriptor();
+    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+      RegType* cur_entry = entries_[i];
+      if (cur_entry->IsUnresolvedAndUninitializedReference() &&
+          cur_entry->GetAllocationPc() == allocation_pc &&
+          cur_entry->GetDescriptor() == descriptor) {
+        return *cur_entry;
+      }
     }
+    entry = new RegType(RegType::kRegTypeUnresolvedAndUninitializedReference,
+                        descriptor, allocation_pc, entries_.size());
+  } else {
+    Class* klass = type.GetClass();
+    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+      RegType* cur_entry = entries_[i];
+      if (cur_entry->IsUninitializedReference() &&
+          cur_entry->GetAllocationPc() == allocation_pc &&
+          cur_entry->GetClass() == klass) {
+        return *cur_entry;
+      }
+    }
+    entry = new RegType(RegType::kRegTypeUninitializedReference,
+                        klass, allocation_pc, entries_.size());
   }
-  RegType* entry = new RegType(RegType::kRegTypeUninitializedReference, klass, allocation_pc, entries_.size());
+  entries_.push_back(entry);
+  return *entry;
+}
+
+const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) {
+  RegType* entry;
+  if (uninit_type.IsUnresolvedTypes()) {
+    String* descriptor = uninit_type.GetDescriptor();
+    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+      RegType* cur_entry = entries_[i];
+      if (cur_entry->IsUnresolvedReference() && cur_entry->GetDescriptor() == descriptor) {
+        return *cur_entry;
+      }
+    }
+    entry = new RegType(RegType::kRegTypeUnresolvedReference, descriptor, 0, entries_.size());
+  } else {
+    Class* klass = uninit_type.GetClass();
+    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+      RegType* cur_entry = entries_[i];
+      if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
+        return *cur_entry;
+      }
+    }
+    entry = new RegType(RegType::kRegTypeReference, klass, 0, entries_.size());
+  }
   entries_.push_back(entry);
   return *entry;
 }
@@ -462,6 +513,18 @@
   return *entry;
 }
 
+const RegType& RegTypeCache::GetComponentType(const RegType& array, const ClassLoader* loader) {
+  CHECK(array.IsArrayClass());
+  if (array.IsUnresolvedTypes()) {
+    std::string descriptor = array.GetDescriptor()->ToModifiedUtf8();
+    std::string component = descriptor.substr(1, descriptor.size() - 1);
+    return FromDescriptor(loader, component);
+  } else {
+    return FromClass(array.GetClass()->GetComponentType());
+  }
+}
+
+
 bool RegisterLine::CheckConstructorReturn() const {
   for (size_t i = 0; i < num_regs_; i++) {
     if (GetRegisterType(i).IsUninitializedThisReference()) {
@@ -561,20 +624,16 @@
 }
 
 void RegisterLine::MarkRefsAsInitialized(const RegType& uninit_type) {
-  Class* klass = uninit_type.GetClass();
-  if (klass == NULL) {
-    verifier_->Fail(VERIFY_ERROR_GENERIC) << "Unable to find type=" << uninit_type;
-  } else {
-    const RegType& init_type = verifier_->GetRegTypeCache()->FromClass(klass);
-    size_t changed = 0;
-    for (size_t i = 0; i < num_regs_; i++) {
-      if (GetRegisterType(i).Equals(uninit_type)) {
-        line_[i] = init_type.GetId();
-        changed++;
-      }
+  DCHECK(uninit_type.IsUninitializedTypes());
+  const RegType& init_type = verifier_->GetRegTypeCache()->FromUninitialized(uninit_type);
+  size_t changed = 0;
+  for (size_t i = 0; i < num_regs_; i++) {
+    if (GetRegisterType(i).Equals(uninit_type)) {
+      line_[i] = init_type.GetId();
+      changed++;
     }
-    DCHECK_GT(changed, 0u);
   }
+  DCHECK_GT(changed, 0u);
 }
 
 void RegisterLine::MarkUninitRefsAsInvalid(const RegType& uninit_type) {
@@ -895,8 +954,9 @@
             << verifier.info_messages_.str() << Dumpable<DexVerifier>(verifier);
 }
 
-DexVerifier::DexVerifier(Method* method) : java_lang_throwable_(NULL), work_insn_idx_(-1),
-                                           method_(method), failure_(VERIFY_ERROR_NONE),
+DexVerifier::DexVerifier(Method* method) : work_insn_idx_(-1), method_(method),
+                                           failure_(VERIFY_ERROR_NONE),
+
                                            new_instance_count_(0), monitor_enter_count_(0) {
   const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
@@ -994,15 +1054,26 @@
   /* Iterate over each of the handlers to verify target addresses. */
   const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item_, 0);
   uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
+  ClassLinker* linker = Runtime::Current()->GetClassLinker();
   for (uint32_t idx = 0; idx < handlers_size; idx++) {
     DexFile::CatchHandlerIterator iterator(handlers_ptr);
     for (; !iterator.HasNext(); iterator.Next()) {
-      uint32_t dex_pc= iterator.Get().address_;
+      const DexFile::CatchHandlerItem& handler = iterator.Get();
+      uint32_t dex_pc= handler.address_;
       if (!insn_flags_[dex_pc].IsOpcode()) {
         Fail(VERIFY_ERROR_GENERIC) << "exception handler starts at bad address (" << dex_pc << ")";
         return false;
       }
       insn_flags_[dex_pc].SetBranchTarget();
+      // Ensure exception types are resolved so that they don't need resolution to be delivered,
+      // unresolved exception types will be ignored by exception delivery
+      if (handler.type_idx_ != DexFile::kDexNoIndex) {
+        Class* exception_type = linker->ResolveType(handler.type_idx_, method_);
+        if (exception_type == NULL) {
+          DCHECK(Thread::Current()->IsExceptionPending());
+          Thread::Current()->ClearException();
+        }
+      }
     }
     handlers_ptr = iterator.GetData();
   }
@@ -1814,12 +1885,8 @@
        * all exception handlers need to have one of these). We verify that as part of extracting the
        * exception type from the catch block list.
        */
-      Class* res_class = GetCaughtExceptionType();
-      if (res_class == NULL) {
-        DCHECK(failure_ != VERIFY_ERROR_NONE);
-      } else {
-        work_line_->SetRegisterType(dec_insn.vA_, reg_types_.FromClass(res_class));
-      }
+      const RegType& res_type = GetCaughtExceptionType();
+      work_line_->SetRegisterType(dec_insn.vA_, res_type);
       break;
     }
     case Instruction::RETURN_VOID:
@@ -1911,17 +1978,12 @@
       work_line_->SetRegisterType(dec_insn.vA_, reg_types_.JavaLangString());
       break;
     case Instruction::CONST_CLASS: {
-      /* make sure we can resolve the class; access check is important */
-      Class* res_class = ResolveClassAndCheckAccess(dec_insn.vB_);
-      if (res_class == NULL) {
-        const char* bad_class_desc = dex_file_->dexStringByTypeIdx(dec_insn.vB_);
-        fail_messages_ << "unable to resolve const-class " << dec_insn.vB_
-                       << " (" << bad_class_desc << ") in "
-                       << PrettyDescriptor(method_->GetDeclaringClass()->GetDescriptor());
-        DCHECK(failure_ != VERIFY_ERROR_GENERIC);
-      } else {
-        work_line_->SetRegisterType(dec_insn.vA_, reg_types_.JavaLangClass());
-      }
+      // Get type from instruction if unresolved then we need an access check
+      // TODO: check Compiler::CanAccessTypeWithoutChecks returns false when res_type is unresolved
+      const RegType& res_type = ResolveClassAndCheckAccess(dec_insn.vB_);
+      // Register holds class, ie its type is class, but on error we keep it Unknown
+      work_line_->SetRegisterType(dec_insn.vA_,
+                                  res_type.IsUnknown() ? res_type : reg_types_.JavaLangClass());
       break;
     }
     case Instruction::MONITOR_ENTER:
@@ -1952,58 +2014,39 @@
       work_line_->PopMonitor(dec_insn.vA_);
       break;
 
-    case Instruction::CHECK_CAST: {
-      /*
-       * If this instruction succeeds, we will promote register vA to
-       * the type in vB. (This could be a demotion -- not expected, so
-       * we don't try to address it.)
-       *
-       * If it fails, an exception is thrown, which we deal with later
-       * by ignoring the update to dec_insn.vA_ when branching to a handler.
-       */
-      Class* res_class = ResolveClassAndCheckAccess(dec_insn.vB_);
-      if (res_class == NULL) {
-        const char* bad_class_desc = dex_file_->dexStringByTypeIdx(dec_insn.vB_);
-        fail_messages_ << "unable to resolve check-cast " << dec_insn.vB_
-                       << " (" << bad_class_desc << ") in "
-                       << PrettyDescriptor(method_->GetDeclaringClass()->GetDescriptor());
-        DCHECK(failure_ != VERIFY_ERROR_GENERIC);
-      } else {
-        const RegType& orig_type = work_line_->GetRegisterType(dec_insn.vA_);
-        if (!orig_type.IsReferenceTypes()) {
-          Fail(VERIFY_ERROR_GENERIC) << "check-cast on non-reference in v" << dec_insn.vA_;
-        } else {
-          work_line_->SetRegisterType(dec_insn.vA_, reg_types_.FromClass(res_class));
-        }
-      }
-      break;
-    }
+    case Instruction::CHECK_CAST:
     case Instruction::INSTANCE_OF: {
-      /* make sure we're checking a reference type */
-      const RegType& tmp_type = work_line_->GetRegisterType(dec_insn.vB_);
-      if (!tmp_type.IsReferenceTypes()) {
-        Fail(VERIFY_ERROR_GENERIC) << "vB not a reference (" << tmp_type << ")";
+      /*
+       * If this instruction succeeds, we will "downcast" register vA to the type in vB. (This
+       * could be a "upcast" -- not expected, so we don't try to address it.)
+       *
+       * If it fails, an exception is thrown, which we deal with later by ignoring the update to
+       * dec_insn.vA_ when branching to a handler.
+       */
+      bool is_checkcast = dec_insn.opcode_ == Instruction::CHECK_CAST;
+      const RegType& res_type =
+          ResolveClassAndCheckAccess(is_checkcast ? dec_insn.vB_ : dec_insn.vC_);
+      // TODO: check Compiler::CanAccessTypeWithoutChecks returns false when res_type is unresolved
+      const RegType& orig_type =
+          work_line_->GetRegisterType(is_checkcast ? dec_insn.vA_ : dec_insn.vB_);
+      if (!res_type.IsNonZeroReferenceTypes()) {
+        Fail(VERIFY_ERROR_GENERIC) << "check-cast on unexpected class " << res_type;
+      } else if (!orig_type.IsReferenceTypes()) {
+        Fail(VERIFY_ERROR_GENERIC) << "check-cast on non-reference in v" << dec_insn.vA_;
       } else {
-        /* make sure we can resolve the class; access check is important */
-        Class* res_class = ResolveClassAndCheckAccess(dec_insn.vC_);
-        if (res_class == NULL) {
-          const char* bad_class_desc = dex_file_->dexStringByTypeIdx(dec_insn.vC_);
-          fail_messages_ << "unable to resolve instance of " << dec_insn.vC_
-                         << " (" << bad_class_desc << ") in "
-                         << PrettyDescriptor(method_->GetDeclaringClass()->GetDescriptor());
-          DCHECK(failure_ != VERIFY_ERROR_GENERIC);
+        if (is_checkcast) {
+          work_line_->SetRegisterType(dec_insn.vA_, res_type);
         } else {
-          /* result is boolean */
           work_line_->SetRegisterType(dec_insn.vA_, reg_types_.Boolean());
         }
       }
       break;
     }
     case Instruction::ARRAY_LENGTH: {
-      Class* res_class = work_line_->GetClassFromRegister(dec_insn.vB_);
-      if (failure_ == VERIFY_ERROR_NONE) {
-        if (res_class != NULL && !res_class->IsArrayClass()) {
-          Fail(VERIFY_ERROR_GENERIC) << "array-length on non-array";
+      const RegType& res_type = work_line_->GetRegisterType(dec_insn.vB_);
+      if (res_type.IsReferenceTypes()) {
+        if (!res_type.IsArrayClass()) {
+          Fail(VERIFY_ERROR_GENERIC) << "array-length on non-array " << res_type;
         } else {
           work_line_->SetRegisterType(dec_insn.vA_, reg_types_.Integer());
         }
@@ -2011,66 +2054,47 @@
       break;
     }
     case Instruction::NEW_INSTANCE: {
-      Class* res_class = ResolveClassAndCheckAccess(dec_insn.vB_);
-      if (res_class == NULL) {
-        const char* bad_class_desc = dex_file_->dexStringByTypeIdx(dec_insn.vB_);
-        fail_messages_ << "unable to resolve new-instance " << dec_insn.vB_
-                       << " (" << bad_class_desc << ") in "
-                       << PrettyDescriptor(method_->GetDeclaringClass()->GetDescriptor());
-        DCHECK(failure_ != VERIFY_ERROR_GENERIC);
+      const RegType& res_type = ResolveClassAndCheckAccess(dec_insn.vB_);
+      // TODO: check Compiler::CanAccessTypeWithoutChecks returns false when res_type is unresolved
+      // can't create an instance of an interface or abstract class */
+      if (!res_type.IsInstantiableTypes()) {
+        Fail(VERIFY_ERROR_INSTANTIATION)
+            << "new-instance on primitive, interface or abstract class" << res_type;
       } else {
-        /* can't create an instance of an interface or abstract class */
-        if (res_class->IsPrimitive() || res_class->IsAbstract() || res_class->IsInterface()) {
-          Fail(VERIFY_ERROR_INSTANTIATION)
-              << "new-instance on primitive, interface or abstract class"
-              << PrettyDescriptor(res_class->GetDescriptor());
-        } else {
-          const RegType& uninit_type = reg_types_.Uninitialized(res_class, work_insn_idx_);
-          // Any registers holding previous allocations from this address that have not yet been
-          // initialized must be marked invalid.
-          work_line_->MarkUninitRefsAsInvalid(uninit_type);
-
-          /* add the new uninitialized reference to the register state */
-          work_line_->SetRegisterType(dec_insn.vA_, uninit_type);
-        }
+        const RegType& uninit_type = reg_types_.Uninitialized(res_type, work_insn_idx_);
+        // Any registers holding previous allocations from this address that have not yet been
+        // initialized must be marked invalid.
+        work_line_->MarkUninitRefsAsInvalid(uninit_type);
+        // add the new uninitialized reference to the register state
+        work_line_->SetRegisterType(dec_insn.vA_, uninit_type);
       }
       break;
     }
     case Instruction::NEW_ARRAY: {
-      Class* res_class = ResolveClassAndCheckAccess(dec_insn.vC_);
-      if (res_class == NULL) {
-        const char* bad_class_desc = dex_file_->dexStringByTypeIdx(dec_insn.vC_);
-        fail_messages_ << "unable to resolve new-array " << dec_insn.vC_
-                       << " (" << bad_class_desc << ") in "
-                       << PrettyDescriptor(method_->GetDeclaringClass()->GetDescriptor());
-        DCHECK(failure_ != VERIFY_ERROR_GENERIC);
-      } else if (!res_class->IsArrayClass()) {
-        Fail(VERIFY_ERROR_GENERIC) << "new-array on non-array class";
+      const RegType& res_type = ResolveClassAndCheckAccess(dec_insn.vC_);
+      // TODO: check Compiler::CanAccessTypeWithoutChecks returns false when res_type is unresolved
+      if (!res_type.IsArrayClass()) {
+        Fail(VERIFY_ERROR_GENERIC) << "new-array on non-array class " << res_type;
       } else {
         /* make sure "size" register is valid type */
         work_line_->VerifyRegisterType(dec_insn.vB_, reg_types_.Integer());
         /* set register type to array class */
-        work_line_->SetRegisterType(dec_insn.vA_, reg_types_.FromClass(res_class));
+        work_line_->SetRegisterType(dec_insn.vA_, res_type);
       }
       break;
     }
     case Instruction::FILLED_NEW_ARRAY:
     case Instruction::FILLED_NEW_ARRAY_RANGE: {
-      Class* res_class = ResolveClassAndCheckAccess(dec_insn.vB_);
-      if (res_class == NULL) {
-        const char* bad_class_desc = dex_file_->dexStringByTypeIdx(dec_insn.vB_);
-        fail_messages_ << "unable to resolve filled-array " << dec_insn.vB_
-                       << " (" << bad_class_desc << ") in "
-                       << PrettyDescriptor(method_->GetDeclaringClass()->GetDescriptor());
-        DCHECK(failure_ != VERIFY_ERROR_GENERIC);
-      } else if (!res_class->IsArrayClass()) {
+      const RegType& res_type = ResolveClassAndCheckAccess(dec_insn.vB_);
+      // TODO: check Compiler::CanAccessTypeWithoutChecks returns false when res_type is unresolved
+      if (!res_type.IsArrayClass()) {
         Fail(VERIFY_ERROR_GENERIC) << "filled-new-array on non-array class";
       } else {
         bool is_range = (dec_insn.opcode_ == Instruction::FILLED_NEW_ARRAY_RANGE);
         /* check the arguments to the instruction */
-        VerifyFilledNewArrayRegs(dec_insn, res_class, is_range);
+        VerifyFilledNewArrayRegs(dec_insn, res_type, is_range);
         /* filled-array result goes into "result" register */
-        work_line_->SetResultRegisterType(reg_types_.FromClass(res_class));
+        work_line_->SetResultRegisterType(res_type);
         just_set_result = true;
       }
       break;
@@ -2093,12 +2117,9 @@
       work_line_->SetRegisterType(dec_insn.vA_, reg_types_.Integer());
       break;
     case Instruction::THROW: {
-      Class* res_class = work_line_->GetClassFromRegister(dec_insn.vA_);
-      if (failure_ == VERIFY_ERROR_NONE && res_class != NULL) {
-        if (!JavaLangThrowable()->IsAssignableFrom(res_class)) {
-          Fail(VERIFY_ERROR_GENERIC) << "thrown class "
-              << PrettyDescriptor(res_class->GetDescriptor()) << " not instanceof Throwable";
-        }
+      const RegType& res_type = work_line_->GetRegisterType(dec_insn.vA_);
+      if (!reg_types_.JavaLangThrowable().IsAssignableFrom(res_type)) {
+        Fail(VERIFY_ERROR_GENERIC) << "thrown class " << res_type << " not instanceof Throwable";
       }
       break;
     }
@@ -2338,9 +2359,17 @@
                         dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);
       Method* called_method = VerifyInvocationArgs(dec_insn, METHOD_VIRTUAL, is_range, is_super);
       if (failure_ == VERIFY_ERROR_NONE) {
+        const char* descriptor;
+        if (called_method == NULL) {
+          uint32_t method_idx = dec_insn.vB_;
+          const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
+          uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
+          descriptor =  dex_file_->dexStringByTypeIdx(return_type_idx);
+        } else {
+          descriptor = called_method->GetReturnTypeDescriptor();
+        }
         const RegType& return_type =
-            reg_types_.FromDescriptor(called_method->GetDeclaringClass()->GetClassLoader(),
-                                      called_method->GetReturnTypeDescriptor());
+            reg_types_.FromDescriptor(method_->GetDeclaringClass()->GetClassLoader(), descriptor);
         work_line_->SetResultRegisterType(return_type);
         just_set_result = true;
       }
@@ -2358,7 +2387,16 @@
          * allowing the latter only if the "this" argument is the same as the "this" argument to
          * this method (which implies that we're in a constructor ourselves).
          */
-        if (called_method->IsConstructor()) {
+        bool is_constructor;
+        if (called_method != NULL) {
+          is_constructor = called_method->IsConstructor();
+        } else {
+          uint32_t method_idx = dec_insn.vB_;
+          const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
+          const char* name = dex_file_->GetMethodName(method_id);
+          is_constructor = strcmp(name, "<init>") == 0;
+        }
+        if (is_constructor) {
           const RegType& this_type = work_line_->GetInvocationThis(dec_insn);
           if (failure_ != VERIFY_ERROR_NONE)
             break;
@@ -2368,19 +2406,20 @@
             Fail(VERIFY_ERROR_GENERIC) << "unable to initialize null ref";
             break;
           }
-          Class* this_class = this_type.GetClass();
-          DCHECK(this_class != NULL);
-
-          /* must be in same class or in superclass */
-          if (called_method->GetDeclaringClass() == this_class->GetSuperClass()) {
-            if (this_class != method_->GetDeclaringClass()) {
-              Fail(VERIFY_ERROR_GENERIC)
-                  << "invoke-direct <init> on super only allowed for 'this' in <init>";
+          if (called_method != NULL) {
+            Class* this_class = this_type.GetClass();
+            DCHECK(this_class != NULL);
+            /* must be in same class or in superclass */
+            if (called_method->GetDeclaringClass() == this_class->GetSuperClass()) {
+              if (this_class != method_->GetDeclaringClass()) {
+                Fail(VERIFY_ERROR_GENERIC)
+                    << "invoke-direct <init> on super only allowed for 'this' in <init>";
+                break;
+              }
+            }  else if (called_method->GetDeclaringClass() != this_class) {
+              Fail(VERIFY_ERROR_GENERIC) << "invoke-direct <init> must be on current class or super";
               break;
             }
-          }  else if (called_method->GetDeclaringClass() != this_class) {
-            Fail(VERIFY_ERROR_GENERIC) << "invoke-direct <init> must be on current class or super";
-            break;
           }
 
           /* arg must be an uninitialized reference */
@@ -2398,9 +2437,17 @@
           if (failure_ != VERIFY_ERROR_NONE)
             break;
         }
+        const char* descriptor;
+        if (called_method == NULL) {
+          uint32_t method_idx = dec_insn.vB_;
+          const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
+          uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
+          descriptor =  dex_file_->dexStringByTypeIdx(return_type_idx);
+        } else {
+          descriptor = called_method->GetReturnTypeDescriptor();
+        }
         const RegType& return_type =
-            reg_types_.FromDescriptor(called_method->GetDeclaringClass()->GetClassLoader(),
-                                      called_method->GetReturnTypeDescriptor());
+            reg_types_.FromDescriptor(method_->GetDeclaringClass()->GetClassLoader(), descriptor);
         work_line_->SetResultRegisterType(return_type);
         just_set_result = true;
       }
@@ -2411,9 +2458,17 @@
         bool is_range = (dec_insn.opcode_ == Instruction::INVOKE_STATIC_RANGE);
         Method* called_method = VerifyInvocationArgs(dec_insn, METHOD_STATIC, is_range, false);
         if (failure_ == VERIFY_ERROR_NONE) {
+          const char* descriptor;
+          if (called_method == NULL) {
+            uint32_t method_idx = dec_insn.vB_;
+            const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
+            uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
+            descriptor =  dex_file_->dexStringByTypeIdx(return_type_idx);
+          } else {
+            descriptor = called_method->GetReturnTypeDescriptor();
+          }
           const RegType& return_type =
-              reg_types_.FromDescriptor(called_method->GetDeclaringClass()->GetClassLoader(),
-                                        called_method->GetReturnTypeDescriptor());
+              reg_types_.FromDescriptor(method_->GetDeclaringClass()->GetClassLoader(), descriptor);
           work_line_->SetResultRegisterType(return_type);
           just_set_result = true;
         }
@@ -2424,42 +2479,52 @@
       bool is_range =  (dec_insn.opcode_ == Instruction::INVOKE_INTERFACE_RANGE);
       Method* abs_method = VerifyInvocationArgs(dec_insn, METHOD_INTERFACE, is_range, false);
       if (failure_ == VERIFY_ERROR_NONE) {
-        Class* called_interface = abs_method->GetDeclaringClass();
-        if (!called_interface->IsInterface()) {
-          Fail(VERIFY_ERROR_CLASS_CHANGE) << "expected interface class in invoke-interface '"
-                                          << PrettyMethod(abs_method) << "'";
-          break;
-        } else {
-          /* Get the type of the "this" arg, which should either be a sub-interface of called
-           * interface or Object (see comments in RegType::JoinClass).
-           */
-          const RegType& this_type = work_line_->GetInvocationThis(dec_insn);
-          if (failure_ == VERIFY_ERROR_NONE) {
-            if (this_type.IsZero()) {
-              /* null pointer always passes (and always fails at runtime) */
-            } else {
-              if (this_type.IsUninitializedTypes()) {
-                Fail(VERIFY_ERROR_GENERIC) << "interface call on uninitialized object "
-                    << this_type;
-                break;
-              }
-              // In the past we have tried to assert that "called_interface" is assignable
-              // from "this_type.GetClass()", however, as we do an imprecise Join
-              // (RegType::JoinClass) we don't have full information on what interfaces are
-              // implemented by "this_type". For example, two classes may implement the same
-              // interfaces and have a common parent that doesn't implement the interface. The
-              // join will set "this_type" to the parent class and a test that this implements
-              // the interface will incorrectly fail.
+        if (abs_method != NULL) {
+          Class* called_interface = abs_method->GetDeclaringClass();
+          if (!called_interface->IsInterface()) {
+            Fail(VERIFY_ERROR_CLASS_CHANGE) << "expected interface class in invoke-interface '"
+                                            << PrettyMethod(abs_method) << "'";
+            break;
+          }
+        }
+        /* Get the type of the "this" arg, which should either be a sub-interface of called
+         * interface or Object (see comments in RegType::JoinClass).
+         */
+        const RegType& this_type = work_line_->GetInvocationThis(dec_insn);
+        if (failure_ == VERIFY_ERROR_NONE) {
+          if (this_type.IsZero()) {
+            /* null pointer always passes (and always fails at runtime) */
+          } else {
+            if (this_type.IsUninitializedTypes()) {
+              Fail(VERIFY_ERROR_GENERIC) << "interface call on uninitialized object "
+                  << this_type;
+              break;
             }
+            // In the past we have tried to assert that "called_interface" is assignable
+            // from "this_type.GetClass()", however, as we do an imprecise Join
+            // (RegType::JoinClass) we don't have full information on what interfaces are
+            // implemented by "this_type". For example, two classes may implement the same
+            // interfaces and have a common parent that doesn't implement the interface. The
+            // join will set "this_type" to the parent class and a test that this implements
+            // the interface will incorrectly fail.
           }
         }
         /*
          * We don't have an object instance, so we can't find the concrete method. However, all of
          * the type information is in the abstract method, so we're good.
          */
+        const char* descriptor;
+        if (abs_method == NULL) {
+          uint32_t method_idx = dec_insn.vB_;
+          const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
+          uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
+          descriptor =  dex_file_->dexStringByTypeIdx(return_type_idx);
+        } else {
+          descriptor = abs_method->GetReturnTypeDescriptor();
+        }
         const RegType& return_type =
-            reg_types_.FromDescriptor(abs_method->GetDeclaringClass()->GetClassLoader(),
-                                      abs_method->GetReturnTypeDescriptor());
+            reg_types_.FromDescriptor(method_->GetDeclaringClass()->GetClassLoader(), descriptor);
+        work_line_->SetResultRegisterType(return_type);
         work_line_->SetResultRegisterType(return_type);
         just_set_result = true;
       }
@@ -2887,24 +2952,30 @@
   return true;
 }
 
-Class* DexVerifier::ResolveClassAndCheckAccess(uint32_t class_idx) {
-  const Class* referrer = method_->GetDeclaringClass();
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  Class* res_class = class_linker->ResolveType(*dex_file_, class_idx, referrer);
-
-  if (res_class == NULL) {
-    Thread::Current()->ClearException();
-    Fail(VERIFY_ERROR_NO_CLASS) << "can't find class with index " << (void*) class_idx;
-  } else if (!referrer->CanAccess(res_class)) {   /* Check if access is allowed. */
-    Fail(VERIFY_ERROR_ACCESS_CLASS) << "illegal class access: "
-                                    << referrer->GetDescriptor()->ToModifiedUtf8() << " -> "
-                                    << res_class->GetDescriptor()->ToModifiedUtf8();
+const RegType& DexVerifier::ResolveClassAndCheckAccess(uint32_t class_idx) {
+  const char* descriptor = dex_file_->dexStringByTypeIdx(class_idx);
+  Class* referrer = method_->GetDeclaringClass();
+  Class* klass = method_->GetDexCacheResolvedTypes()->Get(class_idx);
+  const RegType& result =
+      klass != NULL ? reg_types_.FromClass(klass)
+                    : reg_types_.FromDescriptor(referrer->GetClassLoader(), descriptor);
+  if (klass == NULL && !result.IsUnresolvedTypes()) {
+    method_->GetDexCacheResolvedTypes()->Set(class_idx, result.GetClass());
   }
-  return res_class;
+  // Check if access is allowed. Unresolved types use AllocObjectFromCodeWithAccessCheck to
+  // check at runtime if access is allowed and so pass here.
+  if (!result.IsUnresolvedTypes() && !referrer->CanAccess(result.GetClass())) {
+    Fail(VERIFY_ERROR_ACCESS_CLASS) << "illegal class access: '"
+                                    << PrettyDescriptor(referrer->GetDescriptor()) << "' -> '"
+                                    << result << "'";
+    return reg_types_.Unknown();
+  } else {
+    return result;
+  }
 }
 
-Class* DexVerifier::GetCaughtExceptionType() {
-  Class* common_super = NULL;
+const RegType& DexVerifier::GetCaughtExceptionType() {
+  const RegType* common_super = NULL;
   if (code_item_->tries_size_ != 0) {
     const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item_, 0);
     uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
@@ -2914,25 +2985,23 @@
         DexFile::CatchHandlerItem handler = iterator.Get();
         if (handler.address_ == (uint32_t) work_insn_idx_) {
           if (handler.type_idx_ == DexFile::kDexNoIndex) {
-            common_super = JavaLangThrowable();
+            common_super = &reg_types_.JavaLangThrowable();
           } else {
-            Class* klass = ResolveClassAndCheckAccess(handler.type_idx_);
+            const RegType& exception = ResolveClassAndCheckAccess(handler.type_idx_);
             /* TODO: on error 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.
              */
-            if (klass == NULL) {
-              Fail(VERIFY_ERROR_GENERIC) << "unable to resolve exception class "
-                                         << handler.type_idx_ << " ("
-                                         << dex_file_->dexStringByTypeIdx(handler.type_idx_) << ")";
-              return NULL;
-            } else if(!JavaLangThrowable()->IsAssignableFrom(klass)) {
-              Fail(VERIFY_ERROR_GENERIC) << "unexpected non-exception class " << PrettyClass(klass);
-              return NULL;
+            if(!reg_types_.JavaLangThrowable().IsAssignableFrom(exception)) {
+              Fail(VERIFY_ERROR_GENERIC) << "unexpected non-exception class " << exception;
+              return reg_types_.Unknown();
             } else if (common_super == NULL) {
-              common_super = klass;
+              common_super = &exception;
+            } else if (common_super->Equals(exception)) {
+              // nothing to do
             } else {
-              common_super = RegType::ClassJoin(common_super, klass);
+              common_super = &common_super->Merge(exception, &reg_types_);
+              CHECK(reg_types_.JavaLangThrowable().IsAssignableFrom(*common_super));
             }
           }
         }
@@ -2944,7 +3013,7 @@
     /* no catch blocks, or no catches with classes we can find */
     Fail(VERIFY_ERROR_GENERIC) << "unable to find exception handler";
   }
-  return common_super;
+  return *common_super;
 }
 
 Method* DexVerifier::ResolveMethodAndCheckAccess(uint32_t method_idx, bool is_direct) {
@@ -2953,11 +3022,11 @@
   Method* res_method = dex_cache->GetResolvedMethod(method_idx);
   if (res_method == NULL) {
     const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
-    Class* klass = ResolveClassAndCheckAccess(method_id.class_idx_);
-    if (klass == NULL) {
-      DCHECK(failure_ != VERIFY_ERROR_NONE);
-      return NULL;
+    const RegType& klass_type = ResolveClassAndCheckAccess(method_id.class_idx_);
+    if(klass_type.IsUnresolvedTypes()) {
+      return NULL;  // Can't resolve Class so no more to do here
     }
+    Class* klass = klass_type.GetClass();
     const char* name = dex_file_->GetMethodName(method_id);
     std::string signature(dex_file_->CreateMethodDescriptor(method_id.proto_idx_, NULL));
     if (is_direct) {
@@ -2991,14 +3060,7 @@
   // we're making.
   Method* res_method = ResolveMethodAndCheckAccess(dec_insn.vB_,
                            (method_type == METHOD_DIRECT || method_type == METHOD_STATIC));
-  if (res_method == NULL) {
-    const DexFile::MethodId& method_id = dex_file_->GetMethodId(dec_insn.vB_);
-    const char* method_name = dex_file_->GetMethodName(method_id);
-    std::string method_signature = dex_file_->GetMethodSignature(method_id);
-    const char* class_descriptor = dex_file_->GetMethodDeclaringClassDescriptor(method_id);
-    DCHECK_NE(failure_, VERIFY_ERROR_NONE);
-    fail_messages_ << "unable to resolve method " << dec_insn.vB_ << ": "
-                   << class_descriptor << "." << method_name << " " << method_signature;
+  if (res_method == NULL) {  // error or class is unresolved
     return NULL;
   }
   // Make sure calls to constructors are "direct". There are additional restrictions but we don't
@@ -3410,13 +3472,14 @@
 }
 
 void DexVerifier::VerifyFilledNewArrayRegs(const Instruction::DecodedInstruction& dec_insn,
-                                           Class* res_class, bool is_range) {
-  DCHECK(res_class->IsArrayClass()) << PrettyClass(res_class);  // Checked before calling.
+                                           const RegType& res_type, bool is_range) {
+  DCHECK(res_type.IsArrayClass()) << res_type;  // Checked before calling.
   /*
    * Verify each register. If "arg_count" is bad, VerifyRegisterType() will run off the end of the
    * list and fail. It's legal, if silly, for arg_count to be zero.
    */
-  const RegType& expected_type = reg_types_.FromClass(res_class->GetComponentType());
+  const RegType& expected_type = reg_types_.GetComponentType(res_type,
+                                                   method_->GetDeclaringClass()->GetClassLoader());
   uint32_t arg_count = dec_insn.vA_;
   for (size_t ui = 0; ui < arg_count; ui++) {
     uint32_t get_reg;
@@ -3663,15 +3726,6 @@
   }
 }
 
-Class* DexVerifier::JavaLangThrowable() {
-  if (java_lang_throwable_ == NULL) {
-    java_lang_throwable_ =
-        Runtime::Current()->GetClassLinker()->FindSystemClass("Ljava/lang/Throwable;");
-   DCHECK(java_lang_throwable_ != NULL);
-  }
-  return java_lang_throwable_;
-}
-
 const uint8_t* PcToReferenceMap::FindBitMap(uint16_t dex_pc, bool error_if_not_present) const {
   size_t num_entries = NumEntries();
   // Do linear or binary search?
diff --git a/src/dex_verifier.h b/src/dex_verifier.h
index 9041c95..dbe92f6 100644
--- a/src/dex_verifier.h
+++ b/src/dex_verifier.h
@@ -143,7 +143,7 @@
 
   bool IsReferenceTypes() const {
     return IsReference() || IsUnresolvedReference() || IsUninitializedReference() ||
-        IsUninitializedThisReference() || IsZero();
+        IsUninitializedThisReference() || IsUnresolvedAndUninitializedReference() || IsZero();
   }
   bool IsNonZeroReferenceTypes() const {
     return IsReference() || IsUnresolvedReference() || IsUninitializedReference() ||
@@ -182,7 +182,7 @@
   }
 
   uint32_t GetAllocationPc() const {
-    DCHECK(IsUninitializedReference());
+    DCHECK(IsUninitializedTypes());
     return allocation_pc_or_constant_;
   }
 
@@ -196,12 +196,24 @@
   bool IsJavaLangObject() const {
     return IsReference() && GetClass()->IsObjectClass();
   }
+  bool IsInstantiableTypes() const {
+    return IsUnresolvedTypes() || (IsNonZeroReferenceTypes() && GetClass()->IsInstantiable());
+  }
   String* GetDescriptor() const {
-    DCHECK(IsUnresolvedReference());
+    DCHECK(IsUnresolvedTypes());
     DCHECK(klass_or_descriptor_ != NULL);
     DCHECK(klass_or_descriptor_->IsString());
     return down_cast<String*>(klass_or_descriptor_);
   }
+  bool IsArrayClass() const {
+    if (IsUnresolvedTypes()) {
+      return GetDescriptor()->CharAt(0) == '[';
+    } else if (!IsConstant()) {
+      return GetClass()->IsArrayClass();
+    } else {
+      return false;
+    }
+  }
 
   uint16_t GetId() const {
     return cache_id_;
@@ -239,12 +251,12 @@
   RegType(Type type, Object* klass_or_descriptor, uint32_t allocation_pc_or_constant, uint16_t cache_id) :
     type_(type), klass_or_descriptor_(klass_or_descriptor), allocation_pc_or_constant_(allocation_pc_or_constant),
     cache_id_(cache_id) {
-    DCHECK(IsConstant() || IsUninitializedReference() || allocation_pc_or_constant == 0);
+    DCHECK(IsConstant() || IsUninitializedTypes() || allocation_pc_or_constant == 0);
     if (!IsConstant() && !IsLongConstant() && !IsLongConstantHigh() && !IsUnknown() &&
         !IsConflict()) {
       DCHECK(klass_or_descriptor != NULL);
-      DCHECK(IsUnresolvedReference() || klass_or_descriptor_->IsClass());
-      DCHECK(!IsUnresolvedReference() || klass_or_descriptor_->IsString());
+      DCHECK(IsUnresolvedTypes() || klass_or_descriptor_->IsClass());
+      DCHECK(!IsUnresolvedTypes() || klass_or_descriptor_->IsString());
     }
   }
 
@@ -300,14 +312,16 @@
   const RegType& JavaLangClass()  { return From(RegType::kRegTypeReference, NULL, "Ljava/lang/Class;"); }
   const RegType& JavaLangObject() { return From(RegType::kRegTypeReference, NULL, "Ljava/lang/Object;"); }
   const RegType& JavaLangString() { return From(RegType::kRegTypeReference, NULL, "Ljava/lang/String;"); }
+  const RegType& JavaLangThrowable() { return From(RegType::kRegTypeReference, NULL, "Ljava/lang/Throwable;"); }
 
   const RegType& Unknown()  { return FromType(RegType::kRegTypeUnknown); }
   const RegType& Conflict() { return FromType(RegType::kRegTypeConflict); }
   const RegType& ConstLo()  { return FromType(RegType::kRegTypeConstLo); }
   const RegType& Zero()     { return FromCat1Const(0); }
 
-  const RegType& Uninitialized(Class* klass, uint32_t allocation_pc);
+  const RegType& Uninitialized(const RegType& type, uint32_t allocation_pc);
   const RegType& UninitializedThisArgument(Class* klass);
+  const RegType& FromUninitialized(const RegType& uninit_type);
 
   // Representatives of various constant types. When merging constants we can't infer a type,
   // (an int may later be used as a float) so we select these representative values meaning future
@@ -315,6 +329,8 @@
   const RegType& ByteConstant() { return FromCat1Const(std::numeric_limits<jbyte>::min()); }
   const RegType& ShortConstant() { return FromCat1Const(std::numeric_limits<jshort>::min()); }
   const RegType& IntConstant() { return FromCat1Const(std::numeric_limits<jint>::max()); }
+
+  const RegType& GetComponentType(const RegType& array, const ClassLoader* loader);
  private:
   // The allocated entries
   std::vector<RegType*> entries_;
@@ -1073,17 +1089,12 @@
                    bool is_primitive, bool is_static);
 
   // Verify that the arguments in a filled-new-array instruction are valid.
-  // "res_class" is the class refered to by dec_insn->vB_.
-  void VerifyFilledNewArrayRegs(const Instruction::DecodedInstruction& dec_insn, Class* res_class,
-                                bool is_range);
+  void VerifyFilledNewArrayRegs(const Instruction::DecodedInstruction& dec_insn,
+                                const RegType& res_type, bool is_range);
 
-  /*
-   * Resolves a class based on an index and performs access checks to ensure the referrer can
-   * access the resolved class.
-   * Exceptions caused by failures are cleared before returning.
-   * Sets "*failure" on failure.
-   */
-  Class* ResolveClassAndCheckAccess(uint32_t class_idx);
+  // Resolves a class based on an index and performs access checks to ensure the referrer can
+  // access the resolved class.
+  const RegType& ResolveClassAndCheckAccess(uint32_t class_idx);
 
   /*
    * For the "move-exception" instruction at "work_insn_idx_", which must be at an exception handler
@@ -1091,7 +1102,7 @@
    * Returns NULL if no matching exception handler can be found, or if the exception is not a
    * subclass of Throwable.
    */
-  Class* GetCaughtExceptionType();
+  const RegType& GetCaughtExceptionType();
 
   /*
    * Resolves a method based on an index and performs access checks to ensure
@@ -1169,8 +1180,6 @@
   // Compute sizes for GC map data
   void ComputeGcMapSizes(size_t* gc_points, size_t* ref_bitmap_bits, size_t* log2_max_gc_pc);
 
-  Class* JavaLangThrowable();
-
   InsnFlags CurrentInsnFlags() {
     return insn_flags_[work_insn_idx_];
   }
@@ -1182,9 +1191,6 @@
   // Storage for the register status we're currently working on.
   UniquePtr<RegisterLine> work_line_;
 
-  // Lazily initialized reference to java.lang.Class<java.lang.Throwable>
-  Class* java_lang_throwable_;
-
   // The address of the instruction we're currently working on, note that this is in 2 byte
   // quantities
   uint32_t work_insn_idx_;
diff --git a/src/object.cc b/src/object.cc
index e59e79a..45fc781 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -668,7 +668,6 @@
 
 uint32_t Method::FindCatchBlock(Class* exception_type, uint32_t dex_pc) const {
   DexCache* dex_cache = GetDeclaringClass()->GetDexCache();
-  const ClassLoader* class_loader = GetDeclaringClass()->GetClassLoader();
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
   const DexFile::CodeItem* code_item = dex_file.GetCodeItem(GetCodeItemOffset());
@@ -681,9 +680,12 @@
       return iter.Get().address_;
     }
     // Does this catch exception type apply?
-    Class* iter_exception_type =
-        class_linker->ResolveType(dex_file, iter_type_idx, dex_cache, class_loader);
-    if (iter_exception_type->IsAssignableFrom(exception_type)) {
+    Class* iter_exception_type = dex_cache->GetResolvedType(iter_type_idx);
+    if (iter_exception_type == NULL) {
+      // The verifier should take care of resolving all exception classes early
+      LOG(WARNING) << "Unresolved exception class when finding catch block: "
+          << dex_file.GetTypeDescriptor(dex_file.GetTypeId(iter_type_idx));
+    } else if (iter_exception_type->IsAssignableFrom(exception_type)) {
       return iter.Get().address_;
     }
   }
@@ -764,10 +766,8 @@
 }
 
 Object* Class::AllocObject() {
-  DCHECK(!IsAbstract()) << PrettyClass(this);
-  DCHECK(!IsInterface()) << PrettyClass(this);
-  DCHECK(!IsPrimitive()) << PrettyClass(this);
   DCHECK(!IsArrayClass()) << PrettyClass(this);
+  DCHECK(IsInstantiable()) << PrettyClass(this);
   DCHECK(!Runtime::Current()->IsStarted() || IsInitializing()) << PrettyClass(this);
   DCHECK_GE(this->object_size_, sizeof(Object));
   return Heap::AllocObject(this, this->object_size_);
diff --git a/src/object.h b/src/object.h
index 58c6ba7..1051985 100644
--- a/src/object.h
+++ b/src/object.h
@@ -1463,6 +1463,9 @@
   bool IsObjectClass() const {
     return !IsPrimitive() && GetSuperClass() == NULL;
   }
+  bool IsInstantiable() const {
+    return !IsPrimitive() && !IsInterface() && !IsAbstract();
+  }
 
   // Creates a raw object instance but does not invoke the default constructor.
   Object* AllocObject();
@@ -2022,8 +2025,7 @@
   Class* super_class_;
 
   // If class verify fails, we must return same error on subsequent tries.
-  // Update with SetVerifyErrorClass to ensure a write barrier is used.
-  const Class* verify_error_class_;
+  Class* verify_error_class_;
 
   // virtual methods defined in this class; invoked through vtable
   ObjectArray<Method>* virtual_methods_;
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 6773338..8df2abe 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -425,30 +425,6 @@
   return code;
 }
 
-// TODO: placeholder.  Helper function to type
-Class* InitializeTypeFromCode(uint32_t type_idx, Method* method) {
-  /*
-   * Should initialize & fix up method->dex_cache_resolved_types_[].
-   * Returns initialized type.  Does not return normally if an exception
-   * is thrown, but instead initiates the catch.  Should be similar to
-   * ClassLinker::InitializeStaticStorageFromCode.
-   */
-  UNIMPLEMENTED(FATAL);
-  return NULL;
-}
-
-// TODO: placeholder.  Helper function to resolve virtual method
-void ResolveMethodFromCode(Method* method, uint32_t method_idx) {
-    /*
-     * Slow-path handler on invoke virtual method path in which
-     * base method is unresolved at compile-time.  Doesn't need to
-     * return anything - just either ensure that
-     * method->dex_cache_resolved_methods_(method_idx) != NULL or
-     * throw and unwind.  The caller will restart call sequence
-     * from the beginning.
-     */
-}
-
 // Fast path field resolution that can't throw exceptions
 static Field* FindFieldFast(uint32_t field_idx, const Method* referrer) {
   Field* resolved_field = referrer->GetDexCacheResolvedFields()->Get(field_idx);
@@ -651,11 +627,30 @@
   return klass->AllocObject();
 }
 
-extern "C" Object* artAllocObjectFromCodeSlowPath(uint32_t type_idx,
-                                                  Method* method,
-                                                  Thread* self, Method** sp) {
-  //TODO: Add delayed verification checks here
-  return artAllocObjectFromCode(type_idx, method, self, sp);
+extern "C" Object* artAllocObjectFromCodeWithAccessCheck(uint32_t type_idx, Method* method,
+                                                         Thread* self, Method** sp) {
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
+  Runtime* runtime = Runtime::Current();
+  if (UNLIKELY(klass == NULL)) {
+    klass = runtime->GetClassLinker()->ResolveType(type_idx, method);
+    if (klass == NULL) {
+      DCHECK(self->IsExceptionPending());
+      return NULL;  // Failure
+    }
+  }
+  Class* referrer = method->GetDeclaringClass();
+  if (UNLIKELY(!referrer->CanAccess(klass))) {
+    self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;", "illegal class access: '%s' -> '%s'",
+                             PrettyDescriptor(referrer->GetDescriptor()).c_str(),
+                             PrettyDescriptor(klass->GetDescriptor()).c_str());
+    return NULL;  // Failure
+  }
+  if (!runtime->GetClassLinker()->EnsureInitialized(klass, true)) {
+    DCHECK(self->IsExceptionPending());
+    return NULL;  // Failure
+  }
+  return klass->AllocObject();
 }
 
 Array* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
@@ -789,6 +784,25 @@
   return InitializeStaticStorage(type_idx, referrer, self);
 }
 
+extern "C" Class* artInitializeTypeFromCode(uint32_t type_idx, const Method* referrer, Thread* self,
+                                            Method** sp) {
+  // Called when method->dex_cache_resolved_types_[] misses
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  return InitializeStaticStorage(type_idx, referrer, self);
+}
+
+// TODO: placeholder.  Helper function to resolve virtual method
+void ResolveMethodFromCode(Method* method, uint32_t method_idx) {
+    /*
+     * Slow-path handler on invoke virtual method path in which
+     * base method is unresolved at compile-time.  Doesn't need to
+     * return anything - just either ensure that
+     * method->dex_cache_resolved_methods_(method_idx) != NULL or
+     * throw and unwind.  The caller will restart call sequence
+     * from the beginning.
+     */
+}
+
 String* ResolveStringFromCode(const Method* referrer, uint32_t string_idx) {
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   return class_linker->ResolveString(string_idx, referrer);
diff --git a/src/runtime_support.h b/src/runtime_support.h
index 4ed6455..90fcf2c 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -59,12 +59,13 @@
   extern "C" void art_unlock_object_from_code(void*);
   extern "C" void* art_alloc_array_from_code(uint32_t, void*, int32_t);
   extern "C" void* art_alloc_object_from_code(uint32_t type_idx, void* method);
-  extern "C" void* art_alloc_object_from_code_slow_path(uint32_t type_idx, void* method);
+  extern "C" void* art_alloc_object_from_code_with_access_check(uint32_t type_idx, void* method);
   extern "C" void* art_check_and_alloc_array_from_code(uint32_t, void*, int32_t);
   extern "C" void* art_find_instance_field_from_code(uint32_t, void*);
   extern "C" void* art_find_static_field_from_code(uint32_t, void*);
   extern "C" void* art_get_obj_static_from_code(uint32_t, void*);
   extern "C" void* art_initialize_static_storage_from_code(uint32_t, void*);
+  extern "C" void* art_initialize_type_from_code(uint32_t, void*);
   extern "C" void* art_resolve_string_from_code(void*, uint32_t);
 
   /* Conversions */
diff --git a/src/runtime_support_asm.S b/src/runtime_support_asm.S
index b6d8928..112a114 100644
--- a/src/runtime_support_asm.S
+++ b/src/runtime_support_asm.S
@@ -280,6 +280,22 @@
     bxne   lr                                  @ return on success
     DELIVER_PENDING_EXCEPTION
 
+    .global art_initialize_type_from_code
+    .extern artInitializeTypeFromCode
+    /*
+     * Entry from managed code when dex cache misses for a type_idx
+     */
+art_initialize_type_from_code:
+    SETUP_REF_ONLY_CALLEE_SAVE_FRAME           @ save callee saves in case of GC
+    mov    r2, r9                              @ pass Thread::Current
+    mov    r3, sp                              @ pass SP
+    @ artInitializeTypeFromCode(uint32_t type_idx, Method* referrer, Thread*, SP)
+    bl     artInitializeTypeFromCode
+    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
+    cmp    r0, #0                              @ success if result is non-null
+    bxne   lr                                  @ return on success
+    DELIVER_PENDING_EXCEPTION
+
     .global art_find_instance_field_from_code
     .extern artFindInstanceFieldFromCode
     /*
@@ -441,16 +457,17 @@
     bxne   lr                         @ return on success
     DELIVER_PENDING_EXCEPTION
 
-    .global art_alloc_object_from_code_slow_path
-    .extern artAllocObjectFromCodeSlowPath
+    .global art_alloc_object_from_code_with_access_check
+    .extern artAllocObjectFromCodeWithAccessCheck
     /*
-     * Called by managed code to allocate an object
+     * Called by managed code to allocate an object when the caller doesn't know whether it has
+     * access to the created type
      */
-art_alloc_object_from_code_slow_path:
+art_alloc_object_from_code_with_access_check:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case of GC
     mov    r2, r9                     @ pass Thread::Current
     mov    r3, sp                     @ pass SP
-    bl     artAllocObjectFromCodeSlowPath     @ (uint32_t type_idx, Method* method, Thread*, SP)
+    bl     artAllocObjectFromCodeWithAccessCheck  @ (uint32_t type_idx, Method* method, Thread*, SP)
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
     cmp    r0, #0                     @ success if result is non-null
     bxne   lr                         @ return on success
diff --git a/src/thread.cc b/src/thread.cc
index 841ea9b..a8c58bf 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -91,7 +91,7 @@
   pLmul = __aeabi_lmul;
   pAllocArrayFromCode = art_alloc_array_from_code;
   pAllocObjectFromCode = art_alloc_object_from_code;
-  pAllocObjectFromCodeSlowPath = art_alloc_object_from_code_slow_path;
+  pAllocObjectFromCodeWithAccessCheck = art_alloc_object_from_code_with_access_check;
   pCanPutArrayElementFromCode = art_can_put_array_element_from_code;
   pCheckAndAllocArrayFromCode = art_check_and_alloc_array_from_code;
   pCheckCastFromCode = art_check_cast_from_code;
@@ -101,6 +101,7 @@
   pGetObjStatic = art_get_obj_static_from_code;
   pHandleFillArrayDataFromCode = art_handle_fill_data_from_code;
   pInitializeStaticStorage = art_initialize_static_storage_from_code;
+  pInitializeTypeFromCode = art_initialize_type_from_code;
   pInvokeInterfaceTrampoline = art_invoke_interface_trampoline;
   pLockObjectFromCode = art_lock_object_from_code;
   pObjectInit = art_object_init_from_code;
@@ -126,7 +127,6 @@
   pDecodeJObjectInThread = DecodeJObjectInThread;
   pDeliverException = art_deliver_exception_from_code;
   pFindNativeMethod = FindNativeMethod;
-  pInitializeTypeFromCode = InitializeTypeFromCode;
   pInstanceofNonTrivialFromCode = IsAssignableFromCode;
   pResolveMethodFromCode = ResolveMethodFromCode;
   pThrowAbstractMethodErrorFromCode = ThrowAbstractMethodErrorFromCode;
@@ -482,7 +482,8 @@
 
 struct StackDumpVisitor : public Thread::StackVisitor {
   StackDumpVisitor(std::ostream& os, const Thread* thread)
-      : os(os), thread(thread), frame_count(0) {
+      : last_method(NULL), last_line_number(0), repetition_count(0), os(os), thread(thread),
+        frame_count(0) {
   }
 
   virtual ~StackDumpVisitor() {
@@ -492,28 +493,41 @@
     if (!frame.HasMethod()) {
       return;
     }
-
+    const int kMaxRepetition = 3;
     Method* m = frame.GetMethod();
     Class* c = m->GetDeclaringClass();
     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     const DexFile& dex_file = class_linker->FindDexFile(c->GetDexCache());
-
-    os << "  at " << PrettyMethod(m, false);
-    if (m->IsNative()) {
-      os << "(Native method)";
+    int line_number = dex_file.GetLineNumFromPC(m, m->ToDexPC(pc));
+    if (line_number == last_line_number && last_method == m) {
+      repetition_count++;
     } else {
-      int line_number = dex_file.GetLineNumFromPC(m, m->ToDexPC(pc));
-      SirtRef<String> source_file(c->GetSourceFile());
-      os << "(" << (source_file.get() != NULL ? source_file->ToModifiedUtf8() : "unavailable")
-         << ":" << line_number << ")";
+      if (repetition_count >= kMaxRepetition) {
+        os << "  ... repeated " << (repetition_count - kMaxRepetition) << " times\n";
+      }
+      repetition_count = 0;
+      last_line_number = line_number;
+      last_method = m;
     }
-    os << "\n";
+    if (repetition_count < kMaxRepetition) {
+      os << "  at " << PrettyMethod(m, false);
+      if (m->IsNative()) {
+        os << "(Native method)";
+      } else {
+        SirtRef<String> source_file(c->GetSourceFile());
+        os << "(" << (source_file.get() != NULL ? source_file->ToModifiedUtf8() : "unavailable")
+           << ":" << line_number << ")";
+      }
+      os << "\n";
+    }
 
     if (frame_count++ == 0) {
       Monitor::DescribeWait(os, thread);
     }
   }
-
+  Method* last_method;
+  int last_line_number;
+  int repetition_count;
   std::ostream& os;
   const Thread* thread;
   int frame_count;
@@ -1316,13 +1330,35 @@
 };
 
 void Thread::DeliverException() {
-  Throwable *exception = GetException();  // Set exception on thread
+  const bool kDebugExceptionDelivery = false;
+  Throwable *exception = GetException();  // Get exception from thread
   CHECK(exception != NULL);
+  // Don't leave exception visible while we try to find the handler, which may cause class
+  // resolution
+  ClearException();
+  if (kDebugExceptionDelivery) {
+    DumpStack(LOG(INFO) << "Delivering exception: " << PrettyTypeOf(exception) << std::endl);
+  }
 
   Context* long_jump_context = GetLongJumpContext();
   CatchBlockStackVisitor catch_finder(exception->GetClass(), long_jump_context);
   WalkStackUntilUpCall(&catch_finder, true);
 
+  if (kDebugExceptionDelivery) {
+    Method* handler_method = catch_finder.handler_frame_.GetMethod();
+    if (handler_method == NULL) {
+      LOG(INFO) << "Handler is upcall";
+    } else {
+      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+      const DexFile& dex_file =
+          class_linker->FindDexFile(handler_method->GetDeclaringClass()->GetDexCache());
+      int line_number = dex_file.GetLineNumFromPC(handler_method,
+                                                handler_method->ToDexPC(catch_finder.handler_pc_));
+      LOG(INFO) << "Handler: " << PrettyMethod(handler_method)
+          << " (line: " << line_number << ")";
+    }
+  }
+  SetException(exception);
   long_jump_context->SetSP(reinterpret_cast<intptr_t>(catch_finder.handler_frame_.GetSP()));
   long_jump_context->SetPC(catch_finder.handler_pc_);
   long_jump_context->DoLongJump();
diff --git a/src/thread.h b/src/thread.h
index ac97ebe..eec9df4 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -120,7 +120,7 @@
   void (*pCheckSuspendFromCode)(Thread*);  // Stub that is called when the suspend count is non-zero
   void (*pTestSuspendFromCode)();  // Stub that is periodically called to test the suspend count
   void* (*pAllocObjectFromCode)(uint32_t, void*);
-  void* (*pAllocObjectFromCodeSlowPath)(uint32_t, void*);
+  void* (*pAllocObjectFromCodeWithAccessCheck)(uint32_t, void*);
   void* (*pAllocArrayFromCode)(uint32_t, void*, int32_t);
   void (*pCanPutArrayElementFromCode)(void*, void*);
   void* (*pCheckAndAllocArrayFromCode)(uint32_t, void*, int32_t);
@@ -137,7 +137,7 @@
   void* (*pInitializeStaticStorage)(uint32_t, void*);
   uint32_t (*pInstanceofNonTrivialFromCode)(const Class*, const Class*);
   void (*pInvokeInterfaceTrampoline)(uint32_t, void*);
-  Class* (*pInitializeTypeFromCode)(uint32_t, Method*);
+  void* (*pInitializeTypeFromCode)(uint32_t, void*);
   void (*pLockObjectFromCode)(void*);
   void (*pObjectInit)(void*);
   void (*pResolveMethodFromCode)(Method*, uint32_t);