OSDN Git Service

Merge change 21907 into eclair
[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  * The VM wraps some additional data structures around the DexFile.  These
18  * are defined here.
19  */
20 #ifndef _DALVIK_DVMDEX
21 #define _DALVIK_DVMDEX
22
23 #include "libdex/DexFile.h"
24
25 /* extern */
26 struct ClassObject;
27 struct HashTable;
28 struct InstField;
29 struct Method;
30 struct StringObject;
31
32
33 /*
34  * Some additional VM data structures that are associated with the DEX file.
35  */
36 typedef struct DvmDex {
37     /* pointer to the DexFile we're associated with */
38     DexFile*            pDexFile;
39
40     /* clone of pDexFile->pHeader (it's used frequently enough) */
41     const DexHeader*    pHeader;
42
43     /* interned strings; parallel to "stringIds" */
44     struct StringObject** pResStrings;
45
46     /* resolved classes; parallel to "typeIds" */
47     struct ClassObject** pResClasses;
48
49     /* resolved methods; parallel to "methodIds" */
50     struct Method**     pResMethods;
51
52     /* resolved instance fields; parallel to "fieldIds" */
53     /* (this holds both InstField and StaticField) */
54     struct Field**      pResFields;
55
56     /* interface method lookup cache */
57     struct AtomicCache* pInterfaceCache;
58
59     /* shared memory region with file contents */
60     MemMapping          memMap;
61 } DvmDex;
62
63
64 /*
65  * Given a file descriptor for an open "optimized" DEX file, map it into
66  * memory and parse the contents.
67  *
68  * On success, returns 0 and sets "*ppDvmDex" to a newly-allocated DvmDex.
69  * On failure, returns a meaningful error code [currently just -1].
70  */
71 int dvmDexFileOpenFromFd(int fd, DvmDex** ppDvmDex);
72
73 /*
74  * Open a partial DEX file.  Only useful as part of the optimization process.
75  */
76 int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex);
77
78 /*
79  * Free a DvmDex structure, along with any associated structures.
80  */
81 void dvmDexFileFree(DvmDex* pDvmDex);
82
83
84 #if DVM_RESOLVER_CACHE == DVM_RC_DISABLED
85 /* 1:1 mapping */
86
87 /*
88  * Return the requested item if it has been resolved, or NULL if it hasn't.
89  */
90 INLINE struct StringObject* dvmDexGetResolvedString(const DvmDex* pDvmDex,
91     u4 stringIdx)
92 {
93     assert(stringIdx < pDvmDex->pHeader->stringIdsSize);
94     return pDvmDex->pResStrings[stringIdx];
95 }
96 INLINE struct ClassObject* dvmDexGetResolvedClass(const DvmDex* pDvmDex,
97     u4 classIdx)
98 {
99     assert(classIdx < pDvmDex->pHeader->typeIdsSize);
100     return pDvmDex->pResClasses[classIdx];
101 }
102 INLINE struct Method* dvmDexGetResolvedMethod(const DvmDex* pDvmDex,
103     u4 methodIdx)
104 {
105     assert(methodIdx < pDvmDex->pHeader->methodIdsSize);
106     return pDvmDex->pResMethods[methodIdx];
107 }
108 INLINE struct Field* dvmDexGetResolvedField(const DvmDex* pDvmDex,
109     u4 fieldIdx)
110 {
111     assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize);
112     return pDvmDex->pResFields[fieldIdx];
113 }
114
115 /*
116  * Update the resolved item table.  Resolution always produces the same
117  * result, so we're not worried about atomicity here.
118  */
119 INLINE void dvmDexSetResolvedString(DvmDex* pDvmDex, u4 stringIdx,
120     struct StringObject* str)
121 {
122     assert(stringIdx < pDvmDex->pHeader->stringIdsSize);
123     pDvmDex->pResStrings[stringIdx] = str;
124 }
125 INLINE void dvmDexSetResolvedClass(DvmDex* pDvmDex, u4 classIdx,
126     struct ClassObject* clazz)
127 {
128     assert(classIdx < pDvmDex->pHeader->typeIdsSize);
129     pDvmDex->pResClasses[classIdx] = clazz;
130 }
131 INLINE void dvmDexSetResolvedMethod(DvmDex* pDvmDex, u4 methodIdx,
132     struct Method* method)
133 {
134     assert(methodIdx < pDvmDex->pHeader->methodIdsSize);
135     pDvmDex->pResMethods[methodIdx] = method;
136 }
137 INLINE void dvmDexSetResolvedField(DvmDex* pDvmDex, u4 fieldIdx,
138     struct Field* field)
139 {
140     assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize);
141     pDvmDex->pResFields[fieldIdx] = field;
142 }
143
144 #elif DVM_RESOLVER_CACHE == DVM_RC_REDUCING
145 /* reduce request to fit in a less-than-full-size cache table */
146
147 /*
148  * Return the requested item if it has been resolved, or NULL if it hasn't.
149  *
150  * If we have a mapping table defined for this category, but there's no
151  * entry for this index, we always return NULL.  Otherwise, we return the
152  * entry.  (To regain some performance we may want to assume that the
153  * table exists when compiled in this mode -- avoids a null check but
154  * prevents us from switching back and forth without rebuilding the VM.)
155  *
156  * We could save an integer compare here by ensuring that map[kNoIndexMapping]
157  * always evalutes to NULL (e.g. set kNoIndexMapping = 0).
158  */
159 INLINE struct StringObject* dvmDexGetResolvedString(const DvmDex* pDvmDex,
160     u4 stringIdx)
161 {
162     const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
163
164     assert(stringIdx < pDvmDex->pHeader->stringIdsSize);
165     if (pIndexMap->stringReducedCount > 0) {
166         stringIdx = pIndexMap->stringMap[stringIdx];
167         if (stringIdx == kNoIndexMapping)
168             return NULL;
169     }
170     return pDvmDex->pResStrings[stringIdx];
171 }
172 INLINE struct ClassObject* dvmDexGetResolvedClass(const DvmDex* pDvmDex,
173     u4 classIdx)
174 {
175     const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
176
177     assert(classIdx < pDvmDex->pHeader->typeIdsSize);
178     if (pIndexMap->classReducedCount > 0) {
179         classIdx = pIndexMap->classMap[classIdx];
180         if (classIdx == kNoIndexMapping)
181             return NULL;
182     }
183     return pDvmDex->pResClasses[classIdx];
184 }
185 INLINE struct Method* dvmDexGetResolvedMethod(const DvmDex* pDvmDex,
186     u4 methodIdx)
187 {
188     const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
189
190     assert(methodIdx < pDvmDex->pHeader->methodIdsSize);
191     if (pIndexMap->methodReducedCount > 0) {
192         methodIdx = pIndexMap->methodMap[methodIdx];
193         if (methodIdx == kNoIndexMapping)
194             return NULL;
195     }
196     return pDvmDex->pResMethods[methodIdx];
197 }
198 INLINE struct Field* dvmDexGetResolvedField(const DvmDex* pDvmDex,
199     u4 fieldIdx)
200 {
201     const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
202
203     assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize);
204     if (pIndexMap->fieldReducedCount > 0) {
205         fieldIdx = pIndexMap->fieldMap[fieldIdx];
206         if (fieldIdx == kNoIndexMapping)
207             return NULL;
208     }
209     return pDvmDex->pResFields[fieldIdx];
210 }
211
212 /*
213  * Update the resolved item table.  Resolution always produces the same
214  * result, so we're not worried about atomicity here.
215  */
216 INLINE void dvmDexSetResolvedString(DvmDex* pDvmDex, u4 stringIdx,
217     struct StringObject* str)
218 {
219     const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
220     u4 newIdx;
221
222     assert(stringIdx < pDvmDex->pHeader->stringIdsSize);
223     if (pIndexMap->stringReducedCount > 0) {
224         newIdx = pIndexMap->stringMap[stringIdx];
225         if (newIdx != kNoIndexMapping)
226             pDvmDex->pResStrings[newIdx] = str;
227     }
228 }
229 INLINE void dvmDexSetResolvedClass(DvmDex* pDvmDex, u4 classIdx,
230     struct ClassObject* clazz)
231 {
232     const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
233     u4 newIdx;
234
235     assert(classIdx < pDvmDex->pHeader->typeIdsSize);
236     if (pIndexMap->classReducedCount > 0) {
237         newIdx = pIndexMap->classMap[classIdx];
238         if (newIdx != kNoIndexMapping)
239             pDvmDex->pResClasses[newIdx] = clazz;
240     }
241 }
242 INLINE void dvmDexSetResolvedMethod(DvmDex* pDvmDex, u4 methodIdx,
243     struct Method* method)
244 {
245     const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
246     u4 newIdx;
247
248     assert(methodIdx < pDvmDex->pHeader->methodIdsSize);
249     if (pIndexMap->methodReducedCount > 0) {
250         newIdx = pIndexMap->methodMap[methodIdx];
251         if (newIdx != kNoIndexMapping)
252             pDvmDex->pResMethods[newIdx] = method;
253     }
254 }
255 INLINE void dvmDexSetResolvedField(DvmDex* pDvmDex, u4 fieldIdx,
256     struct Field* field)
257 {
258     const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
259     u4 newIdx;
260
261     assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize);
262     if (pIndexMap->fieldReducedCount > 0) {
263         newIdx = pIndexMap->fieldMap[fieldIdx];
264         if (newIdx != kNoIndexMapping)
265             pDvmDex->pResFields[newIdx] = field;
266     }
267 }
268
269 #elif DVM_RESOLVER_CACHE == DVM_RC_EXPANDING
270
271 #error "not implemented"    /* TODO */
272
273 #elif DVM_RESOLVER_CACHE == DVM_RC_NO_CACHE
274
275 /*
276  * There's no cache, so we always return NULL.
277  */
278 INLINE struct StringObject* dvmDexGetResolvedString(const DvmDex* pDvmDex,
279     u4 stringIdx)
280 {
281     return NULL;
282 }
283 INLINE struct ClassObject* dvmDexGetResolvedClass(const DvmDex* pDvmDex,
284     u4 classIdx)
285 {
286     return NULL;
287 }
288 INLINE struct Method* dvmDexGetResolvedMethod(const DvmDex* pDvmDex,
289     u4 methodIdx)
290 {
291     return NULL;
292 }
293 INLINE struct Field* dvmDexGetResolvedField(const DvmDex* pDvmDex,
294     u4 fieldIdx)
295 {
296     return NULL;
297 }
298
299 /*
300  * Update the resolved item table.  There is no table, so do nothing.
301  */
302 INLINE void dvmDexSetResolvedString(DvmDex* pDvmDex, u4 stringIdx,
303     struct StringObject* str)
304 {}
305 INLINE void dvmDexSetResolvedClass(DvmDex* pDvmDex, u4 classIdx,
306     struct ClassObject* clazz)
307 {}
308 INLINE void dvmDexSetResolvedMethod(DvmDex* pDvmDex, u4 methodIdx,
309     struct Method* method)
310 {}
311 INLINE void dvmDexSetResolvedField(DvmDex* pDvmDex, u4 fieldIdx,
312     struct Field* field)
313 {}
314
315 #else
316 #error "huh?"
317 #endif /*DVM_RESOLVER_CACHE==N*/
318
319 #endif /*_DALVIK_DVMDEX*/