| /* |
| * 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*/ |