OSDN Git Service

am cf4e8b02: Merge "This is a contribution of x86-atom targeted assembly for the...
[android-x86/dalvik.git] / vm / analysis / DexOptimize.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 /*
18  * Convert the output from "dx" into a locally-optimized DEX file.
19  *
20  * TODO: the format of the optimized header is currently "whatever we
21  * happen to write", since the VM that writes it is by definition the same
22  * as the VM that reads it.  Still, it should be better documented and
23  * more rigorously structured.
24  */
25 #include "Dalvik.h"
26 #include "libdex/InstrUtils.h"
27 #include "libdex/OptInvocation.h"
28 #include "analysis/RegisterMap.h"
29
30 #include <zlib.h>
31
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <sys/mman.h>
35 #include <sys/stat.h>
36 #include <sys/file.h>
37 #include <sys/wait.h>
38 #include <fcntl.h>
39 #include <errno.h>
40
41 /*
42  * Virtual/direct calls to "method" are replaced with an execute-inline
43  * instruction with index "idx".
44  */
45 typedef struct InlineSub {
46     Method* method;
47     int     inlineIdx;
48 } InlineSub;
49
50
51 /* fwd */
52 static int writeDependencies(int fd, u4 modWhen, u4 crc);
53 static bool writeAuxData(int fd, const DexClassLookup* pClassLookup,\
54     const IndexMapSet* pIndexMapSet, const RegisterMapBuilder* pRegMapBuilder);
55 static void logFailedWrite(size_t expected, ssize_t actual, const char* msg,
56     int err);
57 static bool computeFileChecksum(int fd, off_t start, size_t length, u4* pSum);
58
59 static bool rewriteDex(u1* addr, int len, bool doVerify, bool doOpt,\
60     u4* pHeaderFlags, DexClassLookup** ppClassLookup);
61 static void updateChecksum(u1* addr, int len, DexHeader* pHeader);
62 static bool loadAllClasses(DvmDex* pDvmDex);
63 static void optimizeLoadedClasses(DexFile* pDexFile);
64 static void optimizeClass(ClassObject* clazz, const InlineSub* inlineSubs);
65 static bool optimizeMethod(Method* method, const InlineSub* inlineSubs);
66 static void rewriteInstField(Method* method, u2* insns, OpCode newOpc);
67 static bool rewriteVirtualInvoke(Method* method, u2* insns, OpCode newOpc);
68 static bool rewriteEmptyDirectInvoke(Method* method, u2* insns);
69 static bool rewriteExecuteInline(Method* method, u2* insns,
70     MethodType methodType, const InlineSub* inlineSubs);
71 static bool rewriteExecuteInlineRange(Method* method, u2* insns,
72     MethodType methodType, const InlineSub* inlineSubs);
73
74
75 /*
76  * Return the fd of an open file in the DEX file cache area.  If the cache
77  * file doesn't exist or is out of date, this will remove the old entry,
78  * create a new one (writing only the file header), and return with the
79  * "new file" flag set.
80  *
81  * It's possible to execute from an unoptimized DEX file directly,
82  * assuming the byte ordering and structure alignment is correct, but
83  * disadvantageous because some significant optimizations are not possible.
84  * It's not generally possible to do the same from an uncompressed Jar
85  * file entry, because we have to guarantee 32-bit alignment in the
86  * memory-mapped file.
87  *
88  * For a Jar/APK file (a zip archive with "classes.dex" inside), "modWhen"
89  * and "crc32" come from the Zip directory entry.  For a stand-alone DEX
90  * file, it's the modification date of the file and the Adler32 from the
91  * DEX header (which immediately follows the magic).  If these don't
92  * match what's stored in the opt header, we reject the file immediately.
93  *
94  * On success, the file descriptor will be positioned just past the "opt"
95  * file header, and will be locked with flock.  "*pCachedName" will point
96  * to newly-allocated storage.
97  */
98 int dvmOpenCachedDexFile(const char* fileName, const char* cacheFileName,
99     u4 modWhen, u4 crc, bool isBootstrap, bool* pNewFile, bool createIfMissing)
100 {
101     int fd, cc;
102     struct stat fdStat, fileStat;
103     bool readOnly = false;
104
105     *pNewFile = false;
106
107 retry:
108     /*
109      * Try to open the cache file.  If we've been asked to,
110      * create it if it doesn't exist.
111      */
112     fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
113     if (fd < 0) {
114         fd = open(cacheFileName, O_RDONLY, 0);
115         if (fd < 0) {
116             if (createIfMissing) {
117                 LOGE("Can't open dex cache '%s': %s\n",
118                     cacheFileName, strerror(errno));
119             }
120             return fd;
121         }
122         readOnly = true;
123     }
124
125     /*
126      * Grab an exclusive lock on the cache file.  If somebody else is
127      * working on it, we'll block here until they complete.  Because
128      * we're waiting on an external resource, we go into VMWAIT mode.
129      */
130     int oldStatus;
131     LOGV("DexOpt: locking cache file %s (fd=%d, boot=%d)\n",
132         cacheFileName, fd, isBootstrap);
133     oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT);
134     cc = flock(fd, LOCK_EX | LOCK_NB);
135     if (cc != 0) {
136         LOGD("DexOpt: sleeping on flock(%s)\n", cacheFileName);
137         cc = flock(fd, LOCK_EX);
138     }
139     dvmChangeStatus(NULL, oldStatus);
140     if (cc != 0) {
141         LOGE("Can't lock dex cache '%s': %d\n", cacheFileName, cc);
142         close(fd);
143         return -1;
144     }
145     LOGV("DexOpt:  locked cache file\n");
146
147     /*
148      * Check to see if the fd we opened and locked matches the file in
149      * the filesystem.  If they don't, then somebody else unlinked ours
150      * and created a new file, and we need to use that one instead.  (If
151      * we caught them between the unlink and the create, we'll get an
152      * ENOENT from the file stat.)
153      */
154     cc = fstat(fd, &fdStat);
155     if (cc != 0) {
156         LOGE("Can't stat open file '%s'\n", cacheFileName);
157         LOGVV("DexOpt: unlocking cache file %s\n", cacheFileName);
158         goto close_fail;
159     }
160     cc = stat(cacheFileName, &fileStat);
161     if (cc != 0 ||
162         fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino)
163     {
164         LOGD("DexOpt: our open cache file is stale; sleeping and retrying\n");
165         LOGVV("DexOpt: unlocking cache file %s\n", cacheFileName);
166         flock(fd, LOCK_UN);
167         close(fd);
168         usleep(250 * 1000);     /* if something is hosed, don't peg machine */
169         goto retry;
170     }
171
172     /*
173      * We have the correct file open and locked.  If the file size is zero,
174      * then it was just created by us, and we want to fill in some fields
175      * in the "opt" header and set "*pNewFile".  Otherwise, we want to
176      * verify that the fields in the header match our expectations, and
177      * reset the file if they don't.
178      */
179     if (fdStat.st_size == 0) {
180         if (readOnly) {
181             LOGW("DexOpt: file has zero length and isn't writable\n");
182             goto close_fail;
183         }
184         cc = dexOptCreateEmptyHeader(fd);
185         if (cc != 0)
186             goto close_fail;
187         *pNewFile = true;
188         LOGV("DexOpt: successfully initialized new cache file\n");
189     } else {
190         bool expectVerify, expectOpt;
191
192         if (gDvm.classVerifyMode == VERIFY_MODE_NONE)
193             expectVerify = false;
194         else if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE)
195             expectVerify = !isBootstrap;
196         else /*if (gDvm.classVerifyMode == VERIFY_MODE_ALL)*/
197             expectVerify = true;
198
199         if (gDvm.dexOptMode == OPTIMIZE_MODE_NONE)
200             expectOpt = false;
201         else if (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED)
202             expectOpt = expectVerify;
203         else /*if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)*/
204             expectOpt = true;
205
206         LOGV("checking deps, expecting vfy=%d opt=%d\n",
207             expectVerify, expectOpt);
208
209         if (!dvmCheckOptHeaderAndDependencies(fd, true, modWhen, crc,
210                 expectVerify, expectOpt))
211         {
212             if (readOnly) {
213                 /*
214                  * We could unlink and rewrite the file if we own it or
215                  * the "sticky" bit isn't set on the directory.  However,
216                  * we're not able to truncate it, which spoils things.  So,
217                  * give up now.
218                  */
219                 if (createIfMissing) {
220                     LOGW("Cached DEX '%s' (%s) is stale and not writable\n",
221                         fileName, cacheFileName);
222                 }
223                 goto close_fail;
224             }
225
226             /*
227              * If we truncate the existing file before unlinking it, any
228              * process that has it mapped will fail when it tries to touch
229              * the pages.
230              *
231              * This is very important.  The zygote process will have the
232              * boot DEX files (core, framework, etc.) mapped early.  If
233              * (say) core.dex gets updated, and somebody launches an app
234              * that uses App.dex, then App.dex gets reoptimized because it's
235              * dependent upon the boot classes.  However, dexopt will be
236              * using the *new* core.dex to do the optimizations, while the
237              * app will actually be running against the *old* core.dex
238              * because it starts from zygote.
239              *
240              * Even without zygote, it's still possible for a class loader
241              * to pull in an APK that was optimized against an older set
242              * of DEX files.  We must ensure that everything fails when a
243              * boot DEX gets updated, and for general "why aren't my
244              * changes doing anything" purposes its best if we just make
245              * everything crash when a DEX they're using gets updated.
246              */
247             LOGD("Stale deps in cache file; removing and retrying\n");
248             if (ftruncate(fd, 0) != 0) {
249                 LOGW("Warning: unable to truncate cache file '%s': %s\n",
250                     cacheFileName, strerror(errno));
251                 /* keep going */
252             }
253             if (unlink(cacheFileName) != 0) {
254                 LOGW("Warning: unable to remove cache file '%s': %d %s\n",
255                     cacheFileName, errno, strerror(errno));
256                 /* keep going; permission failure should probably be fatal */
257             }
258             LOGVV("DexOpt: unlocking cache file %s\n", cacheFileName);
259             flock(fd, LOCK_UN);
260             close(fd);
261             goto retry;
262         } else {
263             LOGV("DexOpt: good deps in cache file\n");
264         }
265     }
266
267     assert(fd >= 0);
268     return fd;
269
270 close_fail:
271     flock(fd, LOCK_UN);
272     close(fd);
273     return -1;
274 }
275
276 /*
277  * Unlock the file descriptor.
278  *
279  * Returns "true" on success.
280  */
281 bool dvmUnlockCachedDexFile(int fd)
282 {
283     LOGVV("DexOpt: unlocking cache file fd=%d\n", fd);
284     return (flock(fd, LOCK_UN) == 0);
285 }
286
287
288 /*
289  * Given a descriptor for a file with DEX data in it, produce an
290  * optimized version.
291  *
292  * The file pointed to by "fd" is expected to be a locked shared resource
293  * (or private); we make no efforts to enforce multi-process correctness
294  * here.
295  *
296  * "fileName" is only used for debug output.  "modWhen" and "crc" are stored
297  * in the dependency set.
298  *
299  * The "isBootstrap" flag determines how the optimizer and verifier handle
300  * package-scope access checks.  When optimizing, we only load the bootstrap
301  * class DEX files and the target DEX, so the flag determines whether the
302  * target DEX classes are given a (synthetic) non-NULL classLoader pointer.
303  * This only really matters if the target DEX contains classes that claim to
304  * be in the same package as bootstrap classes.
305  *
306  * The optimizer will need to load every class in the target DEX file.
307  * This is generally undesirable, so we start a subprocess to do the
308  * work and wait for it to complete.
309  *
310  * Returns "true" on success.  All data will have been written to "fd".
311  */
312 bool dvmOptimizeDexFile(int fd, off_t dexOffset, long dexLength,
313     const char* fileName, u4 modWhen, u4 crc, bool isBootstrap)
314 {
315     const char* lastPart = strrchr(fileName, '/');
316     if (lastPart != NULL)
317         lastPart++;
318     else
319         lastPart = fileName;
320
321     /*
322      * For basic optimizations (byte-swapping and structure aligning) we
323      * don't need to fork().  It looks like fork+exec is causing problems
324      * with gdb on our bewildered Linux distro, so in some situations we
325      * want to avoid this.
326      *
327      * For optimization and/or verification, we need to load all the classes.
328      *
329      * We don't check gDvm.generateRegisterMaps, since that is dependent
330      * upon the verifier state.
331      */
332     if (gDvm.classVerifyMode == VERIFY_MODE_NONE &&
333         (gDvm.dexOptMode == OPTIMIZE_MODE_NONE ||
334          gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED))
335     {
336         LOGD("DexOpt: --- BEGIN (quick) '%s' ---\n", lastPart);
337         return dvmContinueOptimization(fd, dexOffset, dexLength,
338                 fileName, modWhen, crc, isBootstrap);
339     }
340
341
342     LOGD("DexOpt: --- BEGIN '%s' (bootstrap=%d) ---\n", lastPart, isBootstrap);
343
344     pid_t pid;
345
346     /*
347      * This could happen if something in our bootclasspath, which we thought
348      * was all optimized, got rejected.
349      */
350     if (gDvm.optimizing) {
351         LOGW("Rejecting recursive optimization attempt on '%s'\n", fileName);
352         return false;
353     }
354
355     pid = fork();
356     if (pid == 0) {
357         static const int kUseValgrind = 0;
358         static const char* kDexOptBin = "/bin/dexopt";
359         static const char* kValgrinder = "/usr/bin/valgrind";
360         static const int kFixedArgCount = 10;
361         static const int kValgrindArgCount = 5;
362         static const int kMaxIntLen = 12;   // '-'+10dig+'\0' -OR- 0x+8dig
363         int bcpSize = dvmGetBootPathSize();
364         int argc = kFixedArgCount + bcpSize
365             + (kValgrindArgCount * kUseValgrind);
366         char* argv[argc+1];             // last entry is NULL
367         char values[argc][kMaxIntLen];
368         char* execFile;
369         char* androidRoot;
370         int flags;
371
372         /* change process groups, so we don't clash with ProcessManager */
373         setpgid(0, 0);
374
375         /* full path to optimizer */
376         androidRoot = getenv("ANDROID_ROOT");
377         if (androidRoot == NULL) {
378             LOGW("ANDROID_ROOT not set, defaulting to /system\n");
379             androidRoot = "/system";
380         }
381         execFile = malloc(strlen(androidRoot) + strlen(kDexOptBin) + 1);
382         strcpy(execFile, androidRoot);
383         strcat(execFile, kDexOptBin);
384
385         /*
386          * Create arg vector.
387          */
388         int curArg = 0;
389
390         if (kUseValgrind) {
391             /* probably shouldn't ship the hard-coded path */
392             argv[curArg++] = (char*)kValgrinder;
393             argv[curArg++] = "--tool=memcheck";
394             argv[curArg++] = "--leak-check=yes";        // check for leaks too
395             argv[curArg++] = "--leak-resolution=med";   // increase from 2 to 4
396             argv[curArg++] = "--num-callers=16";        // default is 12
397             assert(curArg == kValgrindArgCount);
398         }
399         argv[curArg++] = execFile;
400
401         argv[curArg++] = "--dex";
402
403         sprintf(values[2], "%d", DALVIK_VM_BUILD);
404         argv[curArg++] = values[2];
405
406         sprintf(values[3], "%d", fd);
407         argv[curArg++] = values[3];
408
409         sprintf(values[4], "%d", (int) dexOffset);
410         argv[curArg++] = values[4];
411
412         sprintf(values[5], "%d", (int) dexLength);
413         argv[curArg++] = values[5];
414
415         argv[curArg++] = (char*)fileName;
416
417         sprintf(values[7], "%d", (int) modWhen);
418         argv[curArg++] = values[7];
419
420         sprintf(values[8], "%d", (int) crc);
421         argv[curArg++] = values[8];
422
423         flags = 0;
424         if (gDvm.dexOptMode != OPTIMIZE_MODE_NONE) {
425             flags |= DEXOPT_OPT_ENABLED;
426             if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)
427                 flags |= DEXOPT_OPT_ALL;
428         }
429         if (gDvm.classVerifyMode != VERIFY_MODE_NONE) {
430             flags |= DEXOPT_VERIFY_ENABLED;
431             if (gDvm.classVerifyMode == VERIFY_MODE_ALL)
432                 flags |= DEXOPT_VERIFY_ALL;
433         }
434         if (isBootstrap)
435             flags |= DEXOPT_IS_BOOTSTRAP;
436         if (gDvm.generateRegisterMaps)
437             flags |= DEXOPT_GEN_REGISTER_MAP;
438         sprintf(values[9], "%d", flags);
439         argv[curArg++] = values[9];
440
441         assert(((!kUseValgrind && curArg == kFixedArgCount) ||
442                ((kUseValgrind && curArg == kFixedArgCount+kValgrindArgCount))));
443
444         ClassPathEntry* cpe;
445         for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) {
446             argv[curArg++] = cpe->fileName;
447         }
448         assert(curArg == argc);
449
450         argv[curArg] = NULL;
451
452         if (kUseValgrind)
453             execv(kValgrinder, argv);
454         else
455             execv(execFile, argv);
456
457         LOGE("execv '%s'%s failed: %s\n", execFile,
458             kUseValgrind ? " [valgrind]" : "", strerror(errno));
459         exit(1);
460     } else {
461         LOGV("DexOpt: waiting for verify+opt, pid=%d\n", (int) pid);
462         int status;
463         pid_t gotPid;
464         int oldStatus;
465
466         /*
467          * Wait for the optimization process to finish.  We go into VMWAIT
468          * mode here so GC suspension won't have to wait for us.
469          */
470         oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT);
471         while (true) {
472             gotPid = waitpid(pid, &status, 0);
473             if (gotPid == -1 && errno == EINTR) {
474                 LOGD("waitpid interrupted, retrying\n");
475             } else {
476                 break;
477             }
478         }
479         dvmChangeStatus(NULL, oldStatus);
480         if (gotPid != pid) {
481             LOGE("waitpid failed: wanted %d, got %d: %s\n",
482                 (int) pid, (int) gotPid, strerror(errno));
483             return false;
484         }
485
486         if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
487             LOGD("DexOpt: --- END '%s' (success) ---\n", lastPart);
488             return true;
489         } else {
490             LOGW("DexOpt: --- END '%s' --- status=0x%04x, process failed\n",
491                 lastPart, status);
492             return false;
493         }
494     }
495 }
496
497 /*
498  * Do the actual optimization.  This is called directly for "minimal"
499  * optimization, or from a newly-created process for "full" optimization.
500  *
501  * For best use of disk/memory, we want to extract once and perform
502  * optimizations in place.  If the file has to expand or contract
503  * to match local structure padding/alignment expectations, we want
504  * to do the rewrite as part of the extract, rather than extracting
505  * into a temp file and slurping it back out.  (The structure alignment
506  * is currently correct for all platforms, and this isn't expected to
507  * change, so we should be okay with having it already extracted.)
508  *
509  * Returns "true" on success.
510  */
511 bool dvmContinueOptimization(int fd, off_t dexOffset, long dexLength,
512     const char* fileName, u4 modWhen, u4 crc, bool isBootstrap)
513 {
514     DexClassLookup* pClassLookup = NULL;
515     IndexMapSet* pIndexMapSet = NULL;
516     RegisterMapBuilder* pRegMapBuilder = NULL;
517     bool doVerify, doOpt;
518     u4 headerFlags = 0;
519
520     if (gDvm.classVerifyMode == VERIFY_MODE_NONE)
521         doVerify = false;
522     else if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE)
523         doVerify = !isBootstrap;
524     else /*if (gDvm.classVerifyMode == VERIFY_MODE_ALL)*/
525         doVerify = true;
526
527     if (gDvm.dexOptMode == OPTIMIZE_MODE_NONE)
528         doOpt = false;
529     else if (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED)
530         doOpt = doVerify;
531     else /*if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)*/
532         doOpt = true;
533
534     LOGV("Continuing optimization (%s, isb=%d, vfy=%d, opt=%d)\n",
535         fileName, isBootstrap, doVerify, doOpt);
536
537     assert(dexOffset >= 0);
538
539     /* quick test so we don't blow up on empty file */
540     if (dexLength < (int) sizeof(DexHeader)) {
541         LOGE("too small to be DEX\n");
542         return false;
543     }
544     if (dexOffset < (int) sizeof(DexOptHeader)) {
545         LOGE("not enough room for opt header\n");
546         return false;
547     }
548
549     bool result = false;
550
551     /*
552      * Drop this into a global so we don't have to pass it around.  We could
553      * also add a field to DexFile, but since it only pertains to DEX
554      * creation that probably doesn't make sense.
555      */
556     gDvm.optimizingBootstrapClass = isBootstrap;
557
558     {
559         /*
560          * Map the entire file (so we don't have to worry about page
561          * alignment).  The expectation is that the output file contains
562          * our DEX data plus room for a small header.
563          */
564         bool success;
565         void* mapAddr;
566         mapAddr = mmap(NULL, dexOffset + dexLength, PROT_READ|PROT_WRITE,
567                     MAP_SHARED, fd, 0);
568         if (mapAddr == MAP_FAILED) {
569             LOGE("unable to mmap DEX cache: %s\n", strerror(errno));
570             goto bail;
571         }
572
573         /*
574          * Rewrite the file.  Byte reordering, structure realigning,
575          * class verification, and bytecode optimization are all performed
576          * here.
577          *
578          * In theory the file could change size and bits could shift around.
579          * In practice this would be annoying to deal with, so the file
580          * layout is designed so that it can always be rewritten in place.
581          *
582          * This sets "headerFlags" and creates the class lookup table as
583          * part of doing the processing.
584          */
585         success = rewriteDex(((u1*) mapAddr) + dexOffset, dexLength,
586                     doVerify, doOpt, &headerFlags, &pClassLookup);
587
588         if (success) {
589             DvmDex* pDvmDex = NULL;
590             u1* dexAddr = ((u1*) mapAddr) + dexOffset;
591
592             if (dvmDexFileOpenPartial(dexAddr, dexLength, &pDvmDex) != 0) {
593                 LOGE("Unable to create DexFile\n");
594                 success = false;
595             } else {
596                 /*
597                  * If configured to do so, scan the instructions, looking
598                  * for ways to reduce the size of the resolved-constant table.
599                  * This is done post-optimization, across the instructions
600                  * in all methods in all classes (even the ones that failed
601                  * to load).
602                  */
603                 pIndexMapSet = dvmRewriteConstants(pDvmDex);
604
605                 /*
606                  * If configured to do so, generate a full set of register
607                  * maps for all verified classes.
608                  */
609                 if (gDvm.generateRegisterMaps) {
610                     pRegMapBuilder = dvmGenerateRegisterMaps(pDvmDex);
611                     if (pRegMapBuilder == NULL) {
612                         LOGE("Failed generating register maps\n");
613                         success = false;
614                     }
615                 }
616
617                 DexHeader* pHeader = (DexHeader*)pDvmDex->pHeader;
618                 updateChecksum(dexAddr, dexLength, pHeader);
619
620                 dvmDexFileFree(pDvmDex);
621             }
622         }
623
624         /* unmap the read-write version, forcing writes to disk */
625         if (msync(mapAddr, dexOffset + dexLength, MS_SYNC) != 0) {
626             LOGW("msync failed: %s\n", strerror(errno));
627             // weird, but keep going
628         }
629 #if 1
630         /*
631          * This causes clean shutdown to fail, because we have loaded classes
632          * that point into it.  For the optimizer this isn't a problem,
633          * because it's more efficient for the process to simply exit.
634          * Exclude this code when doing clean shutdown for valgrind.
635          */
636         if (munmap(mapAddr, dexOffset + dexLength) != 0) {
637             LOGE("munmap failed: %s\n", strerror(errno));
638             goto bail;
639         }
640 #endif
641
642         if (!success)
643             goto bail;
644     }
645
646     /* get start offset, and adjust deps start for 64-bit alignment */
647     off_t depsOffset, auxOffset, endOffset, adjOffset;
648     int depsLength, auxLength;
649     u4 optChecksum;
650
651     depsOffset = lseek(fd, 0, SEEK_END);
652     if (depsOffset < 0) {
653         LOGE("lseek to EOF failed: %s\n", strerror(errno));
654         goto bail;
655     }
656     adjOffset = (depsOffset + 7) & ~(0x07);
657     if (adjOffset != depsOffset) {
658         LOGV("Adjusting deps start from %d to %d\n",
659             (int) depsOffset, (int) adjOffset);
660         depsOffset = adjOffset;
661         lseek(fd, depsOffset, SEEK_SET);
662     }
663
664     /*
665      * Append the dependency list.
666      */
667     if (writeDependencies(fd, modWhen, crc) != 0) {
668         LOGW("Failed writing dependencies\n");
669         goto bail;
670     }
671
672     /* compute deps length, then adjust aux start for 64-bit alignment */
673     auxOffset = lseek(fd, 0, SEEK_END);
674     depsLength = auxOffset - depsOffset;
675
676     adjOffset = (auxOffset + 7) & ~(0x07);
677     if (adjOffset != auxOffset) {
678         LOGV("Adjusting aux start from %d to %d\n",
679             (int) auxOffset, (int) adjOffset);
680         auxOffset = adjOffset;
681         lseek(fd, auxOffset, SEEK_SET);
682     }
683
684     /*
685      * Append any auxillary pre-computed data structures.
686      */
687     if (!writeAuxData(fd, pClassLookup, pIndexMapSet, pRegMapBuilder)) {
688         LOGW("Failed writing aux data\n");
689         goto bail;
690     }
691
692     endOffset = lseek(fd, 0, SEEK_END);
693     auxLength = endOffset - auxOffset;
694
695     /* compute checksum from start of deps to end of aux area */
696     if (!computeFileChecksum(fd, depsOffset,
697             (auxOffset+auxLength) - depsOffset, &optChecksum))
698     {
699         goto bail;
700     }
701
702     /*
703      * Output the "opt" header with all values filled in and a correct
704      * magic number.
705      */
706     DexOptHeader optHdr;
707     memset(&optHdr, 0xff, sizeof(optHdr));
708     memcpy(optHdr.magic, DEX_OPT_MAGIC, 4);
709     memcpy(optHdr.magic+4, DEX_OPT_MAGIC_VERS, 4);
710     optHdr.dexOffset = (u4) dexOffset;
711     optHdr.dexLength = (u4) dexLength;
712     optHdr.depsOffset = (u4) depsOffset;
713     optHdr.depsLength = (u4) depsLength;
714     optHdr.auxOffset = (u4) auxOffset;
715     optHdr.auxLength = (u4) auxLength;
716
717     optHdr.flags = headerFlags;
718     optHdr.checksum = optChecksum;
719
720     ssize_t actual;
721     lseek(fd, 0, SEEK_SET);
722     actual = write(fd, &optHdr, sizeof(optHdr));
723     if (actual != sizeof(optHdr)) {
724         logFailedWrite(sizeof(optHdr), actual, "opt header", errno);
725         goto bail;
726     }
727
728     LOGV("Successfully wrote DEX header\n");
729     result = true;
730
731     //dvmRegisterMapDumpStats();
732
733 bail:
734     dvmFreeIndexMapSet(pIndexMapSet);
735     dvmFreeRegisterMapBuilder(pRegMapBuilder);
736     free(pClassLookup);
737     return result;
738 }
739
740
741 /*
742  * Get the cache file name from a ClassPathEntry.
743  */
744 static const char* getCacheFileName(const ClassPathEntry* cpe)
745 {
746     switch (cpe->kind) {
747     case kCpeJar:
748         return dvmGetJarFileCacheFileName((JarFile*) cpe->ptr);
749     case kCpeDex:
750         return dvmGetRawDexFileCacheFileName((RawDexFile*) cpe->ptr);
751     default:
752         LOGE("DexOpt: unexpected cpe kind %d\n", cpe->kind);
753         dvmAbort();
754         return NULL;
755     }
756 }
757
758 /*
759  * Get the SHA-1 signature.
760  */
761 static const u1* getSignature(const ClassPathEntry* cpe)
762 {
763     DvmDex* pDvmDex;
764
765     switch (cpe->kind) {
766     case kCpeJar:
767         pDvmDex = dvmGetJarFileDex((JarFile*) cpe->ptr);
768         break;
769     case kCpeDex:
770         pDvmDex = dvmGetRawDexFileDex((RawDexFile*) cpe->ptr);
771         break;
772     default:
773         LOGE("unexpected cpe kind %d\n", cpe->kind);
774         dvmAbort();
775         pDvmDex = NULL;         // make gcc happy
776     }
777
778     assert(pDvmDex != NULL);
779     return pDvmDex->pDexFile->pHeader->signature;
780 }
781
782
783 /*
784  * Dependency layout:
785  *  4b  Source file modification time, in seconds since 1970 UTC
786  *  4b  CRC-32 from Zip entry, or Adler32 from source DEX header
787  *  4b  Dalvik VM build number
788  *  4b  Number of dependency entries that follow
789  *  Dependency entries:
790  *    4b  Name length (including terminating null)
791  *    var Full path of cache entry (null terminated)
792  *    20b SHA-1 signature from source DEX file
793  *
794  * If this changes, update DEX_OPT_MAGIC_VERS.
795  */
796 static const size_t kMinDepSize = 4 * 4;
797 static const size_t kMaxDepSize = 4 * 4 + 1024;     // sanity check
798
799 /*
800  * Read the "opt" header, verify it, then read the dependencies section
801  * and verify that data as well.
802  *
803  * If "sourceAvail" is "true", this will verify that "modWhen" and "crc"
804  * match up with what is stored in the header.  If they don't, we reject
805  * the file so that it can be recreated from the updated original.  If
806  * "sourceAvail" isn't set, e.g. for a .odex file, we ignore these arguments.
807  *
808  * On successful return, the file will be seeked immediately past the
809  * "opt" header.
810  */
811 bool dvmCheckOptHeaderAndDependencies(int fd, bool sourceAvail, u4 modWhen,
812     u4 crc, bool expectVerify, bool expectOpt)
813 {
814     DexOptHeader optHdr;
815     u1* depData = NULL;
816     const u1* magic;
817     off_t posn;
818     int result = false;
819     ssize_t actual;
820
821     /*
822      * Start at the start.  The "opt" header, when present, will always be
823      * the first thing in the file.
824      */
825     if (lseek(fd, 0, SEEK_SET) != 0) {
826         LOGE("DexOpt: failed to seek to start of file: %s\n", strerror(errno));
827         goto bail;
828     }
829
830     /*
831      * Read and do trivial verification on the opt header.  The header is
832      * always in host byte order.
833      */
834     if (read(fd, &optHdr, sizeof(optHdr)) != sizeof(optHdr)) {
835         LOGE("DexOpt: failed reading opt header: %s\n", strerror(errno));
836         goto bail;
837     }
838
839     magic = optHdr.magic;
840     if (memcmp(magic, DEX_OPT_MAGIC, 4) != 0) {
841         /* not a DEX file, or previous attempt was interrupted */
842         LOGD("DexOpt: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
843             magic[0], magic[1], magic[2], magic[3]);
844         goto bail;
845     }
846     if (memcmp(magic+4, DEX_OPT_MAGIC_VERS, 4) != 0) {
847         LOGW("DexOpt: stale opt version (0x%02x %02x %02x %02x)\n",
848             magic[4], magic[5], magic[6], magic[7]);
849         goto bail;
850     }
851     if (optHdr.depsLength < kMinDepSize || optHdr.depsLength > kMaxDepSize) {
852         LOGW("DexOpt: weird deps length %d, bailing\n", optHdr.depsLength);
853         goto bail;
854     }
855
856     /*
857      * Do the header flags match up with what we want?
858      *
859      * This is useful because it allows us to automatically regenerate
860      * a file when settings change (e.g. verification is now mandatory),
861      * but can cause difficulties if the bootstrap classes we depend upon
862      * were handled differently than the current options specify.  We get
863      * upset because they're not verified or optimized, but we're not able
864      * to regenerate them because the installer won't let us.
865      *
866      * (This is also of limited value when !sourceAvail.)
867      *
868      * So, for now, we essentially ignore "expectVerify" and "expectOpt"
869      * by limiting the match mask.
870      *
871      * The only thing we really can't handle is incorrect byte-ordering.
872      */
873     const u4 matchMask = DEX_OPT_FLAG_BIG;
874     u4 expectedFlags = 0;
875 #if __BYTE_ORDER != __LITTLE_ENDIAN
876     expectedFlags |= DEX_OPT_FLAG_BIG;
877 #endif
878     if (expectVerify)
879         expectedFlags |= DEX_FLAG_VERIFIED;
880     if (expectOpt)
881         expectedFlags |= DEX_OPT_FLAG_FIELDS | DEX_OPT_FLAG_INVOCATIONS;
882     if ((expectedFlags & matchMask) != (optHdr.flags & matchMask)) {
883         LOGI("DexOpt: header flag mismatch (0x%02x vs 0x%02x, mask=0x%02x)\n",
884             expectedFlags, optHdr.flags, matchMask);
885         goto bail;
886     }
887
888     posn = lseek(fd, optHdr.depsOffset, SEEK_SET);
889     if (posn < 0) {
890         LOGW("DexOpt: seek to deps failed: %s\n", strerror(errno));
891         goto bail;
892     }
893
894     /*
895      * Read all of the dependency stuff into memory.
896      */
897     depData = (u1*) malloc(optHdr.depsLength);
898     if (depData == NULL) {
899         LOGW("DexOpt: unable to allocate %d bytes for deps\n",
900             optHdr.depsLength);
901         goto bail;
902     }
903     actual = read(fd, depData, optHdr.depsLength);
904     if (actual != (ssize_t) optHdr.depsLength) {
905         LOGW("DexOpt: failed reading deps: %d of %d (err=%s)\n",
906             (int) actual, optHdr.depsLength, strerror(errno));
907         goto bail;
908     }
909
910     /*
911      * Verify simple items.
912      */
913     const u1* ptr;
914     u4 val;
915
916     ptr = depData;
917     val = read4LE(&ptr);
918     if (sourceAvail && val != modWhen) {
919         LOGI("DexOpt: source file mod time mismatch (%08x vs %08x)\n",
920             val, modWhen);
921         goto bail;
922     }
923     val = read4LE(&ptr);
924     if (sourceAvail && val != crc) {
925         LOGI("DexOpt: source file CRC mismatch (%08x vs %08x)\n", val, crc);
926         goto bail;
927     }
928     val = read4LE(&ptr);
929     if (val != DALVIK_VM_BUILD) {
930         LOGD("DexOpt: VM build version mismatch (%d vs %d)\n",
931             val, DALVIK_VM_BUILD);
932         goto bail;
933     }
934
935     /*
936      * Verify dependencies on other cached DEX files.  It must match
937      * exactly with what is currently defined in the bootclasspath.
938      */
939     ClassPathEntry* cpe;
940     u4 numDeps;
941
942     numDeps = read4LE(&ptr);
943     LOGV("+++ DexOpt: numDeps = %d\n", numDeps);
944     for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) {
945         const char* cacheFileName = getCacheFileName(cpe);
946         const u1* signature = getSignature(cpe);
947         size_t len = strlen(cacheFileName) +1;
948         u4 storedStrLen;
949
950         if (numDeps == 0) {
951             /* more entries in bootclasspath than in deps list */
952             LOGI("DexOpt: not all deps represented\n");
953             goto bail;
954         }
955
956         storedStrLen = read4LE(&ptr);
957         if (len != storedStrLen ||
958             strcmp(cacheFileName, (const char*) ptr) != 0)
959         {
960             LOGI("DexOpt: mismatch dep name: '%s' vs. '%s'\n",
961                 cacheFileName, ptr);
962             goto bail;
963         }
964
965         ptr += storedStrLen;
966
967         if (memcmp(signature, ptr, kSHA1DigestLen) != 0) {
968             LOGI("DexOpt: mismatch dep signature for '%s'\n", cacheFileName);
969             goto bail;
970         }
971         ptr += kSHA1DigestLen;
972
973         LOGV("DexOpt: dep match on '%s'\n", cacheFileName);
974
975         numDeps--;
976     }
977
978     if (numDeps != 0) {
979         /* more entries in deps list than in classpath */
980         LOGI("DexOpt: Some deps went away\n");
981         goto bail;
982     }
983
984     // consumed all data and no more?
985     if (ptr != depData + optHdr.depsLength) {
986         LOGW("DexOpt: Spurious dep data? %d vs %d\n",
987             (int) (ptr - depData), optHdr.depsLength);
988         assert(false);
989     }
990
991     result = true;
992
993 bail:
994     free(depData);
995     return result;
996 }
997
998 /*
999  * Write the dependency info to "fd" at the current file position.
1000  */
1001 static int writeDependencies(int fd, u4 modWhen, u4 crc)
1002 {
1003     u1* buf = NULL;
1004     ssize_t actual;
1005     int result = -1;
1006     ssize_t bufLen;
1007     ClassPathEntry* cpe;
1008     int i, numDeps;
1009
1010     /*
1011      * Count up the number of completed entries in the bootclasspath.
1012      */
1013     numDeps = 0;
1014     bufLen = 0;
1015     for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) {
1016         const char* cacheFileName = getCacheFileName(cpe);
1017         LOGV("+++ DexOpt: found dep '%s'\n", cacheFileName);
1018
1019         numDeps++;
1020         bufLen += strlen(cacheFileName) +1;
1021     }
1022
1023     bufLen += 4*4 + numDeps * (4+kSHA1DigestLen);
1024
1025     buf = malloc(bufLen);
1026
1027     set4LE(buf+0, modWhen);
1028     set4LE(buf+4, crc);
1029     set4LE(buf+8, DALVIK_VM_BUILD);
1030     set4LE(buf+12, numDeps);
1031
1032     // TODO: do we want to add dvmGetInlineOpsTableLength() here?  Won't
1033     // help us if somebody replaces an existing entry, but it'd catch
1034     // additions/removals.
1035
1036     u1* ptr = buf + 4*4;
1037     for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) {
1038         const char* cacheFileName = getCacheFileName(cpe);
1039         const u1* signature = getSignature(cpe);
1040         int len = strlen(cacheFileName) +1;
1041
1042         if (ptr + 4 + len + kSHA1DigestLen > buf + bufLen) {
1043             LOGE("DexOpt: overran buffer\n");
1044             dvmAbort();
1045         }
1046
1047         set4LE(ptr, len);
1048         ptr += 4;
1049         memcpy(ptr, cacheFileName, len);
1050         ptr += len;
1051         memcpy(ptr, signature, kSHA1DigestLen);
1052         ptr += kSHA1DigestLen;
1053     }
1054
1055     assert(ptr == buf + bufLen);
1056
1057     actual = write(fd, buf, bufLen);
1058     if (actual != bufLen) {
1059         result = (errno != 0) ? errno : -1;
1060         logFailedWrite(bufLen, actual, "dep info", errno);
1061     } else {
1062         result = 0;
1063     }
1064
1065     free(buf);
1066     return result;
1067 }
1068
1069
1070 /*
1071  * Write a block of data in "chunk" format.
1072  *
1073  * The chunk header fields are always in "native" byte order.  If "size"
1074  * is not a multiple of 8 bytes, the data area is padded out.
1075  */
1076 static bool writeChunk(int fd, u4 type, const void* data, size_t size)
1077 {
1078     ssize_t actual;
1079     union {             /* save a syscall by grouping these together */
1080         char raw[8];
1081         struct {
1082             u4 type;
1083             u4 size;
1084         } ts;
1085     } header;
1086
1087     assert(sizeof(header) == 8);
1088
1089     LOGV("Writing chunk, type=%.4s size=%d\n", (char*) &type, size);
1090
1091     header.ts.type = type;
1092     header.ts.size = (u4) size;
1093     actual = write(fd, &header, sizeof(header));
1094     if (actual != sizeof(header)) {
1095         logFailedWrite(size, actual, "aux chunk header write", errno);
1096         return false;
1097     }
1098
1099     if (size > 0) {
1100         actual = write(fd, data, size);
1101         if (actual != (ssize_t) size) {
1102             logFailedWrite(size, actual, "aux chunk write", errno);
1103             return false;
1104         }
1105     }
1106
1107     /* if necessary, pad to 64-bit alignment */
1108     if ((size & 7) != 0) {
1109         int padSize = 8 - (size & 7);
1110         LOGV("size was %d, inserting %d pad bytes\n", size, padSize);
1111         lseek(fd, padSize, SEEK_CUR);
1112     }
1113
1114     assert( ((int)lseek(fd, 0, SEEK_CUR) & 7) == 0);
1115
1116     return true;
1117 }
1118
1119 /*
1120  * Write aux data.
1121  *
1122  * We have different pieces, some of which may be optional.  To make the
1123  * most effective use of space, we use a "chunk" format, with a 4-byte
1124  * type and a 4-byte length.  We guarantee 64-bit alignment for the data,
1125  * so it can be used directly when the file is mapped for reading.
1126  */
1127 static bool writeAuxData(int fd, const DexClassLookup* pClassLookup,
1128     const IndexMapSet* pIndexMapSet, const RegisterMapBuilder* pRegMapBuilder)
1129 {
1130     /* pre-computed class lookup hash table */
1131     if (!writeChunk(fd, (u4) kDexChunkClassLookup,
1132             pClassLookup, pClassLookup->size))
1133     {
1134         return false;
1135     }
1136
1137     /* remapped constants (optional) */
1138     if (pIndexMapSet != NULL) {
1139         if (!writeChunk(fd, pIndexMapSet->chunkType,
1140                 pIndexMapSet->chunkData, pIndexMapSet->chunkDataLen))
1141         {
1142             return false;
1143         }
1144     }
1145
1146     /* register maps (optional) */
1147     if (pRegMapBuilder != NULL) {
1148         if (!writeChunk(fd, (u4) kDexChunkRegisterMaps,
1149                 pRegMapBuilder->data, pRegMapBuilder->size))
1150         {
1151             return false;
1152         }
1153     }
1154
1155     /* write the end marker */
1156     if (!writeChunk(fd, (u4) kDexChunkEnd, NULL, 0)) {
1157         return false;
1158     }
1159
1160     return true;
1161 }
1162
1163 /*
1164  * Log a failed write.
1165  */
1166 static void logFailedWrite(size_t expected, ssize_t actual, const char* msg,
1167     int err)
1168 {
1169     LOGE("Write failed: %s (%d of %d): %s\n",
1170         msg, (int)actual, (int)expected, strerror(err));
1171 }
1172
1173 /*
1174  * Compute a checksum on a piece of an open file.
1175  *
1176  * File will be positioned at end of checksummed area.
1177  *
1178  * Returns "true" on success.
1179  */
1180 static bool computeFileChecksum(int fd, off_t start, size_t length, u4* pSum)
1181 {
1182     unsigned char readBuf[8192];
1183     ssize_t actual;
1184     uLong adler;
1185
1186     if (lseek(fd, start, SEEK_SET) != start) {
1187         LOGE("Unable to seek to start of checksum area (%ld): %s\n",
1188             (long) start, strerror(errno));
1189         return false;
1190     }
1191
1192     adler = adler32(0L, Z_NULL, 0);
1193
1194     while (length != 0) {
1195         size_t wanted = (length < sizeof(readBuf)) ? length : sizeof(readBuf);
1196         actual = read(fd, readBuf, wanted);
1197         if (actual <= 0) {
1198             LOGE("Read failed (%d) while computing checksum (len=%zu): %s\n",
1199                 (int) actual, length, strerror(errno));
1200             return false;
1201         }
1202
1203         adler = adler32(adler, readBuf, actual);
1204
1205         length -= actual;
1206     }
1207
1208     *pSum = adler;
1209     return true;
1210 }
1211
1212
1213 /*
1214  * ===========================================================================
1215  *      Optimizations
1216  * ===========================================================================
1217  */
1218
1219 /*
1220  * Perform in-place rewrites on a memory-mapped DEX file.
1221  *
1222  * This happens in a short-lived child process, so we can go nutty with
1223  * loading classes and allocating memory.
1224  */
1225 static bool rewriteDex(u1* addr, int len, bool doVerify, bool doOpt,
1226     u4* pHeaderFlags, DexClassLookup** ppClassLookup)
1227 {
1228     u8 prepWhen, loadWhen, verifyWhen, optWhen;
1229     DvmDex* pDvmDex = NULL;
1230     bool result = false;
1231
1232     *pHeaderFlags = 0;
1233
1234     LOGV("+++ swapping bytes\n");
1235     if (dexFixByteOrdering(addr, len) != 0)
1236         goto bail;
1237 #if __BYTE_ORDER != __LITTLE_ENDIAN
1238     *pHeaderFlags |= DEX_OPT_FLAG_BIG;
1239 #endif
1240
1241     /*
1242      * Now that the DEX file can be read directly, create a DexFile for it.
1243      */
1244     if (dvmDexFileOpenPartial(addr, len, &pDvmDex) != 0) {
1245         LOGE("Unable to create DexFile\n");
1246         goto bail;
1247     }
1248
1249     /*
1250      * Create the class lookup table.
1251      */
1252     //startWhen = dvmGetRelativeTimeUsec();
1253     *ppClassLookup = dexCreateClassLookup(pDvmDex->pDexFile);
1254     if (*ppClassLookup == NULL)
1255         goto bail;
1256
1257     /*
1258      * Bail out early if they don't want The Works.  The current implementation
1259      * doesn't fork a new process if this flag isn't set, so we really don't
1260      * want to continue on with the crazy class loading.
1261      */
1262     if (!doVerify && !doOpt) {
1263         result = true;
1264         goto bail;
1265     }
1266
1267     /* this is needed for the next part */
1268     pDvmDex->pDexFile->pClassLookup = *ppClassLookup;
1269
1270     prepWhen = dvmGetRelativeTimeUsec();
1271
1272     /*
1273      * Load all classes found in this DEX file.  If they fail to load for
1274      * some reason, they won't get verified (which is as it should be).
1275      */
1276     if (!loadAllClasses(pDvmDex))
1277         goto bail;
1278     loadWhen = dvmGetRelativeTimeUsec();
1279
1280     /*
1281      * Verify all classes in the DEX file.  Export the "is verified" flag
1282      * to the DEX file we're creating.
1283      */
1284     if (doVerify) {
1285         dvmVerifyAllClasses(pDvmDex->pDexFile);
1286         *pHeaderFlags |= DEX_FLAG_VERIFIED;
1287     }
1288     verifyWhen = dvmGetRelativeTimeUsec();
1289
1290     /*
1291      * Optimize the classes we successfully loaded.  If the opt mode is
1292      * OPTIMIZE_MODE_VERIFIED, each class must have been successfully
1293      * verified or we'll skip it.
1294      */
1295 #ifndef PROFILE_FIELD_ACCESS
1296     if (doOpt) {
1297         optimizeLoadedClasses(pDvmDex->pDexFile);
1298         *pHeaderFlags |= DEX_OPT_FLAG_FIELDS | DEX_OPT_FLAG_INVOCATIONS;
1299     }
1300 #endif
1301     optWhen = dvmGetRelativeTimeUsec();
1302
1303     LOGD("DexOpt: load %dms, verify %dms, opt %dms\n",
1304         (int) (loadWhen - prepWhen) / 1000,
1305         (int) (verifyWhen - loadWhen) / 1000,
1306         (int) (optWhen - verifyWhen) / 1000);
1307
1308     result = true;
1309
1310 bail:
1311     /* free up storage */
1312     dvmDexFileFree(pDvmDex);
1313
1314     return result;
1315 }
1316
1317 /*
1318  * Update the Adler-32 checksum stored in the DEX file.  This covers the
1319  * swapped and optimized DEX data, but does not include the opt header
1320  * or auxillary data.
1321  */
1322 static void updateChecksum(u1* addr, int len, DexHeader* pHeader)
1323 {
1324     /*
1325      * Rewrite the checksum.  We leave the SHA-1 signature alone.
1326      */
1327     uLong adler = adler32(0L, Z_NULL, 0);
1328     const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum);
1329
1330     adler = adler32(adler, addr + nonSum, len - nonSum);
1331     pHeader->checksum = adler;
1332 }
1333
1334 /*
1335  * Try to load all classes in the specified DEX.  If they have some sort
1336  * of broken dependency, e.g. their superclass lives in a different DEX
1337  * that wasn't previously loaded into the bootstrap class path, loading
1338  * will fail.  This is the desired behavior.
1339  *
1340  * We have no notion of class loader at this point, so we load all of
1341  * the classes with the bootstrap class loader.  It turns out this has
1342  * exactly the behavior we want, and has no ill side effects because we're
1343  * running in a separate process and anything we load here will be forgotten.
1344  *
1345  * We set the CLASS_MULTIPLE_DEFS flag here if we see multiple definitions.
1346  * This works because we only call here as part of optimization / pre-verify,
1347  * not during verification as part of loading a class into a running VM.
1348  *
1349  * This returns "false" if the world is too screwed up to do anything
1350  * useful at all.
1351  */
1352 static bool loadAllClasses(DvmDex* pDvmDex)
1353 {
1354     u4 count = pDvmDex->pDexFile->pHeader->classDefsSize;
1355     u4 idx;
1356     int loaded = 0;
1357
1358     LOGV("DexOpt: +++ trying to load %d classes\n", count);
1359
1360     dvmSetBootPathExtraDex(pDvmDex);
1361
1362     /*
1363      * We have some circularity issues with Class and Object that are most
1364      * easily avoided by ensuring that Object is never the first thing we
1365      * try to find.  Take care of that here.  (We only need to do this when
1366      * loading classes from the DEX file that contains Object, and only
1367      * when Object comes first in the list, but it costs very little to
1368      * do it in all cases.)
1369      */
1370     if (dvmFindSystemClass("Ljava/lang/Class;") == NULL) {
1371         LOGE("ERROR: java.lang.Class does not exist!\n");
1372         return false;
1373     }
1374
1375     for (idx = 0; idx < count; idx++) {
1376         const DexClassDef* pClassDef;
1377         const char* classDescriptor;
1378         ClassObject* newClass;
1379
1380         pClassDef = dexGetClassDef(pDvmDex->pDexFile, idx);
1381         classDescriptor =
1382             dexStringByTypeIdx(pDvmDex->pDexFile, pClassDef->classIdx);
1383
1384         LOGV("+++  loading '%s'", classDescriptor);
1385         //newClass = dvmDefineClass(pDexFile, classDescriptor,
1386         //        NULL);
1387         newClass = dvmFindSystemClassNoInit(classDescriptor);
1388         if (newClass == NULL) {
1389             LOGV("DexOpt: failed loading '%s'\n", classDescriptor);
1390             dvmClearOptException(dvmThreadSelf());
1391         } else if (newClass->pDvmDex != pDvmDex) {
1392             /*
1393              * We don't load the new one, and we tag the first one found
1394              * with the "multiple def" flag so the resolver doesn't try
1395              * to make it available.
1396              */
1397             LOGD("DexOpt: '%s' has an earlier definition; blocking out\n",
1398                 classDescriptor);
1399             SET_CLASS_FLAG(newClass, CLASS_MULTIPLE_DEFS);
1400         } else {
1401             loaded++;
1402         }
1403     }
1404     LOGV("DexOpt: +++ successfully loaded %d classes\n", loaded);
1405
1406     dvmSetBootPathExtraDex(NULL);
1407     return true;
1408 }
1409
1410
1411 /*
1412  * Create a table of inline substitutions.
1413  *
1414  * TODO: this is currently just a linear array.  We will want to put this
1415  * into a hash table as the list size increases.
1416  */
1417 static InlineSub* createInlineSubsTable(void)
1418 {
1419     const InlineOperation* ops = dvmGetInlineOpsTable();
1420     const int count = dvmGetInlineOpsTableLength();
1421     InlineSub* table;
1422     Method* method;
1423     ClassObject* clazz;
1424     int i, tableIndex;
1425
1426     /*
1427      * Allocate for optimism: one slot per entry, plus an end-of-list marker.
1428      */
1429     table = malloc(sizeof(InlineSub) * (count+1));
1430
1431     tableIndex = 0;
1432     for (i = 0; i < count; i++) {
1433         clazz = dvmFindClassNoInit(ops[i].classDescriptor, NULL);
1434         if (clazz == NULL) {
1435             LOGV("DexOpt: can't inline for class '%s': not found\n",
1436                 ops[i].classDescriptor);
1437             dvmClearOptException(dvmThreadSelf());
1438         } else {
1439             /*
1440              * Method could be virtual or direct.  Try both.  Don't use
1441              * the "hier" versions.
1442              */
1443             method = dvmFindDirectMethodByDescriptor(clazz, ops[i].methodName,
1444                         ops[i].methodSignature);
1445             if (method == NULL)
1446                 method = dvmFindVirtualMethodByDescriptor(clazz, ops[i].methodName,
1447                         ops[i].methodSignature);
1448             if (method == NULL) {
1449                 LOGW("DexOpt: can't inline %s.%s %s: method not found\n",
1450                     ops[i].classDescriptor, ops[i].methodName,
1451                     ops[i].methodSignature);
1452             } else {
1453                 if (!dvmIsFinalClass(clazz) && !dvmIsFinalMethod(method)) {
1454                     LOGW("DexOpt: WARNING: inline op on non-final class/method "
1455                          "%s.%s\n",
1456                         clazz->descriptor, method->name);
1457                     /* fail? */
1458                 }
1459                 if (dvmIsSynchronizedMethod(method) ||
1460                     dvmIsDeclaredSynchronizedMethod(method))
1461                 {
1462                     LOGW("DexOpt: WARNING: inline op on synchronized method "
1463                          "%s.%s\n",
1464                         clazz->descriptor, method->name);
1465                     /* fail? */
1466                 }
1467
1468                 table[tableIndex].method = method;
1469                 table[tableIndex].inlineIdx = i;
1470                 tableIndex++;
1471
1472                 LOGV("DexOpt: will inline %d: %s.%s %s\n", i,
1473                     ops[i].classDescriptor, ops[i].methodName,
1474                     ops[i].methodSignature);
1475             }
1476         }
1477     }
1478
1479     /* mark end of table */
1480     table[tableIndex].method = NULL;
1481     LOGV("DexOpt: inline table has %d entries\n", tableIndex);
1482
1483     return table;
1484 }
1485
1486 /*
1487  * Run through all classes that were successfully loaded from this DEX
1488  * file and optimize their code sections.
1489  */
1490 static void optimizeLoadedClasses(DexFile* pDexFile)
1491 {
1492     u4 count = pDexFile->pHeader->classDefsSize;
1493     u4 idx;
1494     InlineSub* inlineSubs = NULL;
1495
1496     LOGV("DexOpt: +++ optimizing up to %d classes\n", count);
1497     assert(gDvm.dexOptMode != OPTIMIZE_MODE_NONE);
1498
1499     inlineSubs = createInlineSubsTable();
1500
1501     for (idx = 0; idx < count; idx++) {
1502         const DexClassDef* pClassDef;
1503         const char* classDescriptor;
1504         ClassObject* clazz;
1505
1506         pClassDef = dexGetClassDef(pDexFile, idx);
1507         classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
1508
1509         /* all classes are loaded into the bootstrap class loader */
1510         clazz = dvmLookupClass(classDescriptor, NULL, false);
1511         if (clazz != NULL) {
1512             if ((pClassDef->accessFlags & CLASS_ISPREVERIFIED) == 0 &&
1513                 gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED)
1514             {
1515                 LOGV("DexOpt: not optimizing '%s': not verified\n",
1516                     classDescriptor);
1517             } else if (clazz->pDvmDex->pDexFile != pDexFile) {
1518                 /* shouldn't be here -- verifier should have caught */
1519                 LOGD("DexOpt: not optimizing '%s': multiple definitions\n",
1520                     classDescriptor);
1521             } else {
1522                 optimizeClass(clazz, inlineSubs);
1523
1524                 /* set the flag whether or not we actually did anything */
1525                 ((DexClassDef*)pClassDef)->accessFlags |=
1526                     CLASS_ISOPTIMIZED;
1527             }
1528         } else {
1529             LOGV("DexOpt: not optimizing unavailable class '%s'\n",
1530                 classDescriptor);
1531         }
1532     }
1533
1534     free(inlineSubs);
1535 }
1536
1537 /*
1538  * Optimize the specified class.
1539  */
1540 static void optimizeClass(ClassObject* clazz, const InlineSub* inlineSubs)
1541 {
1542     int i;
1543
1544     for (i = 0; i < clazz->directMethodCount; i++) {
1545         if (!optimizeMethod(&clazz->directMethods[i], inlineSubs))
1546             goto fail;
1547     }
1548     for (i = 0; i < clazz->virtualMethodCount; i++) {
1549         if (!optimizeMethod(&clazz->virtualMethods[i], inlineSubs))
1550             goto fail;
1551     }
1552
1553     return;
1554
1555 fail:
1556     LOGV("DexOpt: ceasing optimization attempts on %s\n", clazz->descriptor);
1557 }
1558
1559 /*
1560  * Optimize instructions in a method.
1561  *
1562  * Returns "true" if all went well, "false" if we bailed out early when
1563  * something failed.
1564  */
1565 static bool optimizeMethod(Method* method, const InlineSub* inlineSubs)
1566 {
1567     u4 insnsSize;
1568     u2* insns;
1569     u2 inst;
1570
1571     if (dvmIsNativeMethod(method) || dvmIsAbstractMethod(method))
1572         return true;
1573
1574     insns = (u2*) method->insns;
1575     assert(insns != NULL);
1576     insnsSize = dvmGetMethodInsnsSize(method);
1577
1578     while (insnsSize > 0) {
1579         int width;
1580
1581         inst = *insns & 0xff;
1582
1583         switch (inst) {
1584         case OP_IGET:
1585         case OP_IGET_BOOLEAN:
1586         case OP_IGET_BYTE:
1587         case OP_IGET_CHAR:
1588         case OP_IGET_SHORT:
1589             rewriteInstField(method, insns, OP_IGET_QUICK);
1590             break;
1591         case OP_IGET_WIDE:
1592             rewriteInstField(method, insns, OP_IGET_WIDE_QUICK);
1593             break;
1594         case OP_IGET_OBJECT:
1595             rewriteInstField(method, insns, OP_IGET_OBJECT_QUICK);
1596             break;
1597         case OP_IPUT:
1598         case OP_IPUT_BOOLEAN:
1599         case OP_IPUT_BYTE:
1600         case OP_IPUT_CHAR:
1601         case OP_IPUT_SHORT:
1602             rewriteInstField(method, insns, OP_IPUT_QUICK);
1603             break;
1604         case OP_IPUT_WIDE:
1605             rewriteInstField(method, insns, OP_IPUT_WIDE_QUICK);
1606             break;
1607         case OP_IPUT_OBJECT:
1608             rewriteInstField(method, insns, OP_IPUT_OBJECT_QUICK);
1609             break;
1610
1611         case OP_INVOKE_VIRTUAL:
1612             if (!rewriteExecuteInline(method, insns, METHOD_VIRTUAL,inlineSubs))
1613             {
1614                 if (!rewriteVirtualInvoke(method, insns, OP_INVOKE_VIRTUAL_QUICK))
1615                     return false;
1616             }
1617             break;
1618         case OP_INVOKE_VIRTUAL_RANGE:
1619             if (!rewriteExecuteInlineRange(method, insns, METHOD_VIRTUAL,
1620                     inlineSubs))
1621             {
1622                 if (!rewriteVirtualInvoke(method, insns,
1623                         OP_INVOKE_VIRTUAL_QUICK_RANGE))
1624                 {
1625                     return false;
1626                 }
1627             }
1628             break;
1629         case OP_INVOKE_SUPER:
1630             if (!rewriteVirtualInvoke(method, insns, OP_INVOKE_SUPER_QUICK))
1631                 return false;
1632             break;
1633         case OP_INVOKE_SUPER_RANGE:
1634             if (!rewriteVirtualInvoke(method, insns, OP_INVOKE_SUPER_QUICK_RANGE))
1635                 return false;
1636             break;
1637
1638         case OP_INVOKE_DIRECT:
1639             if (!rewriteExecuteInline(method, insns, METHOD_DIRECT, inlineSubs))
1640             {
1641                 if (!rewriteEmptyDirectInvoke(method, insns))
1642                     return false;
1643             }
1644             break;
1645         case OP_INVOKE_DIRECT_RANGE:
1646             rewriteExecuteInlineRange(method, insns, METHOD_DIRECT, inlineSubs);
1647             break;
1648
1649         case OP_INVOKE_STATIC:
1650             rewriteExecuteInline(method, insns, METHOD_STATIC, inlineSubs);
1651             break;
1652         case OP_INVOKE_STATIC_RANGE:
1653             rewriteExecuteInlineRange(method, insns, METHOD_STATIC, inlineSubs);
1654             break;
1655
1656         default:
1657             // ignore this instruction
1658             ;
1659         }
1660
1661         if (*insns == kPackedSwitchSignature) {
1662             width = 4 + insns[1] * 2;
1663         } else if (*insns == kSparseSwitchSignature) {
1664             width = 2 + insns[1] * 4;
1665         } else if (*insns == kArrayDataSignature) {
1666             u2 elemWidth = insns[1];
1667             u4 len = insns[2] | (((u4)insns[3]) << 16);
1668             width = 4 + (elemWidth * len + 1) / 2;
1669         } else {
1670             width = dexGetInstrWidth(gDvm.instrWidth, inst);
1671         }
1672         assert(width > 0);
1673
1674         insns += width;
1675         insnsSize -= width;
1676     }
1677
1678     assert(insnsSize == 0);
1679     return true;
1680 }
1681
1682
1683 /*
1684  * If "referrer" and "resClass" don't come from the same DEX file, and
1685  * the DEX we're working on is not destined for the bootstrap class path,
1686  * tweak the class loader so package-access checks work correctly.
1687  *
1688  * Only do this if we're doing pre-verification or optimization.
1689  */
1690 static void tweakLoader(ClassObject* referrer, ClassObject* resClass)
1691 {
1692     if (!gDvm.optimizing)
1693         return;
1694     assert(referrer->classLoader == NULL);
1695     assert(resClass->classLoader == NULL);
1696
1697     if (!gDvm.optimizingBootstrapClass) {
1698         /* class loader for an array class comes from element type */
1699         if (dvmIsArrayClass(resClass))
1700             resClass = resClass->elementClass;
1701         if (referrer->pDvmDex != resClass->pDvmDex)
1702             resClass->classLoader = (Object*) 0xdead3333;
1703     }
1704 }
1705
1706 /*
1707  * Undo the effects of tweakLoader.
1708  */
1709 static void untweakLoader(ClassObject* referrer, ClassObject* resClass)
1710 {
1711     if (!gDvm.optimizing || gDvm.optimizingBootstrapClass)
1712         return;
1713
1714     if (dvmIsArrayClass(resClass))
1715         resClass = resClass->elementClass;
1716     resClass->classLoader = NULL;
1717 }
1718
1719
1720 /*
1721  * Alternate version of dvmResolveClass for use with verification and
1722  * optimization.  Performs access checks on every resolve, and refuses
1723  * to acknowledge the existence of classes defined in more than one DEX
1724  * file.
1725  *
1726  * Exceptions caused by failures are cleared before returning.
1727  *
1728  * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
1729  */
1730 ClassObject* dvmOptResolveClass(ClassObject* referrer, u4 classIdx,
1731     VerifyError* pFailure)
1732 {
1733     DvmDex* pDvmDex = referrer->pDvmDex;
1734     ClassObject* resClass;
1735
1736     /*
1737      * Check the table first.  If not there, do the lookup by name.
1738      */
1739     resClass = dvmDexGetResolvedClass(pDvmDex, classIdx);
1740     if (resClass == NULL) {
1741         const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, classIdx);
1742         if (className[0] != '\0' && className[1] == '\0') {
1743             /* primitive type */
1744             resClass = dvmFindPrimitiveClass(className[0]);
1745         } else {
1746             resClass = dvmFindClassNoInit(className, referrer->classLoader);
1747         }
1748         if (resClass == NULL) {
1749             /* not found, exception should be raised */
1750             LOGV("DexOpt: class %d (%s) not found\n",
1751                 classIdx,
1752                 dexStringByTypeIdx(pDvmDex->pDexFile, classIdx));
1753             if (pFailure != NULL) {
1754                 /* dig through the wrappers to find the original failure */
1755                 Object* excep = dvmGetException(dvmThreadSelf());
1756                 while (true) {
1757                     Object* cause = dvmGetExceptionCause(excep);
1758                     if (cause == NULL)
1759                         break;
1760                     excep = cause;
1761                 }
1762                 if (strcmp(excep->clazz->descriptor,
1763                     "Ljava/lang/IncompatibleClassChangeError;") == 0)
1764                 {
1765                     *pFailure = VERIFY_ERROR_CLASS_CHANGE;
1766                 } else {
1767                     *pFailure = VERIFY_ERROR_NO_CLASS;
1768                 }
1769             }
1770             dvmClearOptException(dvmThreadSelf());
1771             return NULL;
1772         }
1773
1774         /*
1775          * Add it to the resolved table so we're faster on the next lookup.
1776          */
1777         dvmDexSetResolvedClass(pDvmDex, classIdx, resClass);
1778     }
1779
1780     /* multiple definitions? */
1781     if (IS_CLASS_FLAG_SET(resClass, CLASS_MULTIPLE_DEFS)) {
1782         LOGI("DexOpt: not resolving ambiguous class '%s'\n",
1783             resClass->descriptor);
1784         if (pFailure != NULL)
1785             *pFailure = VERIFY_ERROR_NO_CLASS;
1786         return NULL;
1787     }
1788
1789     /* access allowed? */
1790     tweakLoader(referrer, resClass);
1791     bool allowed = dvmCheckClassAccess(referrer, resClass);
1792     untweakLoader(referrer, resClass);
1793     if (!allowed) {
1794         LOGW("DexOpt: resolve class illegal access: %s -> %s\n",
1795             referrer->descriptor, resClass->descriptor);
1796         if (pFailure != NULL)
1797             *pFailure = VERIFY_ERROR_ACCESS_CLASS;
1798         return NULL;
1799     }
1800
1801     return resClass;
1802 }
1803
1804 /*
1805  * Alternate version of dvmResolveInstField().
1806  *
1807  * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
1808  */
1809 InstField* dvmOptResolveInstField(ClassObject* referrer, u4 ifieldIdx,
1810     VerifyError* pFailure)
1811 {
1812     DvmDex* pDvmDex = referrer->pDvmDex;
1813     InstField* resField;
1814
1815     resField = (InstField*) dvmDexGetResolvedField(pDvmDex, ifieldIdx);
1816     if (resField == NULL) {
1817         const DexFieldId* pFieldId;
1818         ClassObject* resClass;
1819
1820         pFieldId = dexGetFieldId(pDvmDex->pDexFile, ifieldIdx);
1821
1822         /*
1823          * Find the field's class.
1824          */
1825         resClass = dvmOptResolveClass(referrer, pFieldId->classIdx, pFailure);
1826         if (resClass == NULL) {
1827             //dvmClearOptException(dvmThreadSelf());
1828             assert(!dvmCheckException(dvmThreadSelf()));
1829             if (pFailure != NULL) { assert(!VERIFY_OK(*pFailure)); }
1830             return NULL;
1831         }
1832
1833         resField = (InstField*)dvmFindFieldHier(resClass,
1834             dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx),
1835             dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx));
1836         if (resField == NULL) {
1837             LOGD("DexOpt: couldn't find field %s.%s\n",
1838                 resClass->descriptor,
1839                 dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
1840             if (pFailure != NULL)
1841                 *pFailure = VERIFY_ERROR_NO_FIELD;
1842             return NULL;
1843         }
1844         if (dvmIsStaticField(&resField->field)) {
1845             LOGD("DexOpt: wanted instance, got static for field %s.%s\n",
1846                 resClass->descriptor,
1847                 dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
1848             if (pFailure != NULL)
1849                 *pFailure = VERIFY_ERROR_CLASS_CHANGE;
1850             return NULL;
1851         }
1852
1853         /*
1854          * Add it to the resolved table so we're faster on the next lookup.
1855          */
1856         dvmDexSetResolvedField(pDvmDex, ifieldIdx, (Field*) resField);
1857     }
1858
1859     /* access allowed? */
1860     tweakLoader(referrer, resField->field.clazz);
1861     bool allowed = dvmCheckFieldAccess(referrer, (Field*)resField);
1862     untweakLoader(referrer, resField->field.clazz);
1863     if (!allowed) {
1864         LOGI("DexOpt: access denied from %s to field %s.%s\n",
1865             referrer->descriptor, resField->field.clazz->descriptor,
1866             resField->field.name);
1867         if (pFailure != NULL)
1868             *pFailure = VERIFY_ERROR_ACCESS_FIELD;
1869         return NULL;
1870     }
1871
1872     return resField;
1873 }
1874
1875 /*
1876  * Alternate version of dvmResolveStaticField().
1877  *
1878  * Does not force initialization of the resolved field's class.
1879  *
1880  * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
1881  */
1882 StaticField* dvmOptResolveStaticField(ClassObject* referrer, u4 sfieldIdx,
1883     VerifyError* pFailure)
1884 {
1885     DvmDex* pDvmDex = referrer->pDvmDex;
1886     StaticField* resField;
1887
1888     resField = (StaticField*)dvmDexGetResolvedField(pDvmDex, sfieldIdx);
1889     if (resField == NULL) {
1890         const DexFieldId* pFieldId;
1891         ClassObject* resClass;
1892
1893         pFieldId = dexGetFieldId(pDvmDex->pDexFile, sfieldIdx);
1894
1895         /*
1896          * Find the field's class.
1897          */
1898         resClass = dvmOptResolveClass(referrer, pFieldId->classIdx, pFailure);
1899         if (resClass == NULL) {
1900             //dvmClearOptException(dvmThreadSelf());
1901             assert(!dvmCheckException(dvmThreadSelf()));
1902             if (pFailure != NULL) { assert(!VERIFY_OK(*pFailure)); }
1903             return NULL;
1904         }
1905
1906         resField = (StaticField*)dvmFindFieldHier(resClass,
1907                     dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx),
1908                     dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx));
1909         if (resField == NULL) {
1910             LOGD("DexOpt: couldn't find static field\n");
1911             if (pFailure != NULL)
1912                 *pFailure = VERIFY_ERROR_NO_FIELD;
1913             return NULL;
1914         }
1915         if (!dvmIsStaticField(&resField->field)) {
1916             LOGD("DexOpt: wanted static, got instance for field %s.%s\n",
1917                 resClass->descriptor,
1918                 dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
1919             if (pFailure != NULL)
1920                 *pFailure = VERIFY_ERROR_CLASS_CHANGE;
1921             return NULL;
1922         }
1923
1924         /*
1925          * Add it to the resolved table so we're faster on the next lookup.
1926          *
1927          * We can only do this if we're in "dexopt", because the presence
1928          * of a valid value in the resolution table implies that the class
1929          * containing the static field has been initialized.
1930          */
1931         if (gDvm.optimizing)
1932             dvmDexSetResolvedField(pDvmDex, sfieldIdx, (Field*) resField);
1933     }
1934
1935     /* access allowed? */
1936     tweakLoader(referrer, resField->field.clazz);
1937     bool allowed = dvmCheckFieldAccess(referrer, (Field*)resField);
1938     untweakLoader(referrer, resField->field.clazz);
1939     if (!allowed) {
1940         LOGI("DexOpt: access denied from %s to field %s.%s\n",
1941             referrer->descriptor, resField->field.clazz->descriptor,
1942             resField->field.name);
1943         if (pFailure != NULL)
1944             *pFailure = VERIFY_ERROR_ACCESS_FIELD;
1945         return NULL;
1946     }
1947
1948     return resField;
1949 }
1950
1951
1952 /*
1953  * Rewrite an iget/iput instruction.  These all have the form:
1954  *   op vA, vB, field@CCCC
1955  *
1956  * Where vA holds the value, vB holds the object reference, and CCCC is
1957  * the field reference constant pool offset.  We want to replace CCCC
1958  * with the byte offset from the start of the object.
1959  *
1960  * "clazz" is the referring class.  We need this because we verify
1961  * access rights here.
1962  */
1963 static void rewriteInstField(Method* method, u2* insns, OpCode newOpc)
1964 {
1965     ClassObject* clazz = method->clazz;
1966     u2 fieldIdx = insns[1];
1967     InstField* field;
1968     int byteOffset;
1969
1970     field = dvmOptResolveInstField(clazz, fieldIdx, NULL);
1971     if (field == NULL) {
1972         LOGI("DexOpt: unable to optimize field ref 0x%04x at 0x%02x in %s.%s\n",
1973             fieldIdx, (int) (insns - method->insns), clazz->descriptor,
1974             method->name);
1975         return;
1976     }
1977
1978     if (field->byteOffset >= 65536) {
1979         LOGI("DexOpt: field offset exceeds 64K (%d)\n", field->byteOffset);
1980         return;
1981     }
1982
1983     insns[0] = (insns[0] & 0xff00) | (u2) newOpc;
1984     insns[1] = (u2) field->byteOffset;
1985     LOGVV("DexOpt: rewrote access to %s.%s --> %d\n",
1986         field->field.clazz->descriptor, field->field.name,
1987         field->byteOffset);
1988 }
1989
1990 /*
1991  * Alternate version of dvmResolveMethod().
1992  *
1993  * Doesn't throw exceptions, and checks access on every lookup.
1994  *
1995  * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
1996  */
1997 Method* dvmOptResolveMethod(ClassObject* referrer, u4 methodIdx,
1998     MethodType methodType, VerifyError* pFailure)
1999 {
2000     DvmDex* pDvmDex = referrer->pDvmDex;
2001     Method* resMethod;
2002
2003     assert(methodType == METHOD_DIRECT ||
2004            methodType == METHOD_VIRTUAL ||
2005            methodType == METHOD_STATIC);
2006
2007     LOGVV("--- resolving method %u (referrer=%s)\n", methodIdx,
2008         referrer->descriptor);
2009
2010     resMethod = dvmDexGetResolvedMethod(pDvmDex, methodIdx);
2011     if (resMethod == NULL) {
2012         const DexMethodId* pMethodId;
2013         ClassObject* resClass;
2014
2015         pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx);
2016
2017         resClass = dvmOptResolveClass(referrer, pMethodId->classIdx, pFailure);
2018         if (resClass == NULL) {
2019             /*
2020              * Can't find the class that the method is a part of, or don't
2021              * have permission to access the class.
2022              */
2023             LOGV("DexOpt: can't find called method's class (?.%s)\n",
2024                 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx));
2025             if (pFailure != NULL) { assert(!VERIFY_OK(*pFailure)); }
2026             return NULL;
2027         }
2028         if (dvmIsInterfaceClass(resClass)) {
2029             /* method is part of an interface; this is wrong method for that */
2030             LOGW("DexOpt: method is in an interface\n");
2031             if (pFailure != NULL)
2032                 *pFailure = VERIFY_ERROR_GENERIC;
2033             return NULL;
2034         }
2035
2036         /*
2037          * We need to chase up the class hierarchy to find methods defined
2038          * in super-classes.  (We only want to check the current class
2039          * if we're looking for a constructor.)
2040          */
2041         DexProto proto;
2042         dexProtoSetFromMethodId(&proto, pDvmDex->pDexFile, pMethodId);
2043
2044         if (methodType == METHOD_DIRECT) {
2045             resMethod = dvmFindDirectMethod(resClass,
2046                 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx), &proto);
2047         } else {
2048             /* METHOD_STATIC or METHOD_VIRTUAL */
2049             resMethod = dvmFindMethodHier(resClass,
2050                 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx), &proto);
2051         }
2052
2053         if (resMethod == NULL) {
2054             LOGV("DexOpt: couldn't find method '%s'\n",
2055                 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx));
2056             if (pFailure != NULL)
2057                 *pFailure = VERIFY_ERROR_NO_METHOD;
2058             return NULL;
2059         }
2060         if (methodType == METHOD_STATIC) {
2061             if (!dvmIsStaticMethod(resMethod)) {
2062                 LOGD("DexOpt: wanted static, got instance for method %s.%s\n",
2063                     resClass->descriptor, resMethod->name);
2064                 if (pFailure != NULL)
2065                     *pFailure = VERIFY_ERROR_CLASS_CHANGE;
2066                 return NULL;
2067             }
2068         } else if (methodType == METHOD_VIRTUAL) {
2069             if (dvmIsStaticMethod(resMethod)) {
2070                 LOGD("DexOpt: wanted instance, got static for method %s.%s\n",
2071                     resClass->descriptor, resMethod->name);
2072                 if (pFailure != NULL)
2073                     *pFailure = VERIFY_ERROR_CLASS_CHANGE;
2074                 return NULL;
2075             }
2076         }
2077
2078         /* see if this is a pure-abstract method */
2079         if (dvmIsAbstractMethod(resMethod) && !dvmIsAbstractClass(resClass)) {
2080             LOGW("DexOpt: pure-abstract method '%s' in %s\n",
2081                 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx),
2082                 resClass->descriptor);
2083             if (pFailure != NULL)
2084                 *pFailure = VERIFY_ERROR_GENERIC;
2085             return NULL;
2086         }
2087
2088         /*
2089          * Add it to the resolved table so we're faster on the next lookup.
2090          *
2091          * We can only do this for static methods if we're not in "dexopt",
2092          * because the presence of a valid value in the resolution table
2093          * implies that the class containing the static field has been
2094          * initialized.
2095          */
2096         if (methodType != METHOD_STATIC || gDvm.optimizing)
2097             dvmDexSetResolvedMethod(pDvmDex, methodIdx, resMethod);
2098     }
2099
2100     LOGVV("--- found method %d (%s.%s)\n",
2101         methodIdx, resMethod->clazz->descriptor, resMethod->name);
2102
2103     /* access allowed? */
2104     tweakLoader(referrer, resMethod->clazz);
2105     bool allowed = dvmCheckMethodAccess(referrer, resMethod);
2106     untweakLoader(referrer, resMethod->clazz);
2107     if (!allowed) {
2108         IF_LOGI() {
2109             char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype);
2110             LOGI("DexOpt: illegal method access (call %s.%s %s from %s)\n",
2111                 resMethod->clazz->descriptor, resMethod->name, desc,
2112                 referrer->descriptor);
2113             free(desc);
2114         }
2115         if (pFailure != NULL)
2116             *pFailure = VERIFY_ERROR_ACCESS_METHOD;
2117         return NULL;
2118     }
2119
2120     return resMethod;
2121 }
2122
2123 /*
2124  * Rewrite invoke-virtual, invoke-virtual/range, invoke-super, and
2125  * invoke-super/range.  These all have the form:
2126  *   op vAA, meth@BBBB, reg stuff @CCCC
2127  *
2128  * We want to replace the method constant pool index BBBB with the
2129  * vtable index.
2130  */
2131 static bool rewriteVirtualInvoke(Method* method, u2* insns, OpCode newOpc)
2132 {
2133     ClassObject* clazz = method->clazz;
2134     Method* baseMethod;
2135     u2 methodIdx = insns[1];
2136
2137     baseMethod = dvmOptResolveMethod(clazz, methodIdx, METHOD_VIRTUAL, NULL);
2138     if (baseMethod == NULL) {
2139         LOGD("DexOpt: unable to optimize virt call 0x%04x at 0x%02x in %s.%s\n",
2140             methodIdx,
2141             (int) (insns - method->insns), clazz->descriptor,
2142             method->name);
2143         return false;
2144     }
2145
2146     assert((insns[0] & 0xff) == OP_INVOKE_VIRTUAL ||
2147            (insns[0] & 0xff) == OP_INVOKE_VIRTUAL_RANGE ||
2148            (insns[0] & 0xff) == OP_INVOKE_SUPER ||
2149            (insns[0] & 0xff) == OP_INVOKE_SUPER_RANGE);
2150
2151     /*
2152      * Note: Method->methodIndex is a u2 and is range checked during the
2153      * initial load.
2154      */
2155     insns[0] = (insns[0] & 0xff00) | (u2) newOpc;
2156     insns[1] = baseMethod->methodIndex;
2157
2158     //LOGI("DexOpt: rewrote call to %s.%s --> %s.%s\n",
2159     //    method->clazz->descriptor, method->name,
2160     //    baseMethod->clazz->descriptor, baseMethod->name);
2161
2162     return true;
2163 }
2164
2165 /*
2166  * Rewrite invoke-direct, which has the form:
2167  *   op vAA, meth@BBBB, reg stuff @CCCC
2168  *
2169  * There isn't a lot we can do to make this faster, but in some situations
2170  * we can make it go away entirely.
2171  *
2172  * This must only be used when the invoked method does nothing and has
2173  * no return value (the latter being very important for verification).
2174  */
2175 static bool rewriteEmptyDirectInvoke(Method* method, u2* insns)
2176 {
2177     ClassObject* clazz = method->clazz;
2178     Method* calledMethod;
2179     u2 methodIdx = insns[1];
2180
2181     calledMethod = dvmOptResolveMethod(clazz, methodIdx, METHOD_DIRECT, NULL);
2182     if (calledMethod == NULL) {
2183         LOGD("DexOpt: unable to opt direct call 0x%04x at 0x%02x in %s.%s\n",
2184             methodIdx,
2185             (int) (insns - method->insns), clazz->descriptor,
2186             method->name);
2187         return false;
2188     }
2189
2190     /* TODO: verify that java.lang.Object() is actually empty! */
2191     if (calledMethod->clazz == gDvm.classJavaLangObject &&
2192         dvmCompareNameDescriptorAndMethod("<init>", "()V", calledMethod) == 0)
2193     {
2194         /*
2195          * Replace with "empty" instruction.  DO NOT disturb anything
2196          * else about it, as we want it to function the same as
2197          * OP_INVOKE_DIRECT when debugging is enabled.
2198          */
2199         assert((insns[0] & 0xff) == OP_INVOKE_DIRECT);
2200         insns[0] = (insns[0] & 0xff00) | (u2) OP_INVOKE_DIRECT_EMPTY;
2201
2202         //LOGI("DexOpt: marked-empty call to %s.%s --> %s.%s\n",
2203         //    method->clazz->descriptor, method->name,
2204         //    calledMethod->clazz->descriptor, calledMethod->name);
2205     }
2206
2207     return true;
2208 }
2209
2210 /*
2211  * Resolve an interface method reference.
2212  *
2213  * No method access check here -- interface methods are always public.
2214  *
2215  * Returns NULL if the method was not found.  Does not throw an exception.
2216  */
2217 Method* dvmOptResolveInterfaceMethod(ClassObject* referrer, u4 methodIdx)
2218 {
2219     DvmDex* pDvmDex = referrer->pDvmDex;
2220     Method* resMethod;
2221     int i;
2222
2223     LOGVV("--- resolving interface method %d (referrer=%s)\n",
2224         methodIdx, referrer->descriptor);
2225
2226     resMethod = dvmDexGetResolvedMethod(pDvmDex, methodIdx);
2227     if (resMethod == NULL) {
2228         const DexMethodId* pMethodId;
2229         ClassObject* resClass;
2230
2231         pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx);
2232
2233         resClass = dvmOptResolveClass(referrer, pMethodId->classIdx, NULL);
2234         if (resClass == NULL) {
2235             /* can't find the class that the method is a part of */
2236             dvmClearOptException(dvmThreadSelf());
2237             return NULL;
2238         }
2239         if (!dvmIsInterfaceClass(resClass)) {
2240             /* whoops */
2241             LOGI("Interface method not part of interface class\n");
2242             return NULL;
2243         }
2244
2245         const char* methodName =
2246             dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
2247         DexProto proto;
2248         dexProtoSetFromMethodId(&proto, pDvmDex->pDexFile, pMethodId);
2249
2250         LOGVV("+++ looking for '%s' '%s' in resClass='%s'\n",
2251             methodName, methodSig, resClass->descriptor);
2252         resMethod = dvmFindVirtualMethod(resClass, methodName, &proto);
2253         if (resMethod == NULL) {
2254             /* scan superinterfaces and superclass interfaces */
2255             LOGVV("+++ did not resolve immediately\n");
2256             for (i = 0; i < resClass->iftableCount; i++) {
2257                 resMethod = dvmFindVirtualMethod(resClass->iftable[i].clazz,
2258                                 methodName, &proto);
2259                 if (resMethod != NULL)
2260                     break;
2261             }
2262
2263             if (resMethod == NULL) {
2264                 LOGVV("+++ unable to resolve method %s\n", methodName);
2265                 return NULL;
2266             }
2267         } else {
2268             LOGVV("+++ resolved immediately: %s (%s %d)\n", resMethod->name,
2269                 resMethod->clazz->descriptor, (u4) resMethod->methodIndex);
2270         }
2271
2272         /* we're expecting this to be abstract */
2273         if (!dvmIsAbstractMethod(resMethod)) {
2274             char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype);
2275             LOGW("Found non-abstract interface method %s.%s %s\n",
2276                 resMethod->clazz->descriptor, resMethod->name, desc);
2277             free(desc);
2278             return NULL;
2279         }
2280
2281         /*
2282          * Add it to the resolved table so we're faster on the next lookup.
2283          */
2284         dvmDexSetResolvedMethod(pDvmDex, methodIdx, resMethod);
2285     }
2286
2287     LOGVV("--- found interface method %d (%s.%s)\n",
2288         methodIdx, resMethod->clazz->descriptor, resMethod->name);
2289
2290     /* interface methods are always public; no need to check access */
2291
2292     return resMethod;
2293 }
2294
2295 /*
2296  * See if the method being called can be rewritten as an inline operation.
2297  * Works for invoke-virtual, invoke-direct, and invoke-static.
2298  *
2299  * Returns "true" if we replace it.
2300  */
2301 static bool rewriteExecuteInline(Method* method, u2* insns,
2302     MethodType methodType, const InlineSub* inlineSubs)
2303 {
2304     ClassObject* clazz = method->clazz;
2305     Method* calledMethod;
2306     u2 methodIdx = insns[1];
2307
2308     //return false;
2309
2310     calledMethod = dvmOptResolveMethod(clazz, methodIdx, methodType, NULL);
2311     if (calledMethod == NULL) {
2312         LOGV("+++ DexOpt inline: can't find %d\n", methodIdx);
2313         return false;
2314     }
2315
2316     while (inlineSubs->method != NULL) {
2317         /*
2318         if (extra) {
2319             LOGI("comparing %p vs %p %s.%s %s\n",
2320                 inlineSubs->method, calledMethod,
2321                 inlineSubs->method->clazz->descriptor,
2322                 inlineSubs->method->name,
2323                 inlineSubs->method->signature);
2324         }
2325         */
2326         if (inlineSubs->method == calledMethod) {
2327             assert((insns[0] & 0xff) == OP_INVOKE_DIRECT ||
2328                    (insns[0] & 0xff) == OP_INVOKE_STATIC ||
2329                    (insns[0] & 0xff) == OP_INVOKE_VIRTUAL);
2330             insns[0] = (insns[0] & 0xff00) | (u2) OP_EXECUTE_INLINE;
2331             insns[1] = (u2) inlineSubs->inlineIdx;
2332
2333             //LOGI("DexOpt: execute-inline %s.%s --> %s.%s\n",
2334             //    method->clazz->descriptor, method->name,
2335             //    calledMethod->clazz->descriptor, calledMethod->name);
2336             return true;
2337         }
2338
2339         inlineSubs++;
2340     }
2341
2342     return false;
2343 }
2344
2345 /*
2346  * See if the method being called can be rewritten as an inline operation.
2347  * Works for invoke-virtual/range, invoke-direct/range, and invoke-static/range.
2348  *
2349  * Returns "true" if we replace it.
2350  */
2351 static bool rewriteExecuteInlineRange(Method* method, u2* insns,
2352     MethodType methodType, const InlineSub* inlineSubs)
2353 {
2354     ClassObject* clazz = method->clazz;
2355     Method* calledMethod;
2356     u2 methodIdx = insns[1];
2357
2358     calledMethod = dvmOptResolveMethod(clazz, methodIdx, methodType, NULL);
2359     if (calledMethod == NULL) {
2360         LOGV("+++ DexOpt inline/range: can't find %d\n", methodIdx);
2361         return false;
2362     }
2363
2364     while (inlineSubs->method != NULL) {
2365         if (inlineSubs->method == calledMethod) {
2366             assert((insns[0] & 0xff) == OP_INVOKE_DIRECT_RANGE ||
2367                    (insns[0] & 0xff) == OP_INVOKE_STATIC_RANGE ||
2368                    (insns[0] & 0xff) == OP_INVOKE_VIRTUAL_RANGE);
2369             insns[0] = (insns[0] & 0xff00) | (u2) OP_EXECUTE_INLINE_RANGE;
2370             insns[1] = (u2) inlineSubs->inlineIdx;
2371
2372             //LOGI("DexOpt: execute-inline/range %s.%s --> %s.%s\n",
2373             //    method->clazz->descriptor, method->name,
2374             //    calledMethod->clazz->descriptor, calledMethod->name);
2375             return true;
2376         }
2377
2378         inlineSubs++;
2379     }
2380
2381     return false;
2382 }
2383