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;",