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.
17 * VM-specific state associated with a DEX file.
22 * Create auxillary data structures.
24 * We need a 4-byte pointer for every reference to a class, method, field,
25 * or string constant. Summed up over all loaded DEX files (including the
26 * whoppers in the boostrap class path), this adds up to be quite a bit
29 * For more traditional VMs these values could be stuffed into the loaded
30 * class file constant pool area, but we don't have that luxury since our
31 * classes are memory-mapped read-only.
33 * The DEX optimizer will remove the need for some of these (e.g. we won't
34 * use the entry for virtual methods that are only called through
35 * invoke-virtual-quick), creating the possibility of some space reduction
38 static DvmDex* allocateAuxStructures(DexFile* pDexFile)
41 const DexHeader* pHeader;
42 u4 stringCount, classCount, methodCount, fieldCount;
44 pDvmDex = (DvmDex*) calloc(1, sizeof(DvmDex));
48 pDvmDex->pDexFile = pDexFile;
49 pDvmDex->pHeader = pDexFile->pHeader;
51 pHeader = pDvmDex->pHeader;
53 stringCount = pHeader->stringIdsSize;
54 classCount = pHeader->typeIdsSize;
55 methodCount = pHeader->methodIdsSize;
56 fieldCount = pHeader->fieldIdsSize;
58 #if (DVM_RESOLVER_CACHE == DVM_RC_REDUCING) || \
59 (DVM_RESOLVER_CACHE == DVM_RC_EXPANDING)
60 if (pDexFile->indexMap.stringReducedCount > 0)
61 stringCount = pDexFile->indexMap.stringReducedCount;
62 if (pDexFile->indexMap.classReducedCount > 0)
63 classCount = pDexFile->indexMap.classReducedCount;
64 if (pDexFile->indexMap.methodReducedCount > 0)
65 methodCount = pDexFile->indexMap.methodReducedCount;
66 if (pDexFile->indexMap.fieldReducedCount > 0)
67 fieldCount = pDexFile->indexMap.fieldReducedCount;
68 #elif (DVM_RESOLVER_CACHE == DVM_RC_NO_CACHE)
69 stringCount = classCount = methodCount = fieldCount = 0;
72 pDvmDex->pResStrings = (struct StringObject**)
73 calloc(stringCount, sizeof(struct StringObject*));
75 pDvmDex->pResClasses = (struct ClassObject**)
76 calloc(classCount, sizeof(struct ClassObject*));
78 pDvmDex->pResMethods = (struct Method**)
79 calloc(methodCount, sizeof(struct Method*));
81 pDvmDex->pResFields = (struct Field**)
82 calloc(fieldCount, sizeof(struct Field*));
84 LOGV("+++ DEX %p: allocateAux %d+%d+%d+%d * 4 = %d bytes\n",
85 pDvmDex, stringCount, classCount, methodCount, fieldCount,
86 (stringCount + classCount + methodCount + fieldCount) * 4);
88 pDvmDex->pInterfaceCache = dvmAllocAtomicCache(DEX_INTERFACE_CACHE_SIZE);
90 if (pDvmDex->pResStrings == NULL ||
91 pDvmDex->pResClasses == NULL ||
92 pDvmDex->pResMethods == NULL ||
93 pDvmDex->pResFields == NULL ||
94 pDvmDex->pInterfaceCache == NULL)
96 LOGE("Alloc failure in allocateAuxStructures\n");
97 free(pDvmDex->pResStrings);
98 free(pDvmDex->pResClasses);
99 free(pDvmDex->pResMethods);
100 free(pDvmDex->pResFields);
110 * Given an open optimized DEX file, map it into read-only shared memory and
111 * parse the contents.
113 * Returns nonzero on error.
115 int dvmDexFileOpenFromFd(int fd, DvmDex** ppDvmDex)
120 int parseFlags = kDexParseDefault;
123 if (gDvm.verifyDexChecksum)
124 parseFlags |= kDexParseVerifyChecksum;
126 if (lseek(fd, 0, SEEK_SET) < 0) {
127 LOGE("lseek rewind failed\n");
131 if (sysMapFileInShmem(fd, &memMap) != 0) {
132 LOGE("Unable to map file\n");
136 pDexFile = dexFileParse(memMap.addr, memMap.length, parseFlags);
137 if (pDexFile == NULL) {
138 LOGE("DEX parse failed\n");
139 sysReleaseShmem(&memMap);
143 pDvmDex = allocateAuxStructures(pDexFile);
144 if (pDvmDex == NULL) {
145 dexFileFree(pDexFile);
146 sysReleaseShmem(&memMap);
150 /* tuck this into the DexFile so it gets released later */
151 sysCopyMap(&pDvmDex->memMap, &memMap);
160 * Create a DexFile structure for a "partial" DEX. This is one that is in
161 * the process of being optimized. The optimization header isn't finished
162 * and we won't have any of the auxillary data tables, so we have to do
163 * the initialization slightly differently.
165 * Returns nonzero on error.
167 int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex)
171 int parseFlags = kDexParseDefault;
174 /* -- file is incomplete, new checksum has not yet been calculated
175 if (gDvm.verifyDexChecksum)
176 parseFlags |= kDexParseVerifyChecksum;
179 pDexFile = dexFileParse(addr, len, parseFlags);
180 if (pDexFile == NULL) {
181 LOGE("DEX parse failed\n");
184 pDvmDex = allocateAuxStructures(pDexFile);
185 if (pDvmDex == NULL) {
186 dexFileFree(pDexFile);
198 * Free up the DexFile and any associated data structures.
200 * Note we may be called with a partially-initialized DvmDex.
202 void dvmDexFileFree(DvmDex* pDvmDex)
207 dexFileFree(pDvmDex->pDexFile);
209 LOGV("+++ DEX %p: freeing aux structs\n", pDvmDex);
210 free(pDvmDex->pResStrings);
211 free(pDvmDex->pResClasses);
212 free(pDvmDex->pResMethods);
213 free(pDvmDex->pResFields);
214 dvmFreeAtomicCache(pDvmDex->pInterfaceCache);
216 sysReleaseShmem(&pDvmDex->memMap);