Increase use of ScopedJniThreadState.
Move the routines for changing Object* to jobject and vice-versa
(AddLocalReference and Decode) to ScopedJniThreadState to enforce use of
Object*s in the Runnable thread state. In the Runnable thread state
suspension is necessary before GC can take place.
Reduce use of const ClassLoader* as the code bottoms out in FindClass
and with a field assignment where the const is cast away (ie if we're
not going to enforce the const-ness we shouldn't pretend it is).
Refactor the Thread::Attach API so that we're not handling raw Objects on
unattached threads.
Remove some unreachable code.
Change-Id: I0fa969f49ee6a8f10752af74a6b0e04d46b4cd97
diff --git a/src/native/dalvik_system_DexFile.cc b/src/native/dalvik_system_DexFile.cc
index 89d7130..3bf0ea5 100644
--- a/src/native/dalvik_system_DexFile.cc
+++ b/src/native/dalvik_system_DexFile.cc
@@ -126,7 +126,7 @@
static jclass DexFile_defineClassNative(JNIEnv* env, jclass, jstring javaName, jobject javaLoader,
jint cookie) {
- ScopedJniThreadState tsc(env);
+ ScopedJniThreadState ts(env);
const DexFile* dex_file = toDexFile(cookie);
if (dex_file == NULL) {
return NULL;
@@ -142,10 +142,10 @@
}
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
class_linker->RegisterDexFile(*dex_file);
- Object* class_loader_object = Decode<Object*>(env, javaLoader);
+ Object* class_loader_object = ts.Decode<Object*>(javaLoader);
ClassLoader* class_loader = down_cast<ClassLoader*>(class_loader_object);
Class* result = class_linker->DefineClass(descriptor, class_loader, *dex_file, *dex_class_def);
- return AddLocalReference<jclass>(env, result);
+ return ts.AddLocalReference<jclass>(result);
}
static jobjectArray DexFile_getClassNameList(JNIEnv* env, jclass, jint cookie) {
diff --git a/src/native/dalvik_system_VMDebug.cc b/src/native/dalvik_system_VMDebug.cc
index 9b10cda..70067fe 100644
--- a/src/native/dalvik_system_VMDebug.cc
+++ b/src/native/dalvik_system_VMDebug.cc
@@ -22,6 +22,7 @@
#include "hprof/hprof.h"
#include "jni_internal.h"
#include "ScopedUtfChars.h"
+#include "scoped_jni_thread_state.h"
#include "toStringArray.h"
#include "trace.h"
@@ -204,7 +205,8 @@
}
static jlong VMDebug_countInstancesOfClass(JNIEnv* env, jclass, jclass javaClass, jboolean countAssignable) {
- Class* c = Decode<Class*>(env, javaClass);
+ ScopedJniThreadState ts(env);
+ Class* c = ts.Decode<Class*>(javaClass);
if (c == NULL) {
return 0;
}
diff --git a/src/native/dalvik_system_VMRuntime.cc b/src/native/dalvik_system_VMRuntime.cc
index 09ca251..417ae5b 100644
--- a/src/native/dalvik_system_VMRuntime.cc
+++ b/src/native/dalvik_system_VMRuntime.cc
@@ -22,6 +22,7 @@
#include "object.h"
#include "object_utils.h"
#include "scoped_heap_lock.h"
+#include "scoped_jni_thread_state.h"
#include "scoped_thread_list_lock.h"
#include "space.h"
#include "thread.h"
@@ -48,7 +49,7 @@
}
static jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaElementClass, jint length) {
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
+ ScopedJniThreadState ts(env);
#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
@@ -56,7 +57,7 @@
UNIMPLEMENTED(FATAL);
#endif
- Class* element_class = Decode<Class*>(env, javaElementClass);
+ Class* element_class = ts.Decode<Class*>(javaElementClass);
if (element_class == NULL) {
Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", "element class == null");
return NULL;
@@ -75,15 +76,15 @@
if (result == NULL) {
return NULL;
}
- return AddLocalReference<jobject>(env, result);
+ return ts.AddLocalReference<jobject>(result);
}
static jlong VMRuntime_addressOf(JNIEnv* env, jobject, jobject javaArray) {
if (javaArray == NULL) { // Most likely allocation failed
return 0;
}
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
- Array* array = Decode<Array*>(env, javaArray);
+ ScopedJniThreadState ts(env);
+ Array* array = ts.Decode<Array*>(javaArray);
if (!array->IsArrayInstance()) {
Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;", "not an array");
return 0;
diff --git a/src/native/dalvik_system_VMStack.cc b/src/native/dalvik_system_VMStack.cc
index e3ecbd9..933a5d5 100644
--- a/src/native/dalvik_system_VMStack.cc
+++ b/src/native/dalvik_system_VMStack.cc
@@ -26,10 +26,11 @@
namespace art {
static jobject GetThreadStack(JNIEnv* env, jobject javaThread) {
+ ScopedJniThreadState ts(env);
ScopedHeapLock heap_lock;
ScopedThreadListLock thread_list_lock;
- Thread* thread = Thread::FromManagedThread(env, javaThread);
- return (thread != NULL) ? GetThreadStack(env, thread) : NULL;
+ Thread* thread = Thread::FromManagedThread(ts, javaThread);
+ return (thread != NULL) ? GetThreadStack(ts, thread) : NULL;
}
static jint VMStack_fillStackTraceElements(JNIEnv* env, jclass, jobject javaThread, jobjectArray javaSteArray) {
@@ -44,10 +45,10 @@
// Returns the defining class loader of the caller's caller.
static jobject VMStack_getCallingClassLoader(JNIEnv* env, jclass) {
- ScopedJniThreadState ts(env, kNative); // Not a state change out of native.
+ ScopedJniThreadState ts(env);
NthCallerVisitor visitor(ts.Self()->GetManagedStack(), ts.Self()->GetTraceStack(), 2);
visitor.WalkStack();
- return AddLocalReference<jobject>(env, visitor.caller->GetDeclaringClass()->GetClassLoader());
+ return ts.AddLocalReference<jobject>(visitor.caller->GetDeclaringClass()->GetClassLoader());
}
static jobject VMStack_getClosestUserClassLoader(JNIEnv* env, jclass, jobject javaBootstrap, jobject javaSystem) {
@@ -72,20 +73,20 @@
Object* class_loader;
};
ScopedJniThreadState ts(env);
- Object* bootstrap = Decode<Object*>(env, javaBootstrap);
- Object* system = Decode<Object*>(env, javaSystem);
+ Object* bootstrap = ts.Decode<Object*>(javaBootstrap);
+ Object* system = ts.Decode<Object*>(javaSystem);
ClosestUserClassLoaderVisitor visitor(ts.Self()->GetManagedStack(), ts.Self()->GetTraceStack(),
bootstrap, system);
visitor.WalkStack();
- return AddLocalReference<jobject>(env, visitor.class_loader);
+ return ts.AddLocalReference<jobject>(visitor.class_loader);
}
// Returns the class of the caller's caller's caller.
static jclass VMStack_getStackClass2(JNIEnv* env, jclass) {
- ScopedJniThreadState ts(env, kNative); // Not a state change out of native.
+ ScopedJniThreadState ts(env);
NthCallerVisitor visitor(ts.Self()->GetManagedStack(), ts.Self()->GetTraceStack(), 3);
visitor.WalkStack();
- return AddLocalReference<jclass>(env, visitor.caller->GetDeclaringClass());
+ return ts.AddLocalReference<jclass>(visitor.caller->GetDeclaringClass());
}
static jobjectArray VMStack_getThreadStackTrace(JNIEnv* env, jclass, jobject javaThread) {
diff --git a/src/native/java_lang_Class.cc b/src/native/java_lang_Class.cc
index 99e3a26..ecab777 100644
--- a/src/native/java_lang_Class.cc
+++ b/src/native/java_lang_Class.cc
@@ -27,8 +27,8 @@
namespace art {
-static Class* DecodeClass(JNIEnv* env, jobject java_class) {
- Class* c = Decode<Class*>(env, java_class);
+static Class* DecodeClass(const ScopedJniThreadState& ts, jobject java_class) {
+ Class* c = ts.Decode<Class*>(java_class);
DCHECK(c != NULL);
DCHECK(c->IsClass());
// TODO: we could EnsureInitialized here, rather than on every reflective get/set or invoke .
@@ -39,7 +39,7 @@
// "name" is in "binary name" format, e.g. "dalvik.system.Debug$1".
static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean initialize, jobject javaLoader) {
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
+ ScopedJniThreadState ts(env);
ScopedUtfChars name(env, javaName);
if (name.c_str() == NULL) {
return NULL;
@@ -55,8 +55,7 @@
}
std::string descriptor(DotToDescriptor(name.c_str()));
- Object* loader = Decode<Object*>(env, javaLoader);
- ClassLoader* class_loader = down_cast<ClassLoader*>(loader);
+ ClassLoader* class_loader = ts.Decode<ClassLoader*>(javaLoader);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Class* c = class_linker->FindClass(descriptor.c_str(), class_loader);
if (c == NULL) {
@@ -71,11 +70,12 @@
if (initialize) {
class_linker->EnsureInitialized(c, true, true);
}
- return AddLocalReference<jclass>(env, c);
+ return ts.AddLocalReference<jclass>(c);
}
static jint Class_getAnnotationDirectoryOffset(JNIEnv* env, jclass javaClass) {
- Class* c = DecodeClass(env, javaClass);
+ ScopedJniThreadState ts(env);
+ Class* c = DecodeClass(ts, javaClass);
if (c->IsPrimitive() || c->IsArrayClass() || c->IsProxyClass()) {
return 0; // primitive, array and proxy classes don't have class definitions
}
@@ -88,12 +88,13 @@
}
template<typename T>
-static jobjectArray ToArray(JNIEnv* env, const char* array_class_name, const std::vector<T*>& objects) {
- ScopedLocalRef<jclass> array_class(env, env->FindClass(array_class_name));
- jobjectArray result = env->NewObjectArray(objects.size(), array_class.get(), NULL);
+static jobjectArray ToArray(const ScopedJniThreadState& ts, const char* array_class_name,
+ const std::vector<T*>& objects) {
+ ScopedLocalRef<jclass> array_class(ts.Env(), ts.Env()->FindClass(array_class_name));
+ jobjectArray result = ts.Env()->NewObjectArray(objects.size(), array_class.get(), NULL);
for (size_t i = 0; i < objects.size(); ++i) {
- ScopedLocalRef<jobject> object(env, AddLocalReference<jobject>(env, objects[i]));
- env->SetObjectArrayElement(result, i, object.get());
+ ScopedLocalRef<jobject> object(ts.Env(), ts.AddLocalReference<jobject>(objects[i]));
+ ts.Env()->SetObjectArrayElement(result, i, object.get());
}
return result;
}
@@ -109,11 +110,8 @@
}
static jobjectArray Class_getDeclaredConstructors(JNIEnv* env, jclass javaClass, jboolean publicOnly) {
- Class* c = DecodeClass(env, javaClass);
- if (c == NULL) {
- return NULL;
- }
-
+ ScopedJniThreadState ts(env);
+ Class* c = DecodeClass(ts, javaClass);
std::vector<Method*> constructors;
for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
Method* m = c->GetDirectMethod(i);
@@ -122,7 +120,7 @@
}
}
- return ToArray(env, "java/lang/reflect/Constructor", constructors);
+ return ToArray(ts, "java/lang/reflect/Constructor", constructors);
}
static bool IsVisibleField(Field* f, bool public_only) {
@@ -133,12 +131,8 @@
}
static jobjectArray Class_getDeclaredFields(JNIEnv* env, jclass javaClass, jboolean publicOnly) {
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
- Class* c = DecodeClass(env, javaClass);
- if (c == NULL) {
- return NULL;
- }
-
+ ScopedJniThreadState ts(env);
+ Class* c = DecodeClass(ts, javaClass);
std::vector<Field*> fields;
FieldHelper fh;
for (size_t i = 0; i < c->NumInstanceFields(); ++i) {
@@ -170,7 +164,7 @@
}
}
- return ToArray(env, "java/lang/reflect/Field", fields);
+ return ToArray(ts, "java/lang/reflect/Field", fields);
}
static bool IsVisibleMethod(Method* m, bool public_only) {
@@ -187,8 +181,8 @@
}
static jobjectArray Class_getDeclaredMethods(JNIEnv* env, jclass javaClass, jboolean publicOnly) {
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
- Class* c = DecodeClass(env, javaClass);
+ ScopedJniThreadState ts(env);
+ Class* c = DecodeClass(ts, javaClass);
if (c == NULL) {
return NULL;
}
@@ -224,11 +218,12 @@
}
}
- return ToArray(env, "java/lang/reflect/Method", methods);
+ return ToArray(ts, "java/lang/reflect/Method", methods);
}
static jobject Class_getDex(JNIEnv* env, jobject javaClass) {
- Class* c = DecodeClass(env, javaClass);
+ ScopedJniThreadState ts(env);
+ Class* c = DecodeClass(ts, javaClass);
DexCache* dex_cache = c->GetDexCache();
if (dex_cache == NULL) {
@@ -287,13 +282,10 @@
static jobject Class_getDeclaredConstructorOrMethod(JNIEnv* env, jclass javaClass, jstring javaName,
jobjectArray javaArgs) {
- Class* c = DecodeClass(env, javaClass);
- if (c == NULL) {
- return NULL;
- }
-
- std::string name(Decode<String*>(env, javaName)->ToModifiedUtf8());
- ObjectArray<Class>* arg_array = Decode<ObjectArray<Class>*>(env, javaArgs);
+ ScopedJniThreadState ts(env);
+ Class* c = DecodeClass(ts, javaClass);
+ std::string name(ts.Decode<String*>(javaName)->ToModifiedUtf8());
+ ObjectArray<Class>* arg_array = ts.Decode<ObjectArray<Class>*>(javaArgs);
Method* m = FindConstructorOrMethodInArray(c->GetDirectMethods(), name, arg_array);
if (m == NULL) {
@@ -301,7 +293,7 @@
}
if (m != NULL) {
- return AddLocalReference<jobject>(env, m);
+ return ts.AddLocalReference<jobject>(m);
} else {
return NULL;
}
@@ -309,12 +301,8 @@
static jobject Class_getDeclaredFieldNative(JNIEnv* env, jclass java_class, jobject jname) {
ScopedJniThreadState ts(env);
- Class* c = DecodeClass(env, java_class);
- if (c == NULL) {
- return NULL;
- }
-
- String* name = Decode<String*>(env, jname);
+ Class* c = DecodeClass(ts, java_class);
+ String* name = ts.Decode<String*>(jname);
DCHECK(name->GetClass()->IsStringClass());
FieldHelper fh;
@@ -326,7 +314,7 @@
DCHECK(env->ExceptionOccurred());
return NULL;
}
- return AddLocalReference<jclass>(env, f);
+ return ts.AddLocalReference<jclass>(f);
}
}
for (size_t i = 0; i < c->NumStaticFields(); ++i) {
@@ -337,7 +325,7 @@
DCHECK(env->ExceptionOccurred());
return NULL;
}
- return AddLocalReference<jclass>(env, f);
+ return ts.AddLocalReference<jclass>(f);
}
}
return NULL;
@@ -345,20 +333,20 @@
static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
ScopedJniThreadState ts(env);
- Class* c = DecodeClass(env, javaThis);
- return AddLocalReference<jstring>(env, c->ComputeName());
+ Class* c = DecodeClass(ts, javaThis);
+ return ts.AddLocalReference<jstring>(c->ComputeName());
}
static jobjectArray Class_getProxyInterfaces(JNIEnv* env, jobject javaThis) {
ScopedJniThreadState ts(env);
- SynthesizedProxyClass* c = down_cast<SynthesizedProxyClass*>(DecodeClass(env, javaThis));
- return AddLocalReference<jobjectArray>(env, c->GetInterfaces()->Clone());
+ SynthesizedProxyClass* c = down_cast<SynthesizedProxyClass*>(DecodeClass(ts, javaThis));
+ return ts.AddLocalReference<jobjectArray>(c->GetInterfaces()->Clone());
}
static jboolean Class_isAssignableFrom(JNIEnv* env, jobject javaLhs, jclass javaRhs) {
ScopedJniThreadState ts(env);
- Class* lhs = DecodeClass(env, javaLhs);
- Class* rhs = Decode<Class*>(env, javaRhs); // Can be null.
+ Class* lhs = DecodeClass(ts, javaLhs);
+ Class* rhs = ts.Decode<Class*>(javaRhs); // Can be null.
if (rhs == NULL) {
ts.Self()->ThrowNewException("Ljava/lang/NullPointerException;", "class == null");
return JNI_FALSE;
@@ -397,7 +385,7 @@
static jobject Class_newInstanceImpl(JNIEnv* env, jobject javaThis) {
ScopedJniThreadState ts(env);
- Class* c = DecodeClass(env, javaThis);
+ Class* c = DecodeClass(ts, javaThis);
if (c->IsPrimitive() || c->IsInterface() || c->IsArrayClass() || c->IsAbstract()) {
ts.Self()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
"Class %s can not be instantiated", PrettyDescriptor(ClassHelper(c).GetDescriptor()).c_str());
@@ -451,8 +439,8 @@
}
// invoke constructor; unlike reflection calls, we don't wrap exceptions
- jclass java_class = AddLocalReference<jclass>(env, c);
- jmethodID mid = EncodeMethod(init);
+ jclass java_class = ts.AddLocalReference<jclass>(c);
+ jmethodID mid = ts.EncodeMethod(init);
return env->NewObject(java_class, mid);
}
diff --git a/src/native/java_lang_Object.cc b/src/native/java_lang_Object.cc
index 51e4581..d6b1bd6 100644
--- a/src/native/java_lang_Object.cc
+++ b/src/native/java_lang_Object.cc
@@ -16,27 +16,31 @@
#include "jni_internal.h"
#include "object.h"
+#include "scoped_jni_thread_state.h"
namespace art {
static jobject Object_internalClone(JNIEnv* env, jobject javaThis) {
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
- Object* o = Decode<Object*>(env, javaThis);
- return AddLocalReference<jobject>(env, o->Clone());
+ ScopedJniThreadState ts(env);
+ Object* o = ts.Decode<Object*>(javaThis);
+ return ts.AddLocalReference<jobject>(o->Clone());
}
static void Object_notify(JNIEnv* env, jobject javaThis) {
- Object* o = Decode<Object*>(env, javaThis);
+ ScopedJniThreadState ts(env);
+ Object* o = ts.Decode<Object*>(javaThis);
o->Notify();
}
static void Object_notifyAll(JNIEnv* env, jobject javaThis) {
- Object* o = Decode<Object*>(env, javaThis);
+ ScopedJniThreadState ts(env);
+ Object* o = ts.Decode<Object*>(javaThis);
o->NotifyAll();
}
static void Object_wait(JNIEnv* env, jobject javaThis, jlong ms, jint ns) {
- Object* o = Decode<Object*>(env, javaThis);
+ ScopedJniThreadState ts(env);
+ Object* o = ts.Decode<Object*>(javaThis);
o->Wait(ms, ns);
}
diff --git a/src/native/java_lang_Runtime.cc b/src/native/java_lang_Runtime.cc
index 3019e95..1b657b1 100644
--- a/src/native/java_lang_Runtime.cc
+++ b/src/native/java_lang_Runtime.cc
@@ -17,16 +17,18 @@
#include <limits.h>
#include <unistd.h>
+#include "class_loader.h"
#include "heap.h"
#include "jni_internal.h"
#include "object.h"
#include "runtime.h"
+#include "scoped_jni_thread_state.h"
#include "ScopedUtfChars.h"
namespace art {
-static void Runtime_gc(JNIEnv*, jclass) {
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
+static void Runtime_gc(JNIEnv* env, jclass) {
+ ScopedJniThreadState ts(env);
Runtime::Current()->GetHeap()->CollectGarbage(false);
}
@@ -43,12 +45,13 @@
* message on failure.
*/
static jstring Runtime_nativeLoad(JNIEnv* env, jclass, jstring javaFilename, jobject javaLoader) {
+ ScopedJniThreadState ts(env);
ScopedUtfChars filename(env, javaFilename);
if (filename.c_str() == NULL) {
return NULL;
}
- ClassLoader* classLoader = Decode<ClassLoader*>(env, javaLoader);
+ ClassLoader* classLoader = ts.Decode<ClassLoader*>(javaLoader);
std::string detail;
JavaVMExt* vm = Runtime::Current()->GetJavaVM();
bool success = vm->LoadNativeLibrary(filename.c_str(), classLoader, detail);
diff --git a/src/native/java_lang_String.cc b/src/native/java_lang_String.cc
index f8fb4a7..96fcf96 100644
--- a/src/native/java_lang_String.cc
+++ b/src/native/java_lang_String.cc
@@ -16,6 +16,7 @@
#include "jni_internal.h"
#include "object.h"
+#include "scoped_jni_thread_state.h"
#ifdef HAVE__MEMCMP16
// "count" is in 16-bit units.
@@ -35,9 +36,9 @@
namespace art {
static jint String_compareTo(JNIEnv* env, jobject javaThis, jobject javaRhs) {
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
- String* lhs = Decode<String*>(env, javaThis);
- String* rhs = Decode<String*>(env, javaRhs);
+ ScopedJniThreadState ts(env);
+ String* lhs = ts.Decode<String*>(javaThis);
+ String* rhs = ts.Decode<String*>(javaRhs);
if (rhs == NULL) {
Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", "rhs == null");
@@ -69,10 +70,11 @@
}
static jint String_fastIndexOf(JNIEnv* env, jobject java_this, jint ch, jint start) {
+ ScopedJniThreadState ts(env);
// This method does not handle supplementary characters. They're dealt with in managed code.
DCHECK_LE(ch, 0xffff);
- String* s = Decode<String*>(env, java_this);
+ String* s = ts.Decode<String*>(java_this);
jint count = s->GetLength();
if (start < 0) {
@@ -94,9 +96,10 @@
}
static jstring String_intern(JNIEnv* env, jobject javaThis) {
- String* s = Decode<String*>(env, javaThis);
+ ScopedJniThreadState ts(env);
+ String* s = ts.Decode<String*>(javaThis);
String* result = s->Intern();
- return AddLocalReference<jstring>(env, result);
+ return ts.AddLocalReference<jstring>(result);
}
static JNINativeMethod gMethods[] = {
diff --git a/src/native/java_lang_System.cc b/src/native/java_lang_System.cc
index b0d1eec..76ac670 100644
--- a/src/native/java_lang_System.cc
+++ b/src/native/java_lang_System.cc
@@ -16,6 +16,7 @@
#include "jni_internal.h"
#include "object.h"
+#include "scoped_jni_thread_state.h"
/*
* We make guarantees about the atomicity of accesses to primitive
@@ -107,22 +108,21 @@
}
static void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst, jint dstPos, jint length) {
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
- Thread* self = Thread::Current();
+ ScopedJniThreadState ts(env);
// Null pointer checks.
if (javaSrc == NULL) {
- self->ThrowNewException("Ljava/lang/NullPointerException;", "src == null");
+ ts.Self()->ThrowNewException("Ljava/lang/NullPointerException;", "src == null");
return;
}
if (javaDst == NULL) {
- self->ThrowNewException("Ljava/lang/NullPointerException;", "dst == null");
+ ts.Self()->ThrowNewException("Ljava/lang/NullPointerException;", "dst == null");
return;
}
// Make sure source and destination are both arrays.
- Object* srcObject = Decode<Object*>(env, javaSrc);
- Object* dstObject = Decode<Object*>(env, javaDst);
+ Object* srcObject = ts.Decode<Object*>(javaSrc);
+ Object* dstObject = ts.Decode<Object*>(javaDst);
if (!srcObject->IsArrayInstance()) {
ThrowArrayStoreException_NotAnArray("source", srcObject);
return;
@@ -138,7 +138,7 @@
// Bounds checking.
if (srcPos < 0 || dstPos < 0 || length < 0 || srcPos > srcArray->GetLength() - length || dstPos > dstArray->GetLength() - length) {
- self->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
+ ts.Self()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
"src.length=%d srcPos=%d dst.length=%d dstPos=%d length=%d",
srcArray->GetLength(), srcPos, dstArray->GetLength(), dstPos, length);
return;
@@ -150,7 +150,7 @@
if (srcComponentType->IsPrimitive() != dstComponentType->IsPrimitive() || srcComponentType != dstComponentType) {
std::string srcType(PrettyTypeOf(srcArray));
std::string dstType(PrettyTypeOf(dstArray));
- self->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
+ ts.Self()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
"Incompatible types: src=%s, dst=%s", srcType.c_str(), dstType.c_str());
return;
}
@@ -233,7 +233,7 @@
if (i != length) {
std::string actualSrcType(PrettyTypeOf(o));
std::string dstType(PrettyTypeOf(dstArray));
- self->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
+ ts.Self()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
"source[%d] of type %s cannot be stored in destination array of type %s",
srcPos + i, actualSrcType.c_str(), dstType.c_str());
return;
@@ -241,7 +241,8 @@
}
static jint System_identityHashCode(JNIEnv* env, jclass, jobject javaObject) {
- Object* o = Decode<Object*>(env, javaObject);
+ ScopedJniThreadState ts(env);
+ Object* o = ts.Decode<Object*>(javaObject);
return static_cast<jint>(reinterpret_cast<uintptr_t>(o));
}
diff --git a/src/native/java_lang_Thread.cc b/src/native/java_lang_Thread.cc
index ed95a6c..86b3a20 100644
--- a/src/native/java_lang_Thread.cc
+++ b/src/native/java_lang_Thread.cc
@@ -17,6 +17,7 @@
#include "debugger.h"
#include "jni_internal.h"
#include "object.h"
+#include "scoped_jni_thread_state.h"
#include "scoped_thread_list_lock.h"
#include "ScopedUtfChars.h"
#include "thread.h"
@@ -25,22 +26,24 @@
namespace art {
static jobject Thread_currentThread(JNIEnv* env, jclass) {
- return AddLocalReference<jobject>(env, Thread::Current()->GetPeer());
+ ScopedJniThreadState ts(env);
+ return ts.AddLocalReference<jobject>(ts.Self()->GetPeer());
}
-static jboolean Thread_interrupted(JNIEnv*, jclass) {
- return Thread::Current()->Interrupted();
+static jboolean Thread_interrupted(JNIEnv* env, jclass) {
+ ScopedJniThreadState ts(env, kNative); // Doesn't touch objects, so keep in native state.
+ return ts.Self()->Interrupted();
}
static jboolean Thread_isInterrupted(JNIEnv* env, jobject java_thread) {
+ ScopedJniThreadState ts(env);
ScopedThreadListLock thread_list_lock;
- Thread* thread = Thread::FromManagedThread(env, java_thread);
+ Thread* thread = Thread::FromManagedThread(ts, java_thread);
return (thread != NULL) ? thread->IsInterrupted() : JNI_FALSE;
}
static void Thread_nativeCreate(JNIEnv* env, jclass, jobject java_thread, jlong stack_size) {
- Object* managedThread = Decode<Object*>(env, java_thread);
- Thread::CreateNativeThread(managedThread, stack_size);
+ Thread::CreateNativeThread(env, java_thread, stack_size);
}
static jint Thread_nativeGetStatus(JNIEnv* env, jobject java_thread, jboolean has_been_started) {
@@ -52,9 +55,10 @@
const jint kJavaTimedWaiting = 4;
const jint kJavaTerminated = 5;
+ ScopedJniThreadState ts(env);
ThreadState internal_thread_state = (has_been_started ? kTerminated : kStarting);
ScopedThreadListLock thread_list_lock;
- Thread* thread = Thread::FromManagedThread(env, java_thread);
+ Thread* thread = Thread::FromManagedThread(ts, java_thread);
if (thread != NULL) {
internal_thread_state = thread->GetState();
}
@@ -74,28 +78,30 @@
}
static jboolean Thread_nativeHoldsLock(JNIEnv* env, jobject java_thread, jobject java_object) {
- Object* object = Decode<Object*>(env, java_object);
+ ScopedJniThreadState ts(env);
+ Object* object = ts.Decode<Object*>(java_object);
if (object == NULL) {
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", "object == null");
return JNI_FALSE;
}
ScopedThreadListLock thread_list_lock;
- Thread* thread = Thread::FromManagedThread(env, java_thread);
+ Thread* thread = Thread::FromManagedThread(ts, java_thread);
return thread->HoldsLock(object);
}
static void Thread_nativeInterrupt(JNIEnv* env, jobject java_thread) {
+ ScopedJniThreadState ts(env);
ScopedThreadListLock thread_list_lock;
- Thread* thread = Thread::FromManagedThread(env, java_thread);
+ Thread* thread = Thread::FromManagedThread(ts, java_thread);
if (thread != NULL) {
thread->Interrupt();
}
}
static void Thread_nativeSetName(JNIEnv* env, jobject java_thread, jstring java_name) {
+ ScopedJniThreadState ts(env);
ScopedThreadListLock thread_list_lock;
- Thread* thread = Thread::FromManagedThread(env, java_thread);
+ Thread* thread = Thread::FromManagedThread(ts, java_thread);
if (thread == NULL) {
return;
}
@@ -112,8 +118,9 @@
* threads at Thread.NORM_PRIORITY (5).
*/
static void Thread_nativeSetPriority(JNIEnv* env, jobject java_thread, jint new_priority) {
+ ScopedJniThreadState ts(env);
ScopedThreadListLock thread_list_lock;
- Thread* thread = Thread::FromManagedThread(env, java_thread);
+ Thread* thread = Thread::FromManagedThread(ts, java_thread);
if (thread != NULL) {
thread->SetNativePriority(new_priority);
}
diff --git a/src/native/java_lang_Throwable.cc b/src/native/java_lang_Throwable.cc
index 625a34b..1c59a34 100644
--- a/src/native/java_lang_Throwable.cc
+++ b/src/native/java_lang_Throwable.cc
@@ -15,13 +15,14 @@
*/
#include "jni_internal.h"
+#include "scoped_jni_thread_state.h"
#include "thread.h"
namespace art {
static jobject Throwable_nativeFillInStackTrace(JNIEnv* env, jclass) {
- JNIEnvExt* env_ext = reinterpret_cast<JNIEnvExt*>(env);
- return env_ext->self->CreateInternalStackTrace(env);
+ ScopedJniThreadState ts(env);
+ return ts.Self()->CreateInternalStackTrace(ts);
}
static jobjectArray Throwable_nativeGetStackTrace(JNIEnv* env, jclass, jobject javaStackState) {
diff --git a/src/native/java_lang_VMClassLoader.cc b/src/native/java_lang_VMClassLoader.cc
index a976933..0689f74 100644
--- a/src/native/java_lang_VMClassLoader.cc
+++ b/src/native/java_lang_VMClassLoader.cc
@@ -15,14 +15,17 @@
*/
#include "class_linker.h"
+#include "class_loader.h"
#include "jni_internal.h"
+#include "scoped_jni_thread_state.h"
#include "ScopedUtfChars.h"
#include "zip_archive.h"
namespace art {
static jclass VMClassLoader_findLoadedClass(JNIEnv* env, jclass, jobject javaLoader, jstring javaName) {
- ClassLoader* loader = Decode<ClassLoader*>(env, javaLoader);
+ ScopedJniThreadState ts(env);
+ ClassLoader* loader = ts.Decode<ClassLoader*>(javaLoader);
ScopedUtfChars name(env, javaName);
if (name.c_str() == NULL) {
return NULL;
@@ -31,7 +34,7 @@
std::string descriptor(DotToDescriptor(name.c_str()));
Class* c = Runtime::Current()->GetClassLinker()->LookupClass(descriptor.c_str(), loader);
if (c != NULL && c->IsResolved()) {
- return AddLocalReference<jclass>(env, c);
+ return ts.AddLocalReference<jclass>(c);
} else {
// Class wasn't resolved so it may be erroneous or not yet ready, force the caller to go into
// the regular loadClass code.
diff --git a/src/native/java_lang_reflect_Array.cc b/src/native/java_lang_reflect_Array.cc
index ea635d3..729312e 100644
--- a/src/native/java_lang_reflect_Array.cc
+++ b/src/native/java_lang_reflect_Array.cc
@@ -18,6 +18,7 @@
#include "jni_internal.h"
#include "object.h"
#include "object_utils.h"
+#include "scoped_jni_thread_state.h"
namespace art {
@@ -68,12 +69,12 @@
// subtract pieces off. Besides, we want to start with the outermost
// piece and work our way in.
static jobject Array_createMultiArray(JNIEnv* env, jclass, jclass javaElementClass, jobject javaDimArray) {
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
+ ScopedJniThreadState ts(env);
DCHECK(javaElementClass != NULL);
- Class* element_class = Decode<Class*>(env, javaElementClass);
+ Class* element_class = ts.Decode<Class*>(javaElementClass);
DCHECK(element_class->IsClass());
DCHECK(javaDimArray != NULL);
- Object* dimensions_obj = Decode<Object*>(env, javaDimArray);
+ Object* dimensions_obj = ts.Decode<Object*>(javaDimArray);
DCHECK(dimensions_obj->IsArrayInstance());
DCHECK_STREQ(ClassHelper(dimensions_obj->GetClass()).GetDescriptor(), "[I");
IntArray* dimensions_array = down_cast<IntArray*>(dimensions_obj);
@@ -89,7 +90,7 @@
for (int i = 0; i < num_dimensions; i++) {
int dimension = dimensions_array->Get(i);
if (dimension < 0) {
- Thread::Current()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;",
+ ts.Self()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;",
"Dimension %d: %d", i, dimension);
return NULL;
}
@@ -112,15 +113,15 @@
CHECK(Thread::Current()->IsExceptionPending());
return NULL;
}
- return AddLocalReference<jobject>(env, new_array);
+ return ts.AddLocalReference<jobject>(new_array);
}
static jobject Array_createObjectArray(JNIEnv* env, jclass, jclass javaElementClass, jint length) {
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
+ ScopedJniThreadState ts(env);
DCHECK(javaElementClass != NULL);
- Class* element_class = Decode<Class*>(env, javaElementClass);
+ Class* element_class = ts.Decode<Class*>(javaElementClass);
if (length < 0) {
- Thread::Current()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", length);
+ ts.Self()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", length);
return NULL;
}
std::string descriptor;
@@ -130,16 +131,16 @@
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Class* array_class = class_linker->FindClass(descriptor.c_str(), element_class->GetClassLoader());
if (array_class == NULL) {
- CHECK(Thread::Current()->IsExceptionPending());
+ CHECK(ts.Self()->IsExceptionPending());
return NULL;
}
DCHECK(array_class->IsArrayClass());
Array* new_array = Array::Alloc(array_class, length);
if (new_array == NULL) {
- CHECK(Thread::Current()->IsExceptionPending());
+ CHECK(ts.Self()->IsExceptionPending());
return NULL;
}
- return AddLocalReference<jobject>(env, new_array);
+ return ts.AddLocalReference<jobject>(new_array);
}
static JNINativeMethod gMethods[] = {
diff --git a/src/native/java_lang_reflect_Constructor.cc b/src/native/java_lang_reflect_Constructor.cc
index 1094d06..564d6db 100644
--- a/src/native/java_lang_reflect_Constructor.cc
+++ b/src/native/java_lang_reflect_Constructor.cc
@@ -19,6 +19,7 @@
#include "object.h"
#include "object_utils.h"
#include "reflection.h"
+#include "scoped_jni_thread_state.h"
namespace art {
@@ -30,17 +31,17 @@
* with an interface, array, or primitive class.
*/
static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs) {
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
- Method* m = Decode<Object*>(env, javaMethod)->AsMethod();
+ ScopedJniThreadState ts(env);
+ Method* m = ts.Decode<Object*>(javaMethod)->AsMethod();
Class* c = m->GetDeclaringClass();
if (c->IsAbstract()) {
- Thread::Current()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
+ ts.Self()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
"Can't instantiate abstract class %s", PrettyDescriptor(c).c_str());
return NULL;
}
if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
- DCHECK(Thread::Current()->IsExceptionPending());
+ DCHECK(ts.Self()->IsExceptionPending());
return NULL;
}
@@ -49,8 +50,8 @@
return NULL;
}
- jobject javaReceiver = AddLocalReference<jobject>(env, receiver);
- InvokeMethod(env, javaMethod, javaReceiver, javaArgs);
+ jobject javaReceiver = ts.AddLocalReference<jobject>(receiver);
+ InvokeMethod(ts, javaMethod, javaReceiver, javaArgs);
// Constructors are ()V methods, so we shouldn't touch the result of InvokeMethod.
return javaReceiver;
diff --git a/src/native/java_lang_reflect_Field.cc b/src/native/java_lang_reflect_Field.cc
index bd33c0e..b2ede63 100644
--- a/src/native/java_lang_reflect_Field.cc
+++ b/src/native/java_lang_reflect_Field.cc
@@ -19,12 +19,13 @@
#include "object.h"
#include "object_utils.h"
#include "reflection.h"
+#include "scoped_jni_thread_state.h"
namespace art {
-static bool GetFieldValue(Object* o, Field* f, JValue& value, bool allow_references) {
+static bool GetFieldValue(const ScopedJniThreadState& ts, Object* o, Field* f, JValue& value,
+ bool allow_references) {
DCHECK_EQ(value.GetJ(), 0LL);
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(f->GetDeclaringClass(), true, true)) {
return false;
}
@@ -64,18 +65,18 @@
// Never okay.
break;
}
- Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
+ ts.Self()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
"Not a primitive field: %s", PrettyField(f).c_str());
return false;
}
-static bool CheckReceiver(JNIEnv* env, jobject javaObj, Field* f, Object*& o) {
+static bool CheckReceiver(const ScopedJniThreadState& ts, jobject javaObj, Field* f, Object*& o) {
if (f->IsStatic()) {
o = NULL;
return true;
}
- o = Decode<Object*>(env, javaObj);
+ o = ts.Decode<Object*>(javaObj);
Class* declaringClass = f->GetDeclaringClass();
if (!VerifyObjectInClass(o, declaringClass)) {
return false;
@@ -84,32 +85,34 @@
}
static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj) {
- Field* f = DecodeField(env->FromReflectedField(javaField));
+ ScopedJniThreadState ts(env);
+ Field* f = ts.DecodeField(env->FromReflectedField(javaField));
Object* o = NULL;
- if (!CheckReceiver(env, javaObj, f, o)) {
+ if (!CheckReceiver(ts, javaObj, f, o)) {
return NULL;
}
// Get the field's value, boxing if necessary.
JValue value;
- if (!GetFieldValue(o, f, value, true)) {
+ if (!GetFieldValue(ts, o, f, value, true)) {
return NULL;
}
BoxPrimitive(FieldHelper(f).GetTypeAsPrimitiveType(), value);
- return AddLocalReference<jobject>(env, value.GetL());
+ return ts.AddLocalReference<jobject>(value.GetL());
}
static JValue GetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, char dst_descriptor) {
- Field* f = DecodeField(env->FromReflectedField(javaField));
+ ScopedJniThreadState ts(env);
+ Field* f = ts.DecodeField(env->FromReflectedField(javaField));
Object* o = NULL;
- if (!CheckReceiver(env, javaObj, f, o)) {
+ if (!CheckReceiver(ts, javaObj, f, o)) {
return JValue();
}
// Read the value.
JValue field_value;
- if (!GetFieldValue(o, f, field_value, false)) {
+ if (!GetFieldValue(ts, o, f, field_value, false)) {
return JValue();
}
@@ -205,11 +208,11 @@
}
static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue) {
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
- Field* f = DecodeField(env->FromReflectedField(javaField));
+ ScopedJniThreadState ts(env);
+ Field* f = ts.DecodeField(env->FromReflectedField(javaField));
// Unbox the value, if necessary.
- Object* boxed_value = Decode<Object*>(env, javaValue);
+ Object* boxed_value = ts.Decode<Object*>(javaValue);
JValue unboxed_value;
if (!UnboxPrimitiveForField(boxed_value, FieldHelper(f).GetType(), unboxed_value, f)) {
return;
@@ -217,7 +220,7 @@
// Check that the receiver is non-null and an instance of the field's declaring class.
Object* o = NULL;
- if (!CheckReceiver(env, javaObj, f, o)) {
+ if (!CheckReceiver(ts, javaObj, f, o)) {
return;
}
@@ -226,15 +229,15 @@
static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, char src_descriptor,
const JValue& new_value) {
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
- Field* f = DecodeField(env->FromReflectedField(javaField));
+ ScopedJniThreadState ts(env);
+ Field* f = ts.DecodeField(env->FromReflectedField(javaField));
Object* o = NULL;
- if (!CheckReceiver(env, javaObj, f, o)) {
+ if (!CheckReceiver(ts, javaObj, f, o)) {
return;
}
FieldHelper fh(f);
if (!fh.IsPrimitiveType()) {
- Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
+ ts.Self()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
"Not a primitive field: %s", PrettyField(f).c_str());
return;
}
diff --git a/src/native/java_lang_reflect_Method.cc b/src/native/java_lang_reflect_Method.cc
index bf5c850..2695822 100644
--- a/src/native/java_lang_reflect_Method.cc
+++ b/src/native/java_lang_reflect_Method.cc
@@ -19,15 +19,18 @@
#include "object.h"
#include "object_utils.h"
#include "reflection.h"
+#include "scoped_jni_thread_state.h"
namespace art {
static jobject Method_invoke(JNIEnv* env, jobject javaMethod, jobject javaReceiver, jobject javaArgs) {
- return InvokeMethod(env, javaMethod, javaReceiver, javaArgs);
+ ScopedJniThreadState ts(env);
+ return InvokeMethod(ts, javaMethod, javaReceiver, javaArgs);
}
static jobject Method_getExceptionTypesNative(JNIEnv* env, jobject javaMethod) {
- Method* proxy_method = Decode<Object*>(env, javaMethod)->AsMethod();
+ ScopedJniThreadState ts(env);
+ Method* proxy_method = ts.Decode<Object*>(javaMethod)->AsMethod();
CHECK(proxy_method->GetDeclaringClass()->IsProxyClass());
SynthesizedProxyClass* proxy_class =
down_cast<SynthesizedProxyClass*>(proxy_method->GetDeclaringClass());
@@ -41,14 +44,13 @@
}
CHECK_NE(throws_index, -1);
ObjectArray<Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index);
- // Change thread state for allocation
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
- return AddLocalReference<jobject>(env, declared_exceptions->Clone());
+ return ts.AddLocalReference<jobject>(declared_exceptions->Clone());
}
static jobject Method_findOverriddenMethodNative(JNIEnv* env, jobject javaMethod) {
- Method* method = Decode<Object*>(env, javaMethod)->AsMethod();
- return AddLocalReference<jobject>(env, method->FindOverriddenMethod());
+ ScopedJniThreadState ts(env);
+ Method* method = ts.Decode<Object*>(javaMethod)->AsMethod();
+ return ts.AddLocalReference<jobject>(method->FindOverriddenMethod());
}
static JNINativeMethod gMethods[] = {
diff --git a/src/native/java_lang_reflect_Proxy.cc b/src/native/java_lang_reflect_Proxy.cc
index eca6c32..a1337a6 100644
--- a/src/native/java_lang_reflect_Proxy.cc
+++ b/src/native/java_lang_reflect_Proxy.cc
@@ -15,22 +15,23 @@
*/
#include "class_linker.h"
+#include "class_loader.h"
#include "jni_internal.h"
#include "object.h"
+#include "scoped_jni_thread_state.h"
namespace art {
static jclass Proxy_generateProxy(JNIEnv* env, jclass, jstring javaName, jobjectArray javaInterfaces, jobject javaLoader, jobjectArray javaMethods, jobjectArray javaThrows) {
- // Allocates Class so transition thread state to runnable
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
- String* name = Decode<String*>(env, javaName);
- ObjectArray<Class>* interfaces = Decode<ObjectArray<Class>*>(env, javaInterfaces);
- ClassLoader* loader = Decode<ClassLoader*>(env, javaLoader);
- ObjectArray<Method>* methods = Decode<ObjectArray<Method>*>(env, javaMethods);
- ObjectArray<ObjectArray<Class> >* throws = Decode<ObjectArray<ObjectArray<Class> >*>(env, javaThrows);
+ ScopedJniThreadState ts(env);
+ String* name = ts.Decode<String*>(javaName);
+ ObjectArray<Class>* interfaces = ts.Decode<ObjectArray<Class>*>(javaInterfaces);
+ ClassLoader* loader = ts.Decode<ClassLoader*>(javaLoader);
+ ObjectArray<Method>* methods = ts.Decode<ObjectArray<Method>*>(javaMethods);
+ ObjectArray<ObjectArray<Class> >* throws = ts.Decode<ObjectArray<ObjectArray<Class> >*>(javaThrows);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Class* result = class_linker->CreateProxyClass(name, interfaces, loader, methods, throws);
- return AddLocalReference<jclass>(env, result);
+ return ts.AddLocalReference<jclass>(result);
}
static JNINativeMethod gMethods[] = {
diff --git a/src/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc b/src/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
index 3766546..87d2b22 100644
--- a/src/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
+++ b/src/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
@@ -18,6 +18,7 @@
#include "jni_internal.h"
#include "logging.h"
#include "scoped_heap_lock.h"
+#include "scoped_jni_thread_state.h"
#include "scoped_thread_list_lock.h"
#include "ScopedPrimitiveArray.h"
#include "stack.h"
@@ -68,7 +69,8 @@
if (thread == NULL) {
return NULL;
}
- jobject stack = GetThreadStack(env, thread);
+ ScopedJniThreadState ts(env);
+ jobject stack = GetThreadStack(ts, thread);
return (stack != NULL) ? Thread::InternalStackTraceToStackTraceElementArray(env, stack) : NULL;
}
diff --git a/src/native/sun_misc_Unsafe.cc b/src/native/sun_misc_Unsafe.cc
index 360f241..dfddd86 100644
--- a/src/native/sun_misc_Unsafe.cc
+++ b/src/native/sun_misc_Unsafe.cc
@@ -16,30 +16,34 @@
#include "jni_internal.h"
#include "object.h"
+#include "scoped_jni_thread_state.h"
namespace art {
static jlong Unsafe_objectFieldOffset0(JNIEnv* env, jclass, jobject javaField) {
// TODO: move to Java code
jfieldID fid = env->FromReflectedField(javaField);
- Field* field = DecodeField(fid);
+ ScopedJniThreadState ts(env);
+ Field* field = ts.DecodeField(fid);
return field->GetOffset().Int32Value();
}
static jint Unsafe_arrayBaseOffset0(JNIEnv* env, jclass, jclass javaArrayClass) {
// TODO: move to Java code
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
- Class* array_class = Decode<Class*>(env, javaArrayClass);
+ ScopedJniThreadState ts(env);
+ Class* array_class = ts.Decode<Class*>(javaArrayClass);
return Array::DataOffset(array_class->GetComponentSize()).Int32Value();
}
static jint Unsafe_arrayIndexScale0(JNIEnv* env, jclass, jclass javaClass) {
- Class* c = Decode<Class*>(env, javaClass);
+ ScopedJniThreadState ts(env);
+ Class* c = ts.Decode<Class*>(javaClass);
return c->GetComponentSize();
}
static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint expectedValue, jint newValue) {
- Object* obj = Decode<Object*>(env, javaObj);
+ ScopedJniThreadState ts(env);
+ Object* obj = ts.Decode<Object*>(javaObj);
byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
volatile int32_t* address = reinterpret_cast<volatile int32_t*>(raw_addr);
// Note: android_atomic_release_cas() returns 0 on success, not failure.
@@ -48,7 +52,8 @@
}
static jboolean Unsafe_compareAndSwapLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong expectedValue, jlong newValue) {
- Object* obj = Decode<Object*>(env, javaObj);
+ ScopedJniThreadState ts(env);
+ Object* obj = ts.Decode<Object*>(javaObj);
byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
volatile int64_t* address = reinterpret_cast<volatile int64_t*>(raw_addr);
// Note: android_atomic_cmpxchg() returns 0 on success, not failure.
@@ -57,9 +62,10 @@
}
static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaExpectedValue, jobject javaNewValue) {
- Object* obj = Decode<Object*>(env, javaObj);
- Object* expectedValue = Decode<Object*>(env, javaExpectedValue);
- Object* newValue = Decode<Object*>(env, javaNewValue);
+ ScopedJniThreadState ts(env);
+ Object* obj = ts.Decode<Object*>(javaObj);
+ Object* expectedValue = ts.Decode<Object*>(javaExpectedValue);
+ Object* newValue = ts.Decode<Object*>(javaNewValue);
byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
int32_t* address = reinterpret_cast<int32_t*>(raw_addr);
// Note: android_atomic_cmpxchg() returns 0 on success, not failure.
@@ -72,90 +78,105 @@
}
static jint Unsafe_getInt(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
- Object* obj = Decode<Object*>(env, javaObj);
+ ScopedJniThreadState ts(env);
+ Object* obj = ts.Decode<Object*>(javaObj);
return obj->GetField32(MemberOffset(offset), false);
}
static jint Unsafe_getIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
- Object* obj = Decode<Object*>(env, javaObj);
+ ScopedJniThreadState ts(env);
+ Object* obj = ts.Decode<Object*>(javaObj);
byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
volatile int32_t* address = reinterpret_cast<volatile int32_t*>(raw_addr);
return android_atomic_acquire_load(address);
}
static void Unsafe_putInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
- Object* obj = Decode<Object*>(env, javaObj);
+ ScopedJniThreadState ts(env);
+ Object* obj = ts.Decode<Object*>(javaObj);
obj->SetField32(MemberOffset(offset), newValue, false);
}
static void Unsafe_putIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
- Object* obj = Decode<Object*>(env, javaObj);
+ ScopedJniThreadState ts(env);
+ Object* obj = ts.Decode<Object*>(javaObj);
byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
volatile int32_t* address = reinterpret_cast<volatile int32_t*>(raw_addr);
android_atomic_release_store(newValue, address);
}
static void Unsafe_putOrderedInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
- Object* obj = Decode<Object*>(env, javaObj);
+ ScopedJniThreadState ts(env);
+ Object* obj = ts.Decode<Object*>(javaObj);
ANDROID_MEMBAR_STORE();
obj->SetField32(MemberOffset(offset), newValue, false);
}
static jlong Unsafe_getLong(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
- Object* obj = Decode<Object*>(env, javaObj);
+ ScopedJniThreadState ts(env);
+ Object* obj = ts.Decode<Object*>(javaObj);
byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
int64_t* address = reinterpret_cast<int64_t*>(raw_addr);
return *address;
}
static jlong Unsafe_getLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
- Object* obj = Decode<Object*>(env, javaObj);
+ ScopedJniThreadState ts(env);
+ Object* obj = ts.Decode<Object*>(javaObj);
return obj->GetField64(MemberOffset(offset), true);
}
static void Unsafe_putLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
- Object* obj = Decode<Object*>(env, javaObj);
+ ScopedJniThreadState ts(env);
+ Object* obj = ts.Decode<Object*>(javaObj);
obj->SetField64(MemberOffset(offset), newValue, false);
}
static void Unsafe_putLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
- Object* obj = Decode<Object*>(env, javaObj);
+ ScopedJniThreadState ts(env);
+ Object* obj = ts.Decode<Object*>(javaObj);
obj->SetField64(MemberOffset(offset), newValue, true);
}
static void Unsafe_putOrderedLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
- Object* obj = Decode<Object*>(env, javaObj);
+ ScopedJniThreadState ts(env);
+ Object* obj = ts.Decode<Object*>(javaObj);
ANDROID_MEMBAR_STORE();
obj->SetField64(MemberOffset(offset), newValue, false);
}
static jobject Unsafe_getObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
- Object* obj = Decode<Object*>(env, javaObj);
+ ScopedJniThreadState ts(env);
+ Object* obj = ts.Decode<Object*>(javaObj);
Object* value = obj->GetFieldObject<Object*>(MemberOffset(offset), true);
- return AddLocalReference<jobject>(env, value);
+ return ts.AddLocalReference<jobject>(value);
}
static jobject Unsafe_getObject(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
- Object* obj = Decode<Object*>(env, javaObj);
+ ScopedJniThreadState ts(env);
+ Object* obj = ts.Decode<Object*>(javaObj);
Object* value = obj->GetFieldObject<Object*>(MemberOffset(offset), false);
- return AddLocalReference<jobject>(env, value);
+ return ts.AddLocalReference<jobject>(value);
}
static void Unsafe_putObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
- Object* obj = Decode<Object*>(env, javaObj);
- Object* newValue = Decode<Object*>(env, javaNewValue);
+ ScopedJniThreadState ts(env);
+ Object* obj = ts.Decode<Object*>(javaObj);
+ Object* newValue = ts.Decode<Object*>(javaNewValue);
obj->SetFieldObject(MemberOffset(offset), newValue, false);
}
static void Unsafe_putObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
- Object* obj = Decode<Object*>(env, javaObj);
- Object* newValue = Decode<Object*>(env, javaNewValue);
+ ScopedJniThreadState ts(env);
+ Object* obj = ts.Decode<Object*>(javaObj);
+ Object* newValue = ts.Decode<Object*>(javaNewValue);
obj->SetFieldObject(MemberOffset(offset), newValue, true);
}
static void Unsafe_putOrderedObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
- Object* obj = Decode<Object*>(env, javaObj);
- Object* newValue = Decode<Object*>(env, javaNewValue);
+ ScopedJniThreadState ts(env);
+ Object* obj = ts.Decode<Object*>(javaObj);
+ Object* newValue = ts.Decode<Object*>(javaNewValue);
ANDROID_MEMBAR_STORE();
obj->SetFieldObject(MemberOffset(offset), newValue, false);
}