summaryrefslogtreecommitdiff
path: root/vm/JniInternal.h
diff options
context:
space:
mode:
Diffstat (limited to 'vm/JniInternal.h')
-rw-r--r--vm/JniInternal.h248
1 files changed, 248 insertions, 0 deletions
diff --git a/vm/JniInternal.h b/vm/JniInternal.h
new file mode 100644
index 0000000..302dcb0
--- /dev/null
+++ b/vm/JniInternal.h
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * JNI innards, common to the regular and "checked" interfaces.
+ */
+#ifndef _DALVIK_JNIINTERNAL
+#define _DALVIK_JNIINTERNAL
+
+#include "jni.h"
+
+/* system init/shutdown */
+bool dvmJniStartup(void);
+void dvmJniShutdown(void);
+
+/*
+ * Our data structures for JNIEnv and JavaVM.
+ *
+ * Native code thinks it has a pointer to a pointer. We know better.
+ */
+struct JavaVMExt;
+
+typedef struct JNIEnvExt {
+ const struct JNINativeInterface* funcTable; /* must be first */
+
+ const struct JNINativeInterface* baseFuncTable;
+
+ /* pointer to the VM we are a part of */
+ struct JavaVMExt* vm;
+
+ u4 envThreadId;
+ Thread* self;
+
+ /* if nonzero, we are in a "critical" JNI call */
+ int critical;
+
+ /* keep a copy of this here for speed */
+ bool forceDataCopy;
+
+ struct JNIEnvExt* prev;
+ struct JNIEnvExt* next;
+} JNIEnvExt;
+
+typedef struct JavaVMExt {
+ const struct JNIInvokeInterface* funcTable; /* must be first */
+
+ const struct JNIInvokeInterface* baseFuncTable;
+
+ /* if multiple VMs are desired, add doubly-linked list stuff here */
+
+ /* per-VM feature flags */
+ bool useChecked;
+ bool warnError;
+ bool forceDataCopy;
+
+ /* head of list of JNIEnvs associated with this VM */
+ JNIEnvExt* envList;
+ pthread_mutex_t envListLock;
+} JavaVMExt;
+
+/*
+ * Native function return type; used by dvmPlatformInvoke().
+ *
+ * This is part of Method.jniArgInfo, and must fit in 3 bits.
+ * Note: Assembly code in arch/<arch>/Call<arch>.S relies on
+ * the enum values defined here.
+ */
+typedef enum DalvikJniReturnType {
+ DALVIK_JNI_RETURN_VOID = 0, /* must be zero */
+ DALVIK_JNI_RETURN_FLOAT = 1,
+ DALVIK_JNI_RETURN_DOUBLE = 2,
+ DALVIK_JNI_RETURN_S8 = 3,
+ DALVIK_JNI_RETURN_S4 = 4,
+ DALVIK_JNI_RETURN_S2 = 5,
+ DALVIK_JNI_RETURN_U2 = 6,
+ DALVIK_JNI_RETURN_S1 = 7
+} DalvikJniReturnType;
+
+#define DALVIK_JNI_NO_ARG_INFO 0x80000000
+#define DALVIK_JNI_RETURN_MASK 0x70000000
+#define DALVIK_JNI_RETURN_SHIFT 28
+#define DALVIK_JNI_COUNT_MASK 0x0f000000
+#define DALVIK_JNI_COUNT_SHIFT 24
+
+
+/*
+ * Pop the JNI local stack when we return from a native method. "saveArea"
+ * points to the StackSaveArea for the method we're leaving.
+ *
+ * (This may be implemented directly in assembly in mterp, so changes here
+ * may only affect the portable interpreter.)
+ */
+INLINE void dvmPopJniLocals(Thread* self, StackSaveArea* saveArea)
+{
+#ifdef USE_INDIRECT_REF
+ self->jniLocalRefTable.segmentState.all = saveArea->xtra.localRefCookie;
+#else
+ self->jniLocalRefTable.nextEntry = saveArea->xtra.localRefCookie;
+#endif
+}
+
+/*
+ * Set the envThreadId field.
+ */
+INLINE void dvmSetJniEnvThreadId(JNIEnv* pEnv, Thread* self)
+{
+ ((JNIEnvExt*)pEnv)->envThreadId = self->threadId;
+ ((JNIEnvExt*)pEnv)->self = self;
+}
+
+/*
+ * JNI call bridges. Not called directly.
+ *
+ * The "Check" versions are used when CheckJNI is enabled.
+ */
+void dvmCallJNIMethod_general(const u4* args, JValue* pResult,
+ const Method* method, Thread* self);
+void dvmCallJNIMethod_synchronized(const u4* args, JValue* pResult,
+ const Method* method, Thread* self);
+void dvmCallJNIMethod_virtualNoRef(const u4* args, JValue* pResult,
+ const Method* method, Thread* self);
+void dvmCallJNIMethod_staticNoRef(const u4* args, JValue* pResult,
+ const Method* method, Thread* self);
+void dvmCheckCallJNIMethod_general(const u4* args, JValue* pResult,
+ const Method* method, Thread* self);
+void dvmCheckCallJNIMethod_synchronized(const u4* args, JValue* pResult,
+ const Method* method, Thread* self);
+void dvmCheckCallJNIMethod_virtualNoRef(const u4* args, JValue* pResult,
+ const Method* method, Thread* self);
+void dvmCheckCallJNIMethod_staticNoRef(const u4* args, JValue* pResult,
+ const Method* method, Thread* self);
+
+/*
+ * Configure "method" to use the JNI bridge to call "func".
+ */
+void dvmUseJNIBridge(Method* method, void* func);
+
+
+/*
+ * Enable the "checked" versions.
+ */
+void dvmUseCheckedJniEnv(JNIEnvExt* pEnv);
+void dvmUseCheckedJniVm(JavaVMExt* pVm);
+void dvmLateEnableCheckedJni(void);
+
+/*
+ * Decode a local, global, or weak-global reference.
+ */
+#ifdef USE_INDIRECT_REF
+Object* dvmDecodeIndirectRef(JNIEnv* env, jobject jobj);
+#else
+/* use an inline to ensure this is a no-op */
+INLINE Object* dvmDecodeIndirectRef(JNIEnv* env, jobject jobj) {
+ return (Object*) jobj;
+}
+#endif
+
+/*
+ * Verify that a reference passed in from native code is valid. Returns
+ * an indication of local/global/invalid.
+ */
+jobjectRefType dvmGetJNIRefType(JNIEnv* env, jobject jobj);
+
+/*
+ * Get the last method called on the interp stack. This is the method
+ * "responsible" for calling into JNI.
+ */
+const Method* dvmGetCurrentJNIMethod(void);
+
+/*
+ * Create/destroy a JNIEnv for the current thread.
+ */
+JNIEnv* dvmCreateJNIEnv(Thread* self);
+void dvmDestroyJNIEnv(JNIEnv* env);
+
+/*
+ * Find the JNIEnv associated with the current thread.
+ */
+JNIEnvExt* dvmGetJNIEnvForThread(void);
+
+/*
+ * Extract the return type enum from the "jniArgInfo" value.
+ */
+DalvikJniReturnType dvmGetArgInfoReturnType(int jniArgInfo);
+
+/*
+ * Release all MonitorEnter-acquired locks that are still held. Called at
+ * DetachCurrentThread time.
+ */
+void dvmReleaseJniMonitors(Thread* self);
+
+/*
+ * Dump the contents of the JNI reference tables to the log file.
+ *
+ * The local ref tables associated with other threads are not included.
+ */
+void dvmDumpJniReferenceTables(void);
+
+/*
+ * This mask is applied to weak global reference values returned to
+ * native code. The goal is to create an invalid pointer that will cause
+ * a crash if misused. The mmap region for the virtual heap is typically
+ * around 0x40xxxxxx.
+ *
+ * To make weak global references easily distinguishable from other kinds
+ * of references when !USE_INDIRECT_REF, we XOR the low bits. Assuming >=
+ * 64-bit alignment of objects, this changes the low 3 bits from all clear
+ * to all set.
+ */
+#define WEAK_GLOBAL_XOR 0x9e0fffff
+
+/*
+ * "Obfuscate" a weak global reference pointer.
+ */
+INLINE jweak dvmObfuscateWeakGlobalRef(jobject jobj) {
+ return (jweak) ((u4) jobj ^ WEAK_GLOBAL_XOR);
+}
+
+/*
+ * Undo the obfuscation.
+ */
+INLINE jobject dvmNormalizeWeakGlobalRef(jweak ref) {
+ return (jobject) ((u4) ref ^ WEAK_GLOBAL_XOR);
+}
+
+/*
+ * Returns "true" if this looks like a weak global reference.
+ *
+ * Relies on the low 3 bits being set instead of clear (the latter is
+ * guaranteed by 64-bit alignment of objects).
+ */
+INLINE bool dvmIsWeakGlobalRef(jobject jobj) {
+ return (((u4) jobj & 0x07) == 0x07);
+}
+
+#endif /*_DALVIK_JNIINTERNAL*/