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