diff options
Diffstat (limited to 'vm/JniInternal.h')
-rw-r--r-- | vm/JniInternal.h | 248 |
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*/ |