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