RegisterMap.h revision 375fb116bcb817b37509ab579dbd55cdbb765cbf
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 */
31enum 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 */
53struct 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
63bool dvmRegisterMapStartup(void);
64void dvmRegisterMapShutdown(void);
65
66/*
67 * Get the format.
68 */
69INLINE RegisterMapFormat dvmRegisterMapGetFormat(const RegisterMap* pMap) {
70    return (RegisterMapFormat)(pMap->format & ~(kRegMapFormatOnHeap));
71}
72
73/*
74 * Set the format.
75 */
76INLINE 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 */
85INLINE bool dvmRegisterMapGetOnHeap(const RegisterMap* pMap) {
86    return (pMap->format & kRegMapFormatOnHeap) != 0;
87}
88
89/*
90 * Get the register bit vector width, in bytes.
91 */
92INLINE u1 dvmRegisterMapGetRegWidth(const RegisterMap* pMap) {
93    return pMap->regWidth;
94}
95
96/*
97 * Set the register bit vector width, in bytes.
98 */
99INLINE void dvmRegisterMapSetRegWidth(RegisterMap* pMap, int regWidth) {
100    pMap->regWidth = regWidth;
101}
102
103/*
104 * Set the "on heap" flag.
105 */
106INLINE 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 */
116INLINE 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 */
123INLINE 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 */
137const 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 */
148INLINE 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 */
162struct 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 */
180struct 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 */
193const 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 */
203const 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 */
212struct 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 */
224RegisterMapBuilder* dvmGenerateRegisterMaps(DvmDex* pDvmDex);
225
226/*
227 * Free the builder.
228 */
229void 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 */
237RegisterMap* 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 */
249const RegisterMap* dvmGetExpandedRegisterMap0(Method* method);
250INLINE 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 */
264void dvmRegisterMapDumpStats(void);
265
266#endif  // DALVIK_REGISTERMAP_H_
267