2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * The VM wraps some additional data structures around the DexFile. These
21 #ifndef _DALVIK_DVMDEX
22 #define _DALVIK_DVMDEX
24 #include "libdex/DexFile.h"
35 * Some additional VM data structures that are associated with the DEX file.
37 typedef struct DvmDex {
38 /* pointer to the DexFile we're associated with */
41 /* clone of pDexFile->pHeader (it's used frequently enough) */
42 const DexHeader* pHeader;
44 /* interned strings; parallel to "stringIds" */
45 struct StringObject** pResStrings;
47 /* resolved classes; parallel to "typeIds" */
48 struct ClassObject** pResClasses;
50 /* resolved methods; parallel to "methodIds" */
51 struct Method** pResMethods;
53 /* resolved instance fields; parallel to "fieldIds" */
54 /* (this holds both InstField and StaticField) */
55 struct Field** pResFields;
57 /* interface method lookup cache */
58 struct AtomicCache* pInterfaceCache;
60 /* shared memory region with file contents */
63 /* lock ensuring mutual exclusion during updates */
64 pthread_mutex_t modLock;
69 * Given a file descriptor for an open "optimized" DEX file, map it into
70 * memory and parse the contents.
72 * On success, returns 0 and sets "*ppDvmDex" to a newly-allocated DvmDex.
73 * On failure, returns a meaningful error code [currently just -1].
75 int dvmDexFileOpenFromFd(int fd, DvmDex** ppDvmDex);
78 * Open a partial DEX file. Only useful as part of the optimization process.
80 int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex);
83 * Free a DvmDex structure, along with any associated structures.
85 void dvmDexFileFree(DvmDex* pDvmDex);
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.
92 * This does not make any synchronization guarantees. The caller must
93 * ensure exclusivity vs. other callers.
95 * For the 2-byte call, the pointer should have 16-bit alignment.
97 * Returns "true" on success.
99 bool dvmDexChangeDex1(DvmDex* pDvmDex, u1* addr, u1 newVal);
100 bool dvmDexChangeDex2(DvmDex* pDvmDex, u2* addr, u2 newVal);
103 #if DVM_RESOLVER_CACHE == DVM_RC_DISABLED
107 * Return the requested item if it has been resolved, or NULL if it hasn't.
109 INLINE struct StringObject* dvmDexGetResolvedString(const DvmDex* pDvmDex,
112 assert(stringIdx < pDvmDex->pHeader->stringIdsSize);
113 return pDvmDex->pResStrings[stringIdx];
115 INLINE struct ClassObject* dvmDexGetResolvedClass(const DvmDex* pDvmDex,
118 assert(classIdx < pDvmDex->pHeader->typeIdsSize);
119 return pDvmDex->pResClasses[classIdx];
121 INLINE struct Method* dvmDexGetResolvedMethod(const DvmDex* pDvmDex,
124 assert(methodIdx < pDvmDex->pHeader->methodIdsSize);
125 return pDvmDex->pResMethods[methodIdx];
127 INLINE struct Field* dvmDexGetResolvedField(const DvmDex* pDvmDex,
130 assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize);
131 return pDvmDex->pResFields[fieldIdx];
135 * Update the resolved item table. Resolution always produces the same
136 * result, so we're not worried about atomicity here.
138 INLINE void dvmDexSetResolvedString(DvmDex* pDvmDex, u4 stringIdx,
139 struct StringObject* str)
141 assert(stringIdx < pDvmDex->pHeader->stringIdsSize);
142 pDvmDex->pResStrings[stringIdx] = str;
144 INLINE void dvmDexSetResolvedClass(DvmDex* pDvmDex, u4 classIdx,
145 struct ClassObject* clazz)
147 assert(classIdx < pDvmDex->pHeader->typeIdsSize);
148 pDvmDex->pResClasses[classIdx] = clazz;
150 INLINE void dvmDexSetResolvedMethod(DvmDex* pDvmDex, u4 methodIdx,
151 struct Method* method)
153 assert(methodIdx < pDvmDex->pHeader->methodIdsSize);
154 pDvmDex->pResMethods[methodIdx] = method;
156 INLINE void dvmDexSetResolvedField(DvmDex* pDvmDex, u4 fieldIdx,
159 assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize);
160 pDvmDex->pResFields[fieldIdx] = field;
163 #elif DVM_RESOLVER_CACHE == DVM_RC_REDUCING
164 /* reduce request to fit in a less-than-full-size cache table */
167 * Return the requested item if it has been resolved, or NULL if it hasn't.
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.)
175 * We could save an integer compare here by ensuring that map[kNoIndexMapping]
176 * always evalutes to NULL (e.g. set kNoIndexMapping = 0).
178 INLINE struct StringObject* dvmDexGetResolvedString(const DvmDex* pDvmDex,
181 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
183 assert(stringIdx < pDvmDex->pHeader->stringIdsSize);
184 if (pIndexMap->stringReducedCount > 0) {
185 stringIdx = pIndexMap->stringMap[stringIdx];
186 if (stringIdx == kNoIndexMapping)
189 return pDvmDex->pResStrings[stringIdx];
191 INLINE struct ClassObject* dvmDexGetResolvedClass(const DvmDex* pDvmDex,
194 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
196 assert(classIdx < pDvmDex->pHeader->typeIdsSize);
197 if (pIndexMap->classReducedCount > 0) {
198 classIdx = pIndexMap->classMap[classIdx];
199 if (classIdx == kNoIndexMapping)
202 return pDvmDex->pResClasses[classIdx];
204 INLINE struct Method* dvmDexGetResolvedMethod(const DvmDex* pDvmDex,
207 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
209 assert(methodIdx < pDvmDex->pHeader->methodIdsSize);
210 if (pIndexMap->methodReducedCount > 0) {
211 methodIdx = pIndexMap->methodMap[methodIdx];
212 if (methodIdx == kNoIndexMapping)
215 return pDvmDex->pResMethods[methodIdx];
217 INLINE struct Field* dvmDexGetResolvedField(const DvmDex* pDvmDex,
220 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
222 assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize);
223 if (pIndexMap->fieldReducedCount > 0) {
224 fieldIdx = pIndexMap->fieldMap[fieldIdx];
225 if (fieldIdx == kNoIndexMapping)
228 return pDvmDex->pResFields[fieldIdx];
232 * Update the resolved item table. Resolution always produces the same
233 * result, so we're not worried about atomicity here.
235 INLINE void dvmDexSetResolvedString(DvmDex* pDvmDex, u4 stringIdx,
236 struct StringObject* str)
238 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
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;
248 INLINE void dvmDexSetResolvedClass(DvmDex* pDvmDex, u4 classIdx,
249 struct ClassObject* clazz)
251 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
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;
261 INLINE void dvmDexSetResolvedMethod(DvmDex* pDvmDex, u4 methodIdx,
262 struct Method* method)
264 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
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;
274 INLINE void dvmDexSetResolvedField(DvmDex* pDvmDex, u4 fieldIdx,
277 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
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;
288 #elif DVM_RESOLVER_CACHE == DVM_RC_EXPANDING
290 #error "not implemented" /* TODO */
292 #elif DVM_RESOLVER_CACHE == DVM_RC_NO_CACHE
295 * There's no cache, so we always return NULL.
297 INLINE struct StringObject* dvmDexGetResolvedString(const DvmDex* pDvmDex,
302 INLINE struct ClassObject* dvmDexGetResolvedClass(const DvmDex* pDvmDex,
307 INLINE struct Method* dvmDexGetResolvedMethod(const DvmDex* pDvmDex,
312 INLINE struct Field* dvmDexGetResolvedField(const DvmDex* pDvmDex,
319 * Update the resolved item table. There is no table, so do nothing.
321 INLINE void dvmDexSetResolvedString(DvmDex* pDvmDex, u4 stringIdx,
322 struct StringObject* str)
324 INLINE void dvmDexSetResolvedClass(DvmDex* pDvmDex, u4 classIdx,
325 struct ClassObject* clazz)
327 INLINE void dvmDexSetResolvedMethod(DvmDex* pDvmDex, u4 methodIdx,
328 struct Method* method)
330 INLINE void dvmDexSetResolvedField(DvmDex* pDvmDex, u4 fieldIdx,
336 #endif /*DVM_RESOLVER_CACHE==N*/
338 #endif /*_DALVIK_DVMDEX*/