Home | History | Annotate | Download | only in analysis
      1 /*
      2  * Copyright (C) 2009 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  * Declaration of register map data structure and related functions.
     19  *
     20  * These structures should be treated as opaque through most of the VM.
     21  */
     22 #ifndef DALVIK_REGISTERMAP_H_
     23 #define DALVIK_REGISTERMAP_H_
     24 
     25 #include "analysis/VerifySubs.h"
     26 #include "analysis/CodeVerify.h"
     27 
     28 /*
     29  * Format enumeration for RegisterMap data area.
     30  */
     31 enum RegisterMapFormat {
     32     kRegMapFormatUnknown = 0,
     33     kRegMapFormatNone,          /* indicates no map data follows */
     34     kRegMapFormatCompact8,      /* compact layout, 8-bit addresses */
     35     kRegMapFormatCompact16,     /* compact layout, 16-bit addresses */
     36     kRegMapFormatDifferential,  /* compressed, differential encoding */
     37 
     38     kRegMapFormatOnHeap = 0x80, /* bit flag, indicates allocation on heap */
     39 };
     40 
     41 /*
     42  * This is a single variable-size structure.  It may be allocated on the
     43  * heap or mapped out of a (post-dexopt) DEX file.
     44  *
     45  * 32-bit alignment of the structure is NOT guaranteed.  This makes it a
     46  * little awkward to deal with as a structure; to avoid accidents we use
     47  * only byte types.  Multi-byte values are little-endian.
     48  *
     49  * Size of (format==FormatNone): 1 byte
     50  * Size of (format==FormatCompact8): 4 + (1 + regWidth) * numEntries
     51  * Size of (format==FormatCompact16): 4 + (2 + regWidth) * numEntries
     52  */
     53 struct RegisterMap {
     54     /* header */
     55     u1      format;         /* enum RegisterMapFormat; MUST be first entry */
     56     u1      regWidth;       /* bytes per register line, 1+ */
     57     u1      numEntries[2];  /* number of entries */
     58 
     59     /* raw data starts here; need not be aligned */
     60     u1      data[1];
     61 };
     62 
     63 bool dvmRegisterMapStartup(void);
     64 void dvmRegisterMapShutdown(void);
     65 
     66 /*
     67  * Get the format.
     68  */
     69 INLINE RegisterMapFormat dvmRegisterMapGetFormat(const RegisterMap* pMap) {
     70     return (RegisterMapFormat)(pMap->format & ~(kRegMapFormatOnHeap));
     71 }
     72 
     73 /*
     74  * Set the format.
     75  */
     76 INLINE void dvmRegisterMapSetFormat(RegisterMap* pMap, RegisterMapFormat format)
     77 {
     78     pMap->format &= kRegMapFormatOnHeap;
     79     pMap->format |= format;
     80 }
     81 
     82 /*
     83  * Get the "on heap" flag.
     84  */
     85 INLINE bool dvmRegisterMapGetOnHeap(const RegisterMap* pMap) {
     86     return (pMap->format & kRegMapFormatOnHeap) != 0;
     87 }
     88 
     89 /*
     90  * Get the register bit vector width, in bytes.
     91  */
     92 INLINE u1 dvmRegisterMapGetRegWidth(const RegisterMap* pMap) {
     93     return pMap->regWidth;
     94 }
     95 
     96 /*
     97  * Set the register bit vector width, in bytes.
     98  */
     99 INLINE void dvmRegisterMapSetRegWidth(RegisterMap* pMap, int regWidth) {
    100     pMap->regWidth = regWidth;
    101 }
    102 
    103 /*
    104  * Set the "on heap" flag.
    105  */
    106 INLINE void dvmRegisterMapSetOnHeap(RegisterMap* pMap, bool val) {
    107     if (val)
    108         pMap->format |= kRegMapFormatOnHeap;
    109     else
    110         pMap->format &= ~(kRegMapFormatOnHeap);
    111 }
    112 
    113 /*
    114  * Get the number of entries in this map.
    115  */
    116 INLINE u2 dvmRegisterMapGetNumEntries(const RegisterMap* pMap) {
    117     return pMap->numEntries[0] | (pMap->numEntries[1] << 8);
    118 }
    119 
    120 /*
    121  * Set the number of entries in this map.
    122  */
    123 INLINE void dvmRegisterMapSetNumEntries(RegisterMap* pMap, u2 numEntries) {
    124     pMap->numEntries[0] = (u1) numEntries;
    125     pMap->numEntries[1] = numEntries >> 8;
    126 }
    127 
    128 /*
    129  * Retrieve the bit vector for the specified address.  This is a pointer
    130  * to the bit data from an uncompressed map, or to a temporary copy of
    131  * data from a compressed map.
    132  *
    133  * The caller must call dvmReleaseRegisterMapLine() with the result.
    134  *
    135  * Returns NULL if not found.
    136  */
    137 const u1* dvmRegisterMapGetLine(const RegisterMap* pMap, int addr);
    138 
    139 /*
    140  * Release "data".
    141  *
    142  * If "pMap" points to a compressed map from which we have expanded a
    143  * single line onto the heap, this will free "data"; otherwise, it does
    144  * nothing.
    145  *
    146  * TODO: decide if this is still a useful concept.
    147  */
    148 INLINE void dvmReleaseRegisterMapLine(const RegisterMap* pMap, const u1* data)
    149 {}
    150 
    151 
    152 /*
    153  * A pool of register maps for methods associated with a single class.
    154  *
    155  * Each entry is a 4-byte method index followed by the 32-bit-aligned
    156  * RegisterMap.  The size of the RegisterMap is determined by parsing
    157  * the map.  The lack of an index reduces random access speed, but we
    158  * should be doing that rarely (during class load) and it saves space.
    159  *
    160  * These structures are 32-bit aligned.
    161  */
    162 struct RegisterMapMethodPool {
    163     u2      methodCount;            /* chiefly used as a sanity check */
    164 
    165     /* stream of per-method data starts here */
    166     u4      methodData[1];
    167 };
    168 
    169 /*
    170  * Header for the memory-mapped RegisterMap pool in the DEX file.
    171  *
    172  * The classDataOffset table provides offsets from the start of the
    173  * RegisterMapPool structure.  There is one entry per class (including
    174  * interfaces, which can have static initializers).
    175  *
    176  * The offset points to a RegisterMapMethodPool.
    177  *
    178  * These structures are 32-bit aligned.
    179  */
    180 struct RegisterMapClassPool {
    181     u4      numClasses;
    182 
    183     /* offset table starts here, 32-bit aligned; offset==0 means no data */
    184     u4      classDataOffset[1];
    185 };
    186 
    187 /*
    188  * Find the register maps for this class.  (Used during class loading.)
    189  * If "pNumMaps" is non-NULL, it will return the number of maps in the set.
    190  *
    191  * Returns NULL if none is available.
    192  */
    193 const void* dvmRegisterMapGetClassData(const DexFile* pDexFile, u4 classIdx,
    194     u4* pNumMaps);
    195 
    196 /*
    197  * Get the register map for the next method.  "*pPtr" will be advanced past
    198  * the end of the map.  (Used during class loading.)
    199  *
    200  * This should initially be called with the result from
    201  * dvmRegisterMapGetClassData().
    202  */
    203 const RegisterMap* dvmRegisterMapGetNext(const void** pPtr);
    204 
    205 /*
    206  * This holds some meta-data while we construct the set of register maps
    207  * for a DEX file.
    208  *
    209  * In particular, it keeps track of our temporary mmap region so we can
    210  * free it later.
    211  */
    212 struct RegisterMapBuilder {
    213     /* public */
    214     void*       data;
    215     size_t      size;
    216 
    217     /* private */
    218     MemMapping  memMap;
    219 };
    220 
    221 /*
    222  * Generate a register map set for all verified classes in "pDvmDex".
    223  */
    224 RegisterMapBuilder* dvmGenerateRegisterMaps(DvmDex* pDvmDex);
    225 
    226 /*
    227  * Free the builder.
    228  */
    229 void dvmFreeRegisterMapBuilder(RegisterMapBuilder* pBuilder);
    230 
    231 /*
    232  * Generate the register map for a method that has just been verified
    233  * (i.e. we're doing this as part of verification).
    234  *
    235  * Returns a pointer to a newly-allocated RegisterMap, or NULL on failure.
    236  */
    237 RegisterMap* dvmGenerateRegisterMapV(VerifierData* vdata);
    238 
    239 /*
    240  * Get the expanded form of the register map associated with the specified
    241  * method.  May update method->registerMap, possibly freeing the previous
    242  * map.
    243  *
    244  * Returns NULL on failure (e.g. unable to expand map).
    245  *
    246  * NOTE: this function is not synchronized; external locking is mandatory.
    247  * (This is expected to be called at GC time.)
    248  */
    249 const RegisterMap* dvmGetExpandedRegisterMap0(Method* method);
    250 INLINE const RegisterMap* dvmGetExpandedRegisterMap(Method* method)
    251 {
    252     const RegisterMap* curMap = method->registerMap;
    253     if (curMap == NULL)
    254         return NULL;
    255     RegisterMapFormat format = dvmRegisterMapGetFormat(curMap);
    256     if (format == kRegMapFormatCompact8 || format == kRegMapFormatCompact16) {
    257         return curMap;
    258     } else {
    259         return dvmGetExpandedRegisterMap0(method);
    260     }
    261 }
    262 
    263 /* dump stats gathered during register map creation process */
    264 void dvmRegisterMapDumpStats(void);
    265 
    266 #endif  // DALVIK_REGISTERMAP_H_
    267