Exception support for object allocation.

Strengthen asserts, no extra unit tests as expect good coverage on this
already.

Change-Id: Ie8786932667b70d20c0cdf69b4b6b721b6244ded
diff --git a/src/object.cc b/src/object.cc
index 29eac77..7b47d9f 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -774,20 +774,10 @@
                  new_dex_cache, false);
 }
 
-Object* Class::AllocObjectFromCode(uint32_t type_idx, Method* method) {
-  Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
-  if (klass == NULL) {
-    klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
-    if (klass == NULL) {
-      UNIMPLEMENTED(FATAL) << "throw an error";
-      return NULL;
-    }
-  }
-  return klass->AllocObject();
-}
-
 Object* Class::AllocObject() {
   DCHECK(!IsAbstract());
+  DCHECK(!IsInterface());
+  DCHECK(!IsPrimitive());
   return Heap::AllocObject(this, this->object_size_);
 }
 
diff --git a/src/object.h b/src/object.h
index 09788be..69f8c14 100644
--- a/src/object.h
+++ b/src/object.h
@@ -1422,11 +1422,6 @@
     return !IsPrimitive() && GetSuperClass() == NULL;
   }
 
-  // Given the context of a calling Method, use its DexCache to
-  // resolve a type to a Class. If it cannot be resolved, throw an
-  // error. If it can, use it to create an instance.
-  static Object* AllocObjectFromCode(uint32_t type_idx, Method* method);
-
   // Creates a raw object instance but does not invoke the default constructor.
   Object* AllocObject();
 
diff --git a/src/object_test.cc b/src/object_test.cc
index 9a5777b..d6705d7 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -162,12 +162,13 @@
   TestPrimitiveArray<ShortArray>(class_linker_);
 }
 
+extern "C" Object* artAllocObjectFromCode(uint32_t type_idx, Method* method);
 TEST_F(ObjectTest, AllocObjectFromCode) {
   // pretend we are trying to call 'new String' from Object.toString
   Class* java_lang_Object = class_linker_->FindSystemClass("Ljava/lang/Object;");
   Method* toString = java_lang_Object->FindVirtualMethod("toString", "()Ljava/lang/String;");
   uint32_t type_idx = FindTypeIdxByDescriptor(*java_lang_dex_file_.get(), "Ljava/lang/String;");
-  Object* string = Class::AllocObjectFromCode(type_idx, toString);
+  Object* string = artAllocObjectFromCode(type_idx, toString);
   EXPECT_TRUE(string->IsString());
 }
 
diff --git a/src/runtime_support.S b/src/runtime_support.S
index 9cfb3ab..4a50344 100644
--- a/src/runtime_support.S
+++ b/src/runtime_support.S
@@ -219,6 +219,28 @@
     mov    r1, sp                             @ pass SP
     b      artDeliverPendingExceptionFromCode @ artDeliverPendingExceptionFromCode(Thread*, SP)
 
+    .global art_alloc_object_from_code
+    .extern artAllocObjectFromCode
+    /*
+     * Called by managed code to allocate an object
+     */
+art_alloc_object_from_code:
+    str    sp, [R9, #THREAD_TOP_OF_MANAGED_STACK_OFFSET]    @ record top of stack and pc in case of
+    str    lr, [R9, #THREAD_TOP_OF_MANAGED_STACK_PC_OFFSET] @ walking stack
+    stmdb  sp!, {lr}               @ Save LR
+    sub    sp, #12                 @ Align stack
+    bl     artAllocObjectFromCode  @ (uint32_t type_idx, Method* method)
+    add    sp, #12
+    ldmia  sp!, {lr}               @ restore LR
+    cmp    r0, #0                  @ success if result is non-null
+    movne  pc, lr                  @ return on success
+                                   @ set up for throwing exception
+    stmdb  sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, lr}
+    sub    sp, #16                 @ 4 words of space, bottom word will hold Method*
+    mov    r0, r9                  @ pass Thread::Current
+    mov    r1, sp                  @ pass SP
+    b      artDeliverPendingExceptionFromCode  @ artDeliverPendingExceptionFromCode(Thread*, SP)
+
     .global art_array_alloc_from_code
     .extern artArrayAllocFromCode
     /*
diff --git a/src/runtime_support.h b/src/runtime_support.h
index 20ca1d4..d9cc364 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -8,6 +8,7 @@
 
 #if defined(__arm__)
   /* Compiler helpers */
+  extern "C" void* art_alloc_object_from_code(uint32_t type_idx, void* method);
   extern "C" void* art_array_alloc_from_code(uint32_t, void*, int32_t);
   extern "C" void* art_check_and_array_alloc_from_code(uint32_t, void*, int32_t);
   extern "C" void art_can_put_array_element_from_code(void*, void*);
diff --git a/src/thread.cc b/src/thread.cc
index 69dec94..22495be 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -191,6 +191,20 @@
      */
 }
 
+// Given the context of a calling Method, use its DexCache to resolve a type to a Class. If it
+// cannot be resolved, throw an error. If it can, use it to create an instance.
+extern "C" Object* artAllocObjectFromCode(uint32_t type_idx, Method* method) {
+  Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
+  if (klass == NULL) {
+    klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
+    if (klass == NULL) {
+      DCHECK(Thread::Current()->IsExceptionPending());
+      return NULL;  // Failure
+    }
+  }
+  return klass->AllocObject();
+}
+
 // Helper function to alloc array for OP_FILLED_NEW_ARRAY
 extern "C" Array* artCheckAndArrayAllocFromCode(uint32_t type_idx, Method* method,
                                                 int32_t component_count) {
@@ -418,6 +432,7 @@
   pFmod = fmod;
   pLdivmod = __aeabi_ldivmod;
   pLmul = __aeabi_lmul;
+  pAllocObjectFromCode = art_alloc_object_from_code;
   pArrayAllocFromCode = art_array_alloc_from_code;
   pCanPutArrayElementFromCode = art_can_put_array_element_from_code;
   pCheckAndArrayAllocFromCode = art_check_and_array_alloc_from_code;
@@ -435,7 +450,6 @@
   pDeliverException = art_deliver_exception_from_code;
   pF2l = F2L;
   pD2l = D2L;
-  pAllocObjectFromCode = Class::AllocObjectFromCode;
   pMemcpy = memcpy;
   pGet32Static = Field::Get32StaticFromCode;
   pSet32Static = Field::Set32StaticFromCode;
diff --git a/src/thread.h b/src/thread.h
index 945d337..fe7900d 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -202,9 +202,9 @@
   int (*pIdiv)(int, int);
   long long (*pLmul)(long long, long long);
   long long (*pLdivmod)(long long, long long);
+  void* (*pAllocObjectFromCode)(uint32_t, void*);
   void* (*pArrayAllocFromCode)(uint32_t, void*, int32_t);
   void* (*pCheckAndArrayAllocFromCode)(uint32_t, void*, int32_t);
-  Object* (*pAllocObjectFromCode)(uint32_t, Method*);
   uint32_t (*pGet32Static)(uint32_t, const Method*);
   void (*pSet32Static)(uint32_t, const Method*, uint32_t);
   uint64_t (*pGet64Static)(uint32_t, const Method*);