1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 /* 17 * JNI innards, common to the regular and "checked" interfaces. 18 */ 19 #ifndef _DALVIK_JNIINTERNAL 20 #define _DALVIK_JNIINTERNAL 21 22 #include "jni.h" 23 24 /* system init/shutdown */ 25 bool dvmJniStartup(void); 26 void dvmJniShutdown(void); 27 28 /* 29 * Our data structures for JNIEnv and JavaVM. 30 * 31 * Native code thinks it has a pointer to a pointer. We know better. 32 */ 33 struct JavaVMExt; 34 35 typedef struct JNIEnvExt { 36 const struct JNINativeInterface* funcTable; /* must be first */ 37 38 const struct JNINativeInterface* baseFuncTable; 39 40 /* pointer to the VM we are a part of */ 41 struct JavaVMExt* vm; 42 43 u4 envThreadId; 44 Thread* self; 45 46 /* if nonzero, we are in a "critical" JNI call */ 47 int critical; 48 49 /* keep a copy of this here for speed */ 50 bool forceDataCopy; 51 52 struct JNIEnvExt* prev; 53 struct JNIEnvExt* next; 54 } JNIEnvExt; 55 56 typedef struct JavaVMExt { 57 const struct JNIInvokeInterface* funcTable; /* must be first */ 58 59 const struct JNIInvokeInterface* baseFuncTable; 60 61 /* if multiple VMs are desired, add doubly-linked list stuff here */ 62 63 /* per-VM feature flags */ 64 bool useChecked; 65 bool warnError; 66 bool forceDataCopy; 67 68 /* head of list of JNIEnvs associated with this VM */ 69 JNIEnvExt* envList; 70 pthread_mutex_t envListLock; 71 } JavaVMExt; 72 73 /* 74 * Native function return type; used by dvmPlatformInvoke(). 75 * 76 * This is part of Method.jniArgInfo, and must fit in 3 bits. 77 * Note: Assembly code in arch/<arch>/Call<arch>.S relies on 78 * the enum values defined here. 79 */ 80 typedef enum DalvikJniReturnType { 81 DALVIK_JNI_RETURN_VOID = 0, /* must be zero */ 82 DALVIK_JNI_RETURN_FLOAT = 1, 83 DALVIK_JNI_RETURN_DOUBLE = 2, 84 DALVIK_JNI_RETURN_S8 = 3, 85 DALVIK_JNI_RETURN_S4 = 4, 86 DALVIK_JNI_RETURN_S2 = 5, 87 DALVIK_JNI_RETURN_U2 = 6, 88 DALVIK_JNI_RETURN_S1 = 7 89 } DalvikJniReturnType; 90 91 #define DALVIK_JNI_NO_ARG_INFO 0x80000000 92 #define DALVIK_JNI_RETURN_MASK 0x70000000 93 #define DALVIK_JNI_RETURN_SHIFT 28 94 #define DALVIK_JNI_COUNT_MASK 0x0f000000 95 #define DALVIK_JNI_COUNT_SHIFT 24 96 97 98 /* 99 * Pop the JNI local stack when we return from a native method. "saveArea" 100 * points to the StackSaveArea for the method we're leaving. 101 * 102 * (This may be implemented directly in assembly in mterp, so changes here 103 * may only affect the portable interpreter.) 104 */ 105 INLINE void dvmPopJniLocals(Thread* self, StackSaveArea* saveArea) 106 { 107 #ifdef USE_INDIRECT_REF 108 self->jniLocalRefTable.segmentState.all = saveArea->xtra.localRefCookie; 109 #else 110 self->jniLocalRefTable.nextEntry = saveArea->xtra.localRefCookie; 111 #endif 112 } 113 114 /* 115 * Set the envThreadId field. 116 */ 117 INLINE void dvmSetJniEnvThreadId(JNIEnv* pEnv, Thread* self) 118 { 119 ((JNIEnvExt*)pEnv)->envThreadId = self->threadId; 120 ((JNIEnvExt*)pEnv)->self = self; 121 } 122 123 /* 124 * JNI call bridges. Not called directly. 125 * 126 * The "Check" versions are used when CheckJNI is enabled. 127 */ 128 void dvmCallJNIMethod_general(const u4* args, JValue* pResult, 129 const Method* method, Thread* self); 130 void dvmCallJNIMethod_synchronized(const u4* args, JValue* pResult, 131 const Method* method, Thread* self); 132 void dvmCallJNIMethod_virtualNoRef(const u4* args, JValue* pResult, 133 const Method* method, Thread* self); 134 void dvmCallJNIMethod_staticNoRef(const u4* args, JValue* pResult, 135 const Method* method, Thread* self); 136 void dvmCheckCallJNIMethod_general(const u4* args, JValue* pResult, 137 const Method* method, Thread* self); 138 void dvmCheckCallJNIMethod_synchronized(const u4* args, JValue* pResult, 139 const Method* method, Thread* self); 140 void dvmCheckCallJNIMethod_virtualNoRef(const u4* args, JValue* pResult, 141 const Method* method, Thread* self); 142 void dvmCheckCallJNIMethod_staticNoRef(const u4* args, JValue* pResult, 143 const Method* method, Thread* self); 144 145 /* 146 * Configure "method" to use the JNI bridge to call "func". 147 */ 148 void dvmUseJNIBridge(Method* method, void* func); 149 150 151 /* 152 * Enable the "checked" versions. 153 */ 154 void dvmUseCheckedJniEnv(JNIEnvExt* pEnv); 155 void dvmUseCheckedJniVm(JavaVMExt* pVm); 156 void dvmLateEnableCheckedJni(void); 157 158 /* 159 * Decode a local, global, or weak-global reference. 160 */ 161 #ifdef USE_INDIRECT_REF 162 Object* dvmDecodeIndirectRef(JNIEnv* env, jobject jobj); 163 #else 164 /* use an inline to ensure this is a no-op */ 165 INLINE Object* dvmDecodeIndirectRef(JNIEnv* env, jobject jobj) { 166 return (Object*) jobj; 167 } 168 #endif 169 170 /* 171 * Verify that a reference passed in from native code is valid. Returns 172 * an indication of local/global/invalid. 173 */ 174 jobjectRefType dvmGetJNIRefType(JNIEnv* env, jobject jobj); 175 176 /* 177 * Get the last method called on the interp stack. This is the method 178 * "responsible" for calling into JNI. 179 */ 180 const Method* dvmGetCurrentJNIMethod(void); 181 182 /* 183 * Create/destroy a JNIEnv for the current thread. 184 */ 185 JNIEnv* dvmCreateJNIEnv(Thread* self); 186 void dvmDestroyJNIEnv(JNIEnv* env); 187 188 /* 189 * Find the JNIEnv associated with the current thread. 190 */ 191 JNIEnvExt* dvmGetJNIEnvForThread(void); 192 193 /* 194 * Extract the return type enum from the "jniArgInfo" value. 195 */ 196 DalvikJniReturnType dvmGetArgInfoReturnType(int jniArgInfo); 197 198 /* 199 * Release all MonitorEnter-acquired locks that are still held. Called at 200 * DetachCurrentThread time. 201 */ 202 void dvmReleaseJniMonitors(Thread* self); 203 204 /* 205 * Dump the contents of the JNI reference tables to the log file. 206 * 207 * The local ref tables associated with other threads are not included. 208 */ 209 void dvmDumpJniReferenceTables(void); 210 211 /* 212 * This mask is applied to weak global reference values returned to 213 * native code. The goal is to create an invalid pointer that will cause 214 * a crash if misused. The mmap region for the virtual heap is typically 215 * around 0x40xxxxxx. 216 * 217 * To make weak global references easily distinguishable from other kinds 218 * of references when !USE_INDIRECT_REF, we XOR the low bits. Assuming >= 219 * 64-bit alignment of objects, this changes the low 3 bits from all clear 220 * to all set. 221 */ 222 #define WEAK_GLOBAL_XOR 0x9e0fffff 223 224 /* 225 * "Obfuscate" a weak global reference pointer. 226 */ 227 INLINE jweak dvmObfuscateWeakGlobalRef(jobject jobj) { 228 return (jweak) ((u4) jobj ^ WEAK_GLOBAL_XOR); 229 } 230 231 /* 232 * Undo the obfuscation. 233 */ 234 INLINE jobject dvmNormalizeWeakGlobalRef(jweak ref) { 235 return (jobject) ((u4) ref ^ WEAK_GLOBAL_XOR); 236 } 237 238 /* 239 * Returns "true" if this looks like a weak global reference. 240 * 241 * Relies on the low 3 bits being set instead of clear (the latter is 242 * guaranteed by 64-bit alignment of objects). 243 */ 244 INLINE bool dvmIsWeakGlobalRef(jobject jobj) { 245 return (((u4) jobj & 0x07) == 0x07); 246 } 247 248 #endif /*_DALVIK_JNIINTERNAL*/ 249