Make sure threads allocating are in the kRunnable state
Change-Id: I55a08fcd38b3388698ef571d2d4fa9553210e197
diff --git a/src/dalvik_system_DexFile.cc b/src/dalvik_system_DexFile.cc
index 40a1626..6ad92ba 100644
--- a/src/dalvik_system_DexFile.cc
+++ b/src/dalvik_system_DexFile.cc
@@ -154,6 +154,7 @@
}
jclass DexFile_defineClass(JNIEnv* env, jclass, jstring javaName, jobject javaLoader, jint cookie) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
const DexFile* dex_file = toDexFile(env, cookie);
if (dex_file == NULL) {
return NULL;
diff --git a/src/dalvik_system_VMRuntime.cc b/src/dalvik_system_VMRuntime.cc
index 8334059..d4c1ed2 100644
--- a/src/dalvik_system_VMRuntime.cc
+++ b/src/dalvik_system_VMRuntime.cc
@@ -44,6 +44,7 @@
}
jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaElementClass, jint length) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
#ifdef MOVING_GARBAGE_COLLECTOR
// TODO: right now, we don't have a copying collector, so there's no need
// to do anything special here, but we ought to pass the non-movability
@@ -74,6 +75,7 @@
}
jlong VMRuntime_addressOf(JNIEnv* env, jobject, jobject javaArray) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
Array* array = Decode<Array*>(env, javaArray);
if (!array->IsArrayInstance()) {
Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;", "not an array");
diff --git a/src/heap.cc b/src/heap.cc
index bef71ae..9e356d1 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -323,6 +323,10 @@
Object* Heap::AllocateLocked(Space* space, size_t size) {
lock_->AssertHeld();
+ // Since allocation can cause a GC which will need to SuspendAll,
+ // make sure all allocators are in the kRunnable state.
+ DCHECK_EQ(Thread::Current()->GetState(), Thread::kRunnable);
+
// Fail impossible allocations. TODO: collect soft references.
if (size > maximum_size_) {
return NULL;
diff --git a/src/java_lang_Class.cc b/src/java_lang_Class.cc
index ec89a57..81d070f 100644
--- a/src/java_lang_Class.cc
+++ b/src/java_lang_Class.cc
@@ -29,6 +29,7 @@
// "name" is in "binary name" format, e.g. "dalvik.system.Debug$1".
jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean initialize, jobject javaLoader) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
ScopedUtfChars name(env, javaName);
if (name.c_str() == NULL) {
return NULL;
@@ -307,6 +308,7 @@
}
jboolean Class_isAssignableFrom(JNIEnv* env, jobject javaLhs, jclass javaRhs) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
Class* lhs = Decode<Class*>(env, javaLhs);
Class* rhs = Decode<Class*>(env, javaRhs);
if (rhs == NULL) {
@@ -365,6 +367,7 @@
}
jobject Class_newInstanceImpl(JNIEnv* env, jobject javaThis) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
Class* c = Decode<Class*>(env, javaThis);
if (c->IsPrimitive() || c->IsInterface() || c->IsArrayClass() || c->IsAbstract()) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
diff --git a/src/java_lang_Object.cc b/src/java_lang_Object.cc
index 41ff8b2..30d8223 100644
--- a/src/java_lang_Object.cc
+++ b/src/java_lang_Object.cc
@@ -30,6 +30,7 @@
}
jobject Object_internalClone(JNIEnv* env, jobject javaThis) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
Object* o = Decode<Object*>(env, javaThis);
return AddLocalReference<jobject>(env, o->Clone());
}
diff --git a/src/java_lang_Runtime.cc b/src/java_lang_Runtime.cc
index a2bd399..981db70 100644
--- a/src/java_lang_Runtime.cc
+++ b/src/java_lang_Runtime.cc
@@ -30,6 +30,7 @@
namespace {
void Runtime_gc(JNIEnv*, jclass) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
Heap::CollectGarbage();
}
diff --git a/src/java_lang_String.cc b/src/java_lang_String.cc
index 9aa5221..ff182e1 100644
--- a/src/java_lang_String.cc
+++ b/src/java_lang_String.cc
@@ -39,6 +39,7 @@
namespace {
jint String_compareTo(JNIEnv* env, jobject javaThis, jobject javaRhs) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
String* lhs = Decode<String*>(env, javaThis);
String* rhs = Decode<String*>(env, javaRhs);
diff --git a/src/java_lang_System.cc b/src/java_lang_System.cc
index d8e8a5a..45a2aee 100644
--- a/src/java_lang_System.cc
+++ b/src/java_lang_System.cc
@@ -111,6 +111,7 @@
}
void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst, jint dstPos, jint length) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
Thread* self = Thread::Current();
// Null pointer checks.
diff --git a/src/java_lang_Thread.cc b/src/java_lang_Thread.cc
index 9a91f77..891238e 100644
--- a/src/java_lang_Thread.cc
+++ b/src/java_lang_Thread.cc
@@ -55,12 +55,13 @@
}
jboolean Thread_nativeHoldsLock(JNIEnv* env, jobject javaThread, jobject javaObject) {
- ThreadListLock lock;
Object* object = Decode<Object*>(env, javaObject);
if (object == NULL) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", "object == null");
return JNI_FALSE;
}
+ ThreadListLock lock;
Thread* thread = Thread::FromManagedThread(env, javaThread);
return thread->HoldsLock(object);
}
diff --git a/src/java_lang_reflect_Array.cc b/src/java_lang_reflect_Array.cc
index d157282..08960b1 100644
--- a/src/java_lang_reflect_Array.cc
+++ b/src/java_lang_reflect_Array.cc
@@ -72,6 +72,7 @@
// subtract pieces off. Besides, we want to start with the outermost
// piece and work our way in.
jobject Array_createMultiArray(JNIEnv* env, jclass, jclass javaElementClass, jobject javaDimArray) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
DCHECK(javaElementClass != NULL);
Class* element_class = Decode<Class*>(env, javaElementClass);
DCHECK(element_class->IsClass());
@@ -120,6 +121,7 @@
jobject Array_createObjectArray(JNIEnv* env, jclass, jclass javaElementClass, jint length)
{
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
DCHECK(javaElementClass != NULL);
Class* element_class = Decode<Class*>(env, javaElementClass);
if (length < 0) {
diff --git a/src/java_lang_reflect_Constructor.cc b/src/java_lang_reflect_Constructor.cc
index 4d42450..f730543 100644
--- a/src/java_lang_reflect_Constructor.cc
+++ b/src/java_lang_reflect_Constructor.cc
@@ -33,6 +33,7 @@
* with an interface, array, or primitive class.
*/
jobject Constructor_constructNative(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs, jclass javaDeclaringClass, jobjectArray javaParams, jint, jboolean) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
Class* c = Decode<Class*>(env, javaDeclaringClass);
if (c->IsAbstract()) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
diff --git a/src/java_lang_reflect_Field.cc b/src/java_lang_reflect_Field.cc
index a2f09e7..727866b 100644
--- a/src/java_lang_reflect_Field.cc
+++ b/src/java_lang_reflect_Field.cc
@@ -30,6 +30,7 @@
}
bool GetFieldValue(Object* o, Field* f, JValue& value, bool allow_references) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
switch (f->GetPrimitiveType()) {
case Primitive::kPrimBoolean:
value.z = f->GetBoolean(o);
@@ -187,6 +188,7 @@
}
void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jchar src_descriptor, const JValue& new_value) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
Field* f = DecodeField(env->FromReflectedField(javaField));
Object* o = NULL;
if (!CheckReceiver(env, javaObj, javaDeclaringClass, f, o)) {
@@ -254,6 +256,7 @@
}
void Field_setField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jobject javaValue) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
Field* f = DecodeField(env->FromReflectedField(javaField));
// Unbox the value, if necessary.
diff --git a/src/thread.cc b/src/thread.cc
index 68acb9b..d9edd60 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -647,6 +647,11 @@
}
void Thread::FinishStartup() {
+ Thread* self = Thread::Current();
+
+ // Need to be kRunnable for FindClass
+ ScopedThreadStateChange tsc(self, Thread::kRunnable);
+
// Now the ClassLinker is ready, we can find the various Class*, Field*, and Method*s we need.
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
@@ -672,7 +677,6 @@
"uncaughtException", "(Ljava/lang/Thread;Ljava/lang/Throwable;)V");
// Finish attaching the main thread.
- Thread* self = Thread::Current();
self->CreatePeer("main", false);
const Field* Thread_contextClassLoader = FindFieldOrDie(Thread_class , "contextClassLoader", "Ljava/lang/ClassLoader;");