OSDN Git Service

Merge change 9384
[android-x86/dalvik.git] / vm / DvmDex.c
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  * VM-specific state associated with a DEX file.
18  */
19 #include "Dalvik.h"
20
21 /*
22  * Create auxillary data structures.
23  *
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
27  * of native memory.
28  *
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.
32  *
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
36  * at dexopt time.
37  */
38 static DvmDex* allocateAuxStructures(DexFile* pDexFile)
39 {
40     DvmDex* pDvmDex;
41     const DexHeader* pHeader;
42     u4 stringCount, classCount, methodCount, fieldCount;
43
44     pDvmDex = (DvmDex*) calloc(1, sizeof(DvmDex));
45     if (pDvmDex == NULL)
46         return NULL;
47
48     pDvmDex->pDexFile = pDexFile;
49     pDvmDex->pHeader = pDexFile->pHeader;
50
51     pHeader = pDvmDex->pHeader;
52
53     stringCount = pHeader->stringIdsSize;
54     classCount = pHeader->typeIdsSize;
55     methodCount = pHeader->methodIdsSize;
56     fieldCount = pHeader->fieldIdsSize;
57
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;
70 #endif
71
72     pDvmDex->pResStrings = (struct StringObject**)
73         calloc(stringCount, sizeof(struct StringObject*));
74
75     pDvmDex->pResClasses = (struct ClassObject**)
76         calloc(classCount, sizeof(struct ClassObject*));
77
78     pDvmDex->pResMethods = (struct Method**)
79         calloc(methodCount, sizeof(struct Method*));
80
81     pDvmDex->pResFields = (struct Field**)
82         calloc(fieldCount, sizeof(struct Field*));
83
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);
87
88     pDvmDex->pInterfaceCache = dvmAllocAtomicCache(DEX_INTERFACE_CACHE_SIZE);
89
90     if (pDvmDex->pResStrings == NULL ||
91         pDvmDex->pResClasses == NULL ||
92         pDvmDex->pResMethods == NULL ||
93         pDvmDex->pResFields == NULL ||
94         pDvmDex->pInterfaceCache == NULL)
95     {
96         LOGE("Alloc failure in allocateAuxStructures\n");
97         free(pDvmDex->pResStrings);
98         free(pDvmDex->pResClasses);
99         free(pDvmDex->pResMethods);
100         free(pDvmDex->pResFields);
101         free(pDvmDex);
102         return NULL;
103     }
104
105     return pDvmDex;
106
107 }
108
109 /*
110  * Given an open optimized DEX file, map it into read-only shared memory and
111  * parse the contents.
112  *
113  * Returns nonzero on error.
114  */
115 int dvmDexFileOpenFromFd(int fd, DvmDex** ppDvmDex)
116 {
117     DvmDex* pDvmDex;
118     DexFile* pDexFile;
119     MemMapping memMap;
120     int parseFlags = kDexParseDefault;
121     int result = -1;
122
123     if (gDvm.verifyDexChecksum)
124         parseFlags |= kDexParseVerifyChecksum;
125
126     if (lseek(fd, 0, SEEK_SET) < 0) {
127         LOGE("lseek rewind failed\n");
128         goto bail;
129     }
130
131     if (sysMapFileInShmem(fd, &memMap) != 0) {
132         LOGE("Unable to map file\n");
133         goto bail;
134     }
135
136     pDexFile = dexFileParse(memMap.addr, memMap.length, parseFlags);
137     if (pDexFile == NULL) {
138         LOGE("DEX parse failed\n");
139         sysReleaseShmem(&memMap);
140         goto bail;
141     }
142
143     pDvmDex = allocateAuxStructures(pDexFile);
144     if (pDvmDex == NULL) {
145         dexFileFree(pDexFile);
146         sysReleaseShmem(&memMap);
147         goto bail;
148     }
149
150     /* tuck this into the DexFile so it gets released later */
151     sysCopyMap(&pDvmDex->memMap, &memMap);
152     *ppDvmDex = pDvmDex;
153     result = 0;
154
155 bail:
156     return result;
157 }
158
159 /*
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.
164  *
165  * Returns nonzero on error.
166  */
167 int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex)
168 {
169     DvmDex* pDvmDex;
170     DexFile* pDexFile;
171     int parseFlags = kDexParseDefault;
172     int result = -1;
173
174     /* -- file is incomplete, new checksum has not yet been calculated
175     if (gDvm.verifyDexChecksum)
176         parseFlags |= kDexParseVerifyChecksum;
177     */
178
179     pDexFile = dexFileParse(addr, len, parseFlags);
180     if (pDexFile == NULL) {
181         LOGE("DEX parse failed\n");
182         goto bail;
183     }
184     pDvmDex = allocateAuxStructures(pDexFile);
185     if (pDvmDex == NULL) {
186         dexFileFree(pDexFile);
187         goto bail;
188     }
189
190     *ppDvmDex = pDvmDex;
191     result = 0;
192
193 bail:
194     return result;
195 }
196
197 /*
198  * Free up the DexFile and any associated data structures.
199  *
200  * Note we may be called with a partially-initialized DvmDex.
201  */
202 void dvmDexFileFree(DvmDex* pDvmDex)
203 {
204     if (pDvmDex == NULL)
205         return;
206
207     dexFileFree(pDvmDex->pDexFile);
208
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);
215
216     sysReleaseShmem(&pDvmDex->memMap);
217     free(pDvmDex);
218 }
219