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