OSDN Git Service

dc17b1d3f2fe603d6db189fea1d6e292f0646292
[android-x86/dalvik.git] / vm / analysis / RegisterMap.h
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
23 #define _DALVIK_REGISTERMAP
24
25 #include "analysis/VerifySubs.h"
26 #include "analysis/CodeVerify.h"
27
28 /*
29  * Format enumeration for RegisterMap data area.
30  */
31 typedef 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 } RegisterMapFormat;
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 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 typedef 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 } RegisterMapMethodPool;
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 typedef struct RegisterMapClassPool {
181     u4      numClasses;
182
183     /* offset table starts here, 32-bit aligned; offset==0 means no data */
184     u4      classDataOffset[1];
185 } RegisterMapClassPool;
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 typedef struct RegisterMapBuilder {
213     /* public */
214     void*       data;
215     size_t      size;
216
217     /* private */
218     MemMapping  memMap;
219 } RegisterMapBuilder;
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 /*
233  * Generate the register map for a previously-verified method.
234  *
235  * Returns a pointer to a newly-allocated RegisterMap.
236  */
237 //RegisterMap* dvmGenerateRegisterMap(const Method* meth);
238
239 /*
240  * Various bits of data generated by the verifier, wrapped up in a package
241  * for ease of use by the register map generator.
242  */
243 typedef struct VerifierData {
244     /*
245      * The method we're working on.
246      */
247     const Method* method;
248
249     /*
250      * Number of instructions in the method.
251      */
252     int         insnsSize;
253
254     /*
255      * Number of registers we track for each instruction.  This is equal
256      * to the method's declared "registersSize".  (Does not include the
257      * pending return value.)
258      */
259     int         insnRegCount;
260
261     /*
262      * Instruction widths and flags, one entry per code unit.
263      */
264     InsnFlags*  insnFlags;
265
266     /*
267      * Array of SRegType arrays, one entry per code unit.  We only need
268      * entries for code units that hold the start of an "interesting"
269      * instruction.  For register map generation, we're only interested
270      * in GC points.
271      */
272     RegType**   addrRegs;
273 } VerifierData;
274
275 /*
276  * Generate the register map for a method that has just been verified
277  * (i.e. we're doing this as part of verification).
278  *
279  * Returns a pointer to a newly-allocated RegisterMap, or NULL on failure.
280  */
281 RegisterMap* dvmGenerateRegisterMapV(VerifierData* vdata);
282
283 /*
284  * Get the expanded form of the register map associated with the specified
285  * method.  May update method->registerMap, possibly freeing the previous
286  * map.
287  *
288  * Returns NULL on failure (e.g. unable to expand map).
289  *
290  * NOTE: this function is not synchronized; external locking is mandatory.
291  * (This is expected to be called at GC time.)
292  */
293 const RegisterMap* dvmGetExpandedRegisterMap0(Method* method);
294 INLINE const RegisterMap* dvmGetExpandedRegisterMap(Method* method)
295 {
296     const RegisterMap* curMap = method->registerMap;
297     if (curMap == NULL)
298         return NULL;
299     RegisterMapFormat format = dvmRegisterMapGetFormat(curMap);
300     if (format == kRegMapFormatCompact8 || format == kRegMapFormatCompact16) {
301         return curMap;
302     } else {
303         return dvmGetExpandedRegisterMap0(method);
304     }
305 }
306
307 /* dump stats gathered during register map creation process */
308 void dvmRegisterMapDumpStats(void);
309
310 #endif /*_DALVIK_REGISTERMAP*/