Home | History | Annotate | Download | only in vm
      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