Initialize the rest of libcore's native code.
This native code requires NewGlobalRef, so this patch also implements
NewLocalRef/DeleteLocalRef, NewGlobalRef/DeleteGlobalRef, and
NewWeakGlobalRef/DeleteWeakGlobalRef.
(The assembler change is because "math.h" also defines OVERFLOW. A slight
change in #include ordering caused the names to conflict.)
Change-Id: Ifbf3b532ec3b0896bd7507d2881c6b77b64f01e7
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 599b0fe..c538670 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -8,6 +8,7 @@
#include <utility>
#include <vector>
+#include "assembler.h"
#include "class_linker.h"
#include "jni.h"
#include "logging.h"
@@ -26,7 +27,11 @@
};
struct SharedLibrary {
- SharedLibrary() : jni_on_load_lock("JNI_OnLoad") {
+ SharedLibrary() : jni_on_load_lock(Mutex::Create("JNI_OnLoad lock")) {
+ }
+
+ ~SharedLibrary() {
+ delete jni_on_load_lock;
}
// Path to library "/system/lib/libjni.so".
@@ -39,7 +44,7 @@
Object* class_loader;
// Guards remaining items.
- Mutex jni_on_load_lock;
+ Mutex* jni_on_load_lock;
// Wait for JNI_OnLoad in other thread.
pthread_cond_t jni_on_load_cond;
// Recursive invocation guard.
@@ -63,7 +68,7 @@
}
UNIMPLEMENTED(ERROR) << "need to pthread_cond_wait!";
- // MutexLock mu(&library->jni_on_load_lock);
+ // MutexLock mu(library->jni_on_load_lock);
while (library->jni_on_load_result == kPending) {
if (vm->verbose_jni) {
LOG(INFO) << "[" << *self << " waiting for \"" << library->path << "\" "
@@ -242,7 +247,7 @@
// Broadcast a wakeup to anybody sleeping on the condition variable.
UNIMPLEMENTED(ERROR) << "missing pthread_cond_broadcast";
- // MutexLock mu(&library->jni_on_load_lock);
+ // MutexLock mu(library->jni_on_load_lock);
// pthread_cond_broadcast(&library->jni_on_load_cond);
return result;
}
@@ -364,7 +369,7 @@
{
JavaVMExt* vm = Runtime::Current()->GetJavaVM();
IndirectReferenceTable& globals = vm->globals;
- MutexLock mu(&vm->globals_lock);
+ MutexLock mu(vm->globals_lock);
result = globals.Get(ref);
break;
}
@@ -372,7 +377,7 @@
{
JavaVMExt* vm = Runtime::Current()->GetJavaVM();
IndirectReferenceTable& weak_globals = vm->weak_globals;
- MutexLock mu(&vm->weak_globals_lock);
+ MutexLock mu(vm->weak_globals_lock);
result = weak_globals.Get(ref);
if (result == kClearedJniWeakGlobal) {
// This is a special case where it's okay to return NULL.
@@ -663,20 +668,79 @@
return res;
}
-jobject NewGlobalRef(JNIEnv* env, jobject lobj) {
+jobject NewGlobalRef(JNIEnv* env, jobject obj) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return NULL;
+ if (obj == NULL) {
+ return NULL;
+ }
+
+ JavaVMExt* vm = Runtime::Current()->GetJavaVM();
+ IndirectReferenceTable& globals = vm->globals;
+ MutexLock mu(vm->globals_lock);
+ IndirectRef ref = globals.Add(IRT_FIRST_SEGMENT, Decode<Object*>(ts, obj));
+ return reinterpret_cast<jobject>(ref);
}
-void DeleteGlobalRef(JNIEnv* env, jobject gref) {
+void DeleteGlobalRef(JNIEnv* env, jobject obj) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ if (obj == NULL) {
+ return;
+ }
+
+ JavaVMExt* vm = Runtime::Current()->GetJavaVM();
+ IndirectReferenceTable& globals = vm->globals;
+ MutexLock mu(vm->globals_lock);
+
+ if (!globals.Remove(IRT_FIRST_SEGMENT, obj)) {
+ LOG(WARNING) << "JNI WARNING: DeleteGlobalRef(" << obj << ") "
+ << "failed to find entry";
+ }
+}
+
+jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
+ ScopedJniThreadState ts(env);
+ if (obj == NULL) {
+ return NULL;
+ }
+
+ JavaVMExt* vm = Runtime::Current()->GetJavaVM();
+ IndirectReferenceTable& weak_globals = vm->weak_globals;
+ MutexLock mu(vm->weak_globals_lock);
+ IndirectRef ref = weak_globals.Add(IRT_FIRST_SEGMENT, Decode<Object*>(ts, obj));
+ return reinterpret_cast<jobject>(ref);
+}
+
+void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
+ ScopedJniThreadState ts(env);
+ if (obj == NULL) {
+ return;
+ }
+
+ JavaVMExt* vm = Runtime::Current()->GetJavaVM();
+ IndirectReferenceTable& weak_globals = vm->weak_globals;
+ MutexLock mu(vm->weak_globals_lock);
+
+ if (!weak_globals.Remove(IRT_FIRST_SEGMENT, obj)) {
+ LOG(WARNING) << "JNI WARNING: DeleteWeakGlobalRef(" << obj << ") "
+ << "failed to find entry";
+ }
+}
+
+jobject NewLocalRef(JNIEnv* env, jobject obj) {
+ ScopedJniThreadState ts(env);
+ if (obj == NULL) {
+ return NULL;
+ }
+
+ IndirectReferenceTable& locals = ts.Env()->locals;
+
+ uint32_t cookie = IRT_FIRST_SEGMENT; // TODO
+ IndirectRef ref = locals.Add(cookie, Decode<Object*>(ts, obj));
+ return reinterpret_cast<jobject>(ref);
}
void DeleteLocalRef(JNIEnv* env, jobject obj) {
ScopedJniThreadState ts(env);
-
if (obj == NULL) {
return;
}
@@ -701,12 +765,6 @@
return JNI_FALSE;
}
-jobject NewLocalRef(JNIEnv* env, jobject ref) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return NULL;
-}
-
jint EnsureLocalCapacity(JNIEnv* env, jint) {
ScopedJniThreadState ts(env);
UNIMPLEMENTED(FATAL);
@@ -2095,17 +2153,6 @@
UNIMPLEMENTED(FATAL);
}
-jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return NULL;
-}
-
-void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
-}
-
jboolean ExceptionCheck(JNIEnv* env) {
ScopedJniThreadState ts(env);
return ts.Self()->IsExceptionPending() ? JNI_TRUE : JNI_FALSE;
@@ -2530,9 +2577,9 @@
check_jni(check_jni),
verbose_jni(verbose_jni),
pin_table("pin table", kPinTableInitialSize, kPinTableMaxSize),
- globals_lock("JNI global reference table"),
+ globals_lock(Mutex::Create("JNI global reference table lock")),
globals(kGlobalsInitial, kGlobalsMax, kGlobal),
- weak_globals_lock("JNI weak global reference table"),
+ weak_globals_lock(Mutex::Create("JNI weak global reference table lock")),
weak_globals(kWeakGlobalsInitial, kWeakGlobalsMax, kWeakGlobal) {
}