Check instantiability at runtime when inconclusive at compile time

Change-Id: I40e4a3da05936fee77e074d5dc4d0fec1a1c5526
diff --git a/src/compiler.h b/src/compiler.h
index 4822b9f..1165161 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -107,6 +107,21 @@
     return referrer_class->CanAccess(resolved_class);
   }
 
+  bool CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_idx, const DexCache* dex_cache,
+                                              const DexFile& dex_file, uint32_t type_idx) const {
+    Class* resolved_class = dex_cache->GetResolvedType(type_idx);
+    if (resolved_class == NULL) {
+      return false;  // Unknown class needs access checks.
+    }
+    const DexFile::MethodId& method_id = dex_file.GetMethodId(referrer_idx);
+    Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_);
+    if (referrer_class == NULL) {
+      return false;  // Incomplete referrer knowledge needs access check.
+    }
+    // Perform access check, will return true if access is ok or false if we're going to have to
+    // check this at runtime (for example for class loaders).
+    return referrer_class->CanAccess(resolved_class) && resolved_class->IsInstantiable();
+  }
  private:
 
   // Checks if class specified by type_idx is one of the image_classes_
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index 042ebb2..423ef46 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -696,10 +696,10 @@
     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_idx,
-                                                    cUnit->dex_cache,
-                                                    *cUnit->dex_file,
-                                                    type_idx)) {
+    if (cUnit->compiler->CanAccessInstantiableTypeWithoutChecks(cUnit->method_idx,
+                                                                cUnit->dex_cache,
+                                                                *cUnit->dex_file,
+                                                                type_idx)) {
         loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pAllocObjectFromCode), rLR);
     } else {
         loadWordDisp(cUnit, rSELF,
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 63efbf7..ff43d1f 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -651,6 +651,11 @@
     }
   }
   if (access_check) {
+    if (UNLIKELY(!klass->IsInstantiable())) {
+      self->ThrowNewException("Ljava/lang/InstantiationError;",
+                              PrettyDescriptor(klass).c_str());
+      return NULL;  // Failure
+    }
     Class* referrer = method->GetDeclaringClass();
     if (UNLIKELY(!referrer->CanAccess(klass))) {
       self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",