Add slow path for OP_NEW_INSTANCE

If the type is unresolved at verification time, we can't be sure
it's a valid new.  The compiler will now check for type resolution
at compile time.  If unresolved, we'll call out to the slow path,
where the access check will take place.

This CL only contains the compiler portion of this change.  For
now, the slow path code just calls out to the normal routine.

Change-Id: Ia568a164389baedaa695a44f6845a0fdfe585b56
diff --git a/src/asm_support.h b/src/asm_support.h
index 2f2cf4c..f81966f 100644
--- a/src/asm_support.h
+++ b/src/asm_support.h
@@ -10,13 +10,13 @@
 #define rSELF r9
 #define rLR r14
 // Offset of field Thread::suspend_count_ verified in InitCpu
-#define THREAD_SUSPEND_COUNT_OFFSET 384
+#define THREAD_SUSPEND_COUNT_OFFSET 388
 // Offset of field Thread::suspend_count_ verified in InitCpu
-#define THREAD_EXCEPTION_OFFSET 380
+#define THREAD_EXCEPTION_OFFSET 384
 
 #elif defined(__i386__)
 // Offset of field Thread::self_ verified in InitCpu
-#define THREAD_SELF_OFFSET 372
+#define THREAD_SELF_OFFSET 376
 #endif
 
 #endif  // ART_SRC_ASM_SUPPORT_H_
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index 00be2be..7098188 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -693,8 +693,11 @@
                            RegLocation rlDest)
 {
     oatFlushAllRegs(cUnit);    /* Everything to home location */
-    loadWordDisp(cUnit, rSELF,
-                 OFFSETOF_MEMBER(Thread, pAllocObjectFromCode), rLR);
+    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
     callRuntimeHelper(cUnit, rLR);
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 35d1103..6773338 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -651,6 +651,13 @@
   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);
+}
+
 Array* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
                                      Thread* self) {
   if (UNLIKELY(component_count < 0)) {
diff --git a/src/runtime_support.h b/src/runtime_support.h
index 2fc2302..4ed6455 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -59,6 +59,7 @@
   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_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*);
diff --git a/src/runtime_support_asm.S b/src/runtime_support_asm.S
index b3eae57..b6d8928 100644
--- a/src/runtime_support_asm.S
+++ b/src/runtime_support_asm.S
@@ -441,6 +441,21 @@
     bxne   lr                         @ return on success
     DELIVER_PENDING_EXCEPTION
 
+    .global art_alloc_object_from_code_slow_path
+    .extern artAllocObjectFromCodeSlowPath
+    /*
+     * Called by managed code to allocate an object
+     */
+art_alloc_object_from_code_slow_path:
+    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)
+    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_alloc_array_from_code
     .extern artAllocArrayFromCode
     /*
diff --git a/src/thread.cc b/src/thread.cc
index fc7fadb..ba81268 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -91,6 +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;
   pCanPutArrayElementFromCode = art_can_put_array_element_from_code;
   pCheckAndAllocArrayFromCode = art_check_and_alloc_array_from_code;
   pCheckCastFromCode = art_check_cast_from_code;
diff --git a/src/thread.h b/src/thread.h
index e721df5..975edfc 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -120,6 +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* (*pAllocArrayFromCode)(uint32_t, void*, int32_t);
   void (*pCanPutArrayElementFromCode)(void*, void*);
   void* (*pCheckAndAllocArrayFromCode)(uint32_t, void*, int32_t);