OSDN Git Service

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