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/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);