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 /*
     18  * The VM wraps some additional data structures around the DexFile.  These
     19  * are defined here.
     20  */
     21 #ifndef _DALVIK_DVMDEX
     22 #define _DALVIK_DVMDEX
     23 
     24 #include "libdex/DexFile.h"
     25 
     26 /* extern */
     27 struct ClassObject;
     28 struct HashTable;
     29 struct InstField;
     30 struct Method;
     31 struct StringObject;
     32 
     33 
     34 /*
     35  * Some additional VM data structures that are associated with the DEX file.
     36  */
     37 typedef struct DvmDex {
     38     /* pointer to the DexFile we're associated with */
     39     DexFile*            pDexFile;
     40 
     41     /* clone of pDexFile->pHeader (it's used frequently enough) */
     42     const DexHeader*    pHeader;
     43 
     44     /* interned strings; parallel to "stringIds" */
     45     struct StringObject** pResStrings;
     46 
     47     /* resolved classes; parallel to "typeIds" */
     48     struct ClassObject** pResClasses;
     49 
     50     /* resolved methods; parallel to "methodIds" */
     51     struct Method**     pResMethods;
     52 
     53     /* resolved instance fields; parallel to "fieldIds" */
     54     /* (this holds both InstField and StaticField) */
     55     struct Field**      pResFields;
     56 
     57     /* interface method lookup cache */
     58     struct AtomicCache* pInterfaceCache;
     59 
     60     /* shared memory region with file contents */
     61     MemMapping          memMap;
     62 } DvmDex;
     63 
     64 
     65 /*
     66  * Given a file descriptor for an open "optimized" DEX file, map it into
     67  * memory and parse the contents.
     68  *
     69  * On success, returns 0 and sets "*ppDvmDex" to a newly-allocated DvmDex.
     70  * On failure, returns a meaningful error code [currently just -1].
     71  */
     72 int dvmDexFileOpenFromFd(int fd, DvmDex** ppDvmDex);
     73 
     74 /*
     75  * Open a partial DEX file.  Only useful as part of the optimization process.
     76  */
     77 int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex);
     78 
     79 /*
     80  * Free a DvmDex structure, along with any associated structures.
     81  */
     82 void dvmDexFileFree(DvmDex* pDvmDex);
     83 
     84 
     85 /*
     86  * Change the 1- or 2-byte value at the specified address to a new value.  If
     87  * the location already has the new value, do nothing.
     88  *
     89  * This does not make any synchronization guarantees.  The caller must
     90  * ensure exclusivity vs. other callers.
     91  *
     92  * For the 2-byte call, the pointer should have 16-bit alignment.
     93  *
     94  * Returns "true" on success.
     95  */
     96 bool dvmDexChangeDex1(DvmDex* pDvmDex, u1* addr, u1 newVal);
     97 bool dvmDexChangeDex2(DvmDex* pDvmDex, u2* addr, u2 newVal);
     98 
     99 
    100 #if DVM_RESOLVER_CACHE == DVM_RC_DISABLED
    101 /* 1:1 mapping */
    102 
    103 /*
    104  * Return the requested item if it has been resolved, or NULL if it hasn't.
    105  */
    106 INLINE struct StringObject* dvmDexGetResolvedString(const DvmDex* pDvmDex,
    107     u4 stringIdx)
    108 {
    109     assert(stringIdx < pDvmDex->pHeader->stringIdsSize);
    110     return pDvmDex->pResStrings[stringIdx];
    111 }
    112 INLINE struct ClassObject* dvmDexGetResolvedClass(const DvmDex* pDvmDex,
    113     u4 classIdx)
    114 {
    115     assert(classIdx < pDvmDex->pHeader->typeIdsSize);
    116     return pDvmDex->pResClasses[classIdx];
    117 }
    118 INLINE struct Method* dvmDexGetResolvedMethod(const DvmDex* pDvmDex,
    119     u4 methodIdx)
    120 {
    121     assert(methodIdx < pDvmDex->pHeader->methodIdsSize);
    122     return pDvmDex->pResMethods[methodIdx];
    123 }
    124 INLINE struct Field* dvmDexGetResolvedField(const DvmDex* pDvmDex,
    125     u4 fieldIdx)
    126 {
    127     assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize);
    128     return pDvmDex->pResFields[fieldIdx];
    129 }
    130 
    131 /*
    132  * Update the resolved item table.  Resolution always produces the same
    133  * result, so we're not worried about atomicity here.
    134  */
    135 INLINE void dvmDexSetResolvedString(DvmDex* pDvmDex, u4 stringIdx,
    136     struct StringObject* str)
    137 {
    138     assert(stringIdx < pDvmDex->pHeader->stringIdsSize);
    139     pDvmDex->pResStrings[stringIdx] = str;
    140 }
    141 INLINE void dvmDexSetResolvedClass(DvmDex* pDvmDex, u4 classIdx,
    142     struct ClassObject* clazz)
    143 {
    144     assert(classIdx < pDvmDex->pHeader->typeIdsSize);
    145     pDvmDex->pResClasses[classIdx] = clazz;
    146 }
    147 INLINE void dvmDexSetResolvedMethod(DvmDex* pDvmDex, u4 methodIdx,
    148     struct Method* method)
    149 {
    150     assert(methodIdx < pDvmDex->pHeader->methodIdsSize);
    151     pDvmDex->pResMethods[methodIdx] = method;
    152 }
    153 INLINE void dvmDexSetResolvedField(DvmDex* pDvmDex, u4 fieldIdx,
    154     struct Field* field)
    155 {
    156     assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize);
    157     pDvmDex->pResFields[fieldIdx] = field;
    158 }
    159 
    160 #elif DVM_RESOLVER_CACHE == DVM_RC_REDUCING
    161 /* reduce request to fit in a less-than-full-size cache table */
    162 
    163 /*
    164  * Return the requested item if it has been resolved, or NULL if it hasn't.
    165  *
    166  * If we have a mapping table defined for this category, but there's no
    167  * entry for this index, we always return NULL.  Otherwise, we return the
    168  * entry.  (To regain some performance we may want to assume that the
    169  * table exists when compiled in this mode -- avoids a null check but
    170  * prevents us from switching back and forth without rebuilding the VM.)
    171  *
    172  * We could save an integer compare here by ensuring that map[kNoIndexMapping]
    173  * always evalutes to NULL (e.g. set kNoIndexMapping = 0).
    174  */
    175 INLINE struct StringObject* dvmDexGetResolvedString(const DvmDex* pDvmDex,
    176     u4 stringIdx)
    177 {
    178     const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
    179 
    180     assert(stringIdx < pDvmDex->pHeader->stringIdsSize);
    181     if (pIndexMap->stringReducedCount > 0) {
    182         stringIdx = pIndexMap->stringMap[stringIdx];
    183         if (stringIdx == kNoIndexMapping)
    184             return NULL;
    185     }
    186     return pDvmDex->pResStrings[stringIdx];
    187 }
    188 INLINE struct ClassObject* dvmDexGetResolvedClass(const DvmDex* pDvmDex,
    189     u4 classIdx)
    190 {
    191     const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
    192 
    193     assert(classIdx < pDvmDex->pHeader->typeIdsSize);
    194     if (pIndexMap->classReducedCount > 0) {
    195         classIdx = pIndexMap->classMap[classIdx];
    196         if (classIdx == kNoIndexMapping)
    197             return NULL;
    198     }
    199     return pDvmDex->pResClasses[classIdx];
    200 }
    201 INLINE struct Method* dvmDexGetResolvedMethod(const DvmDex* pDvmDex,
    202     u4 methodIdx)
    203 {
    204     const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
    205 
    206     assert(methodIdx < pDvmDex->pHeader->methodIdsSize);
    207     if (pIndexMap->methodReducedCount > 0) {
    208         methodIdx = pIndexMap->methodMap[methodIdx];
    209         if (methodIdx == kNoIndexMapping)
    210             return NULL;
    211     }
    212     return pDvmDex->pResMethods[methodIdx];
    213 }
    214 INLINE struct Field* dvmDexGetResolvedField(const DvmDex* pDvmDex,
    215     u4 fieldIdx)
    216 {
    217     const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
    218 
    219     assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize);
    220     if (pIndexMap->fieldReducedCount > 0) {
    221         fieldIdx = pIndexMap->fieldMap[fieldIdx];
    222         if (fieldIdx == kNoIndexMapping)
    223             return NULL;
    224     }
    225     return pDvmDex->pResFields[fieldIdx];
    226 }
    227 
    228 /*
    229  * Update the resolved item table.  Resolution always produces the same
    230  * result, so we're not worried about atomicity here.
    231  */
    232 INLINE void dvmDexSetResolvedString(DvmDex* pDvmDex, u4 stringIdx,
    233     struct StringObject* str)
    234 {
    235     const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
    236     u4 newIdx;
    237 
    238     assert(stringIdx < pDvmDex->pHeader->stringIdsSize);
    239     if (pIndexMap->stringReducedCount > 0) {
    240         newIdx = pIndexMap->stringMap[stringIdx];
    241         if (newIdx != kNoIndexMapping)
    242             pDvmDex->pResStrings[newIdx] = str;
    243     }
    244 }
    245 INLINE void dvmDexSetResolvedClass(DvmDex* pDvmDex, u4 classIdx,
    246     struct ClassObject* clazz)
    247 {
    248     const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
    249     u4 newIdx;
    250 
    251     assert(classIdx < pDvmDex->pHeader->typeIdsSize);
    252     if (pIndexMap->classReducedCount > 0) {
    253         newIdx = pIndexMap->classMap[classIdx];
    254         if (newIdx != kNoIndexMapping)
    255             pDvmDex->pResClasses[newIdx] = clazz;
    256     }
    257 }
    258 INLINE void dvmDexSetResolvedMethod(DvmDex* pDvmDex, u4 methodIdx,
    259     struct Method* method)
    260 {
    261     const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
    262     u4 newIdx;
    263 
    264     assert(methodIdx < pDvmDex->pHeader->methodIdsSize);
    265     if (pIndexMap->methodReducedCount > 0) {
    266         newIdx = pIndexMap->methodMap[methodIdx];
    267         if (newIdx != kNoIndexMapping)
    268             pDvmDex->pResMethods[newIdx] = method;
    269     }
    270 }
    271 INLINE void dvmDexSetResolvedField(DvmDex* pDvmDex, u4 fieldIdx,
    272     struct Field* field)
    273 {
    274     const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
    275     u4 newIdx;
    276 
    277     assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize);
    278     if (pIndexMap->fieldReducedCount > 0) {
    279         newIdx = pIndexMap->fieldMap[fieldIdx];
    280         if (newIdx != kNoIndexMapping)
    281             pDvmDex->pResFields[newIdx] = field;
    282     }
    283 }
    284 
    285 #elif DVM_RESOLVER_CACHE == DVM_RC_EXPANDING
    286 
    287 #error "not implemented"    /* TODO */
    288 
    289 #elif DVM_RESOLVER_CACHE == DVM_RC_NO_CACHE
    290 
    291 /*
    292  * There's no cache, so we always return NULL.
    293  */
    294 INLINE struct StringObject* dvmDexGetResolvedString(const DvmDex* pDvmDex,
    295     u4 stringIdx)
    296 {
    297     return NULL;
    298 }
    299 INLINE struct ClassObject* dvmDexGetResolvedClass(const DvmDex* pDvmDex,
    300     u4 classIdx)
    301 {
    302     return NULL;
    303 }
    304 INLINE struct Method* dvmDexGetResolvedMethod(const DvmDex* pDvmDex,
    305     u4 methodIdx)
    306 {
    307     return NULL;
    308 }
    309 INLINE struct Field* dvmDexGetResolvedField(const DvmDex* pDvmDex,
    310     u4 fieldIdx)
    311 {
    312     return NULL;
    313 }
    314 
    315 /*
    316  * Update the resolved item table.  There is no table, so do nothing.
    317  */
    318 INLINE void dvmDexSetResolvedString(DvmDex* pDvmDex, u4 stringIdx,
    319     struct StringObject* str)
    320 {}
    321 INLINE void dvmDexSetResolvedClass(DvmDex* pDvmDex, u4 classIdx,
    322     struct ClassObject* clazz)
    323 {}
    324 INLINE void dvmDexSetResolvedMethod(DvmDex* pDvmDex, u4 methodIdx,
    325     struct Method* method)
    326 {}
    327 INLINE void dvmDexSetResolvedField(DvmDex* pDvmDex, u4 fieldIdx,
    328     struct Field* field)
    329 {}
    330 
    331 #else
    332 #error "huh?"
    333 #endif /*DVM_RESOLVER_CACHE==N*/
    334 
    335 #endif /*_DALVIK_DVMDEX*/
    336