Implement stub for initialize static storage base.

Also fix a race in thread list.

Change-Id: Ice35c2fa14e7a9a0585e89d558815ab99bbdd6b9
diff --git a/src/class_linker.cc b/src/class_linker.cc
index a9c2005..be1de23 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1491,7 +1491,8 @@
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   Class* klass = class_linker->ResolveType(type_idx, referrer);
   if (klass == NULL) {
-    UNIMPLEMENTED(FATAL) << "throw exception due to unresolved class";
+    CHECK(Thread::Current()->IsExceptionPending());
+    return NULL;  // Failure - Indicate to caller to deliver exception
   }
   // If we are the <clinit> of this class, just return our storage.
   //
@@ -1502,7 +1503,7 @@
   }
   if (!class_linker->EnsureInitialized(klass, true)) {
     CHECK(Thread::Current()->IsExceptionPending());
-    UNIMPLEMENTED(FATAL) << "throw class initialization error " << PrettyClass(klass);
+    return NULL;  // Failure - Indicate to caller to deliver exception
   }
   referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass);
   return klass;
diff --git a/src/runtime_support.S b/src/runtime_support.S
index 5746059..0e57592 100644
--- a/src/runtime_support.S
+++ b/src/runtime_support.S
@@ -160,6 +160,31 @@
     mov    r1, sp                             @ pass SP
     b      artDeliverPendingExceptionFromCode @ artDeliverPendingExceptionFromCode(Thread*, SP)
 
+    .global art_initialize_static_storage_from_code
+    .extern _ZN3art11ClassLinker31InitializeStaticStorageFromCodeEjPKNS_6MethodE
+    /*
+     * Entry from managed code when uninitialized static storage, this stub will run the class
+     * initializer and deliver the exception on error. On success the static storage base is
+     * returned.
+     */
+art_initialize_static_storage_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
+    @ ClassLinker::InitializeStaticStorageFromCode(uint32_t type_idx, Method* referrer)
+    bl     _ZN3art11ClassLinker31InitializeStaticStorageFromCodeEjPKNS_6MethodE
+    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_shl_long
 art_shl_long:
     /*
diff --git a/src/runtime_support.h b/src/runtime_support.h
index e7aeb74..734ba0b 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -10,19 +10,13 @@
   /* Compiler helpers */
   extern "C" void art_check_cast_from_code(void*, void*);
   extern "C" void art_handle_fill_data_from_code(void*, void*);
+  extern "C" void* art_initialize_static_storage_from_code(uint32_t, void*);
   extern "C" void art_invoke_interface_trampoline(void*, void*, void*, void*);
+  extern "C" void art_test_suspend();
   extern "C" void art_throw_array_bounds_from_code(int32_t index, int32_t limit);
   extern "C" void art_throw_div_zero_from_code();
   extern "C" void art_throw_null_pointer_exception_from_code();
   extern "C" void art_unlock_object_from_code(void*, void*);
-  extern "C" uint64_t art_shl_long(uint64_t, uint32_t);
-  extern "C" uint64_t art_shr_long(uint64_t, uint32_t);
-  extern "C" uint64_t art_ushr_long(uint64_t, uint32_t);
-  extern "C" void art_throw_null_pointer_exception_from_code();
-  extern "C" void art_throw_div_zero_from_code();
-  extern "C" void art_throw_array_bounds_from_code(int32_t index, int32_t limit);
-  extern "C" void art_invoke_interface_trampoline(void*, void*, void*, void*);
-  extern "C" void art_test_suspend();
 
   /* Conversions */
   extern "C" float __aeabi_i2f(int op1);             // OP_INT_TO_FLOAT
@@ -55,6 +49,9 @@
   /* Long long arithmetics - OP_REM_LONG[_2ADDR] & OP_DIV_LONG[_2ADDR] */
   extern "C" long long __aeabi_ldivmod(long long op1, long long op2);
   extern "C" long long __aeabi_lmul(long long op1, long long op2);
+  extern "C" uint64_t art_shl_long(uint64_t, uint32_t);
+  extern "C" uint64_t art_shr_long(uint64_t, uint32_t);
+  extern "C" uint64_t art_ushr_long(uint64_t, uint32_t);
 
 #endif
 
diff --git a/src/thread.cc b/src/thread.cc
index 857d44d..74d62d7 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -353,6 +353,7 @@
   pLmul = __aeabi_lmul;
   pCheckCastFromCode = art_check_cast_from_code;
   pHandleFillArrayDataFromCode = art_handle_fill_data_from_code;
+  pInitializeStaticStorage = art_initialize_static_storage_from_code;
   pInvokeInterfaceTrampoline = art_invoke_interface_trampoline;
   pTestSuspendFromCode = art_test_suspend;
   pThrowArrayBoundsFromCode = art_throw_array_bounds_from_code;
@@ -376,7 +377,6 @@
   pCanPutArrayElementFromCode = Class::CanPutArrayElementFromCode;
   pInitializeTypeFromCode = InitializeTypeFromCode;
   pResolveMethodFromCode = ResolveMethodFromCode;
-  pInitializeStaticStorage = ClassLinker::InitializeStaticStorageFromCode;
   pInstanceofNonTrivialFromCode = Object::InstanceOf;
   pLockObjectFromCode = LockObjectFromCode;
   pFindInstanceFieldFromCode = Field::FindInstanceFieldFromCode;
diff --git a/src/thread.h b/src/thread.h
index e198d9a..a33d361 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -221,7 +221,7 @@
   Class* (*pInitializeTypeFromCode)(uint32_t, Method*);
   void (*pResolveMethodFromCode)(Method*, uint32_t);
   void (*pInvokeInterfaceTrampoline)(void*, void*, void*, void*);
-  StaticStorageBase* (*pInitializeStaticStorage)(uint32_t, const Method*);
+  void* (*pInitializeStaticStorage)(uint32_t, void*);
   Field* (*pFindInstanceFieldFromCode)(uint32_t, const Method*);
   void (*pCheckSuspendFromCode)(Thread*);
   void (*pTestSuspendFromCode)();
diff --git a/src/thread_list.cc b/src/thread_list.cc
index 8c6185d..9a34426 100644
--- a/src/thread_list.cc
+++ b/src/thread_list.cc
@@ -310,7 +310,9 @@
 
 bool ThreadList::AllThreadsAreDaemons() {
   for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
-    if (!(*it)->IsDaemon()) {
+    // TODO: there's a race here with thread exit that's being worked around by checking if the peer
+    // is null.
+    if ((*it)->GetPeer() != NULL && !(*it)->IsDaemon()) {
       return false;
     }
   }