diff options
author | Dan Bornstein <danfuzz@android.com> | 2010-09-12 16:42:28 -0700 |
---|---|---|
committer | Dan Bornstein <danfuzz@android.com> | 2010-09-12 17:20:07 -0700 |
commit | 4701d5f8d0e691eeb9a0824311d5166d301a5aa5 (patch) | |
tree | 053bde789439b3c296b8126f563a738b9189ff20 /dexopt | |
parent | ab9d89fb7417157c3972278d1bd899cc091a8168 (diff) | |
download | android_dalvik-4701d5f8d0e691eeb9a0824311d5166d301a5aa5.tar.gz android_dalvik-4701d5f8d0e691eeb9a0824311d5166d301a5aa5.tar.bz2 android_dalvik-4701d5f8d0e691eeb9a0824311d5166d301a5aa5.zip |
Add a new "--preopt" mode to dexopt, for running on the host.
This change takes much of what used to be in the function fromZip()
(the "--zip" mode implementation) and pulls it into a helper function,
which is then also used by the new preopt() function.
Change-Id: Id54618047896366448adaec0bf973627a9f1f397
Diffstat (limited to 'dexopt')
-rw-r--r-- | dexopt/OptMain.c | 174 |
1 files changed, 130 insertions, 44 deletions
diff --git a/dexopt/OptMain.c b/dexopt/OptMain.c index 8dffcf521..276db82c8 100644 --- a/dexopt/OptMain.c +++ b/dexopt/OptMain.c @@ -17,7 +17,7 @@ /* * Command-line DEX optimization and verification entry point. * - * There are two ways to launch this: + * There are three ways to launch this: * (1) From the VM. This takes a dozen args, one of which is a file * descriptor that acts as both input and output. This allows us to * remain ignorant of where the DEX data originally came from. @@ -26,6 +26,9 @@ * a filename for debug messages. Many assumptions are made about * what's going on (verification + optimization are enabled, boot * class path is in BOOTCLASSPATH, etc). + * (3) On the host during a build for preoptimization. This behaves + * almost the same as (2), except it takes file names instead of + * file descriptors. * * There are some fragile aspects around bootclasspath entries, owing * largely to the VM's history of working on whenever it thought it needed @@ -38,6 +41,8 @@ #include "utils/Log.h" #include "cutils/process_name.h" +#include <fcntl.h> +#include <stdbool.h> #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -50,7 +55,7 @@ static const char* kClassesDex = "classes.dex"; * up front for the DEX optimization header. */ static int extractAndProcessZip(int zipFd, int cacheFd, - const char* debugFileName, int isBootstrap, const char* bootClassPath, + const char* debugFileName, bool isBootstrap, const char* bootClassPath, const char* dexoptFlagStr) { ZipArchive zippy; @@ -181,6 +186,60 @@ bail: return result; } +/* + * Common functionality for normal device-side processing as well as + * preoptimization. + */ +static int processZipFile(int zipFd, int cacheFd, const char* zipName, + const char *dexoptFlags) +{ + int result = -1; + char* bcpCopy = NULL; + + /* + * Check to see if this is a bootstrap class entry. If so, truncate + * the path. + */ + const char* bcp = getenv("BOOTCLASSPATH"); + if (bcp == NULL) { + LOGE("DexOptZ: BOOTCLASSPATH not set\n"); + goto bail; + } + + bool isBootstrap = false; + const char* match = strstr(bcp, zipName); + if (match != NULL) { + /* + * TODO: we have a partial string match, but that doesn't mean + * we've matched an entire path component. We should make sure + * that we're matching on the full zipName, and if not we + * should re-do the strstr starting at (match+1). + * + * The scenario would be a bootclasspath with something like + * "/system/framework/core.jar" while we're trying to optimize + * "/framework/core.jar". Not very likely since all paths are + * absolute and end with ".jar", but not impossible. + */ + int matchOffset = match - bcp; + if (matchOffset > 0 && bcp[matchOffset-1] == ':') + matchOffset--; + LOGV("DexOptZ: found '%s' in bootclasspath, cutting off at %d\n", + inputFileName, matchOffset); + bcpCopy = strdup(bcp); + bcpCopy[matchOffset] = '\0'; + + bcp = bcpCopy; + LOGD("DexOptZ: truncated BOOTCLASSPATH to '%s'\n", bcp); + isBootstrap = true; + } + + result = extractAndProcessZip(zipFd, cacheFd, zipName, isBootstrap, + bcp, dexoptFlags); + +bail: + free(bcpCopy); + return result; +} /* advance to the next arg and extract it */ #define GET_ARG(_var, _func, _msg) \ @@ -200,8 +259,8 @@ bail: * 1. "--zip" * 2. zip fd (input, read-only) * 3. cache fd (output, read-write, locked with flock) - * 4. filename of file being optimized (used for debug messages and - * for comparing against BOOTCLASSPATH -- does not need to be + * 4. filename of zipfile being optimized (used for debug messages and + * for comparing against BOOTCLASSPATH; does not need to be * accessible or even exist) * 5. dexopt flags * @@ -216,10 +275,10 @@ bail: static int fromZip(int argc, char* const argv[]) { int result = -1; - int zipFd, cacheFd, vmBuildVersion; - const char* inputFileName; + int zipFd, cacheFd; + const char* zipName; char* bcpCopy = NULL; - const char* dexoptFlagStr; + const char* dexoptFlags; if (argc != 6) { LOGE("Wrong number of args for --zip (found %d)\n", argc); @@ -232,53 +291,73 @@ static int fromZip(int argc, char* const argv[]) GET_ARG(zipFd, strtol, "bad zip fd"); GET_ARG(cacheFd, strtol, "bad cache fd"); - inputFileName = *++argv; + zipName = *++argv; --argc; - dexoptFlagStr = *++argv; + dexoptFlags = *++argv; --argc; - /* - * Check to see if this is a bootstrap class entry. If so, truncate - * the path. - */ - const char* bcp = getenv("BOOTCLASSPATH"); - if (bcp == NULL) { - LOGE("DexOptZ: BOOTCLASSPATH not set\n"); + result = processZipFile(zipFd, cacheFd, zipName, dexoptFlags); + +bail: + return result; +} + +/* + * Parse arguments for a preoptimization run. This is when dalvikvm is run + * on a host to optimize dex files for eventual running on a (different) + * device. We want: + * 0. (name of dexopt command -- ignored) + * 1. "--preopt" + * 2. zipfile name + * 3. output file name + * 4. dexopt flags + * + * The BOOTCLASSPATH environment variable is assumed to hold the correct + * boot class path. If the filename provided appears in the boot class + * path, the path will be truncated just before that entry (so that, if + * you were to dexopt "core.jar", your bootclasspath would be empty). + * + * This does not try to normalize the boot class path name, so the + * filename test won't catch you if you get creative. + */ +static int preopt(int argc, char* const argv[]) +{ + if (argc != 5) { + LOGE("Wrong number of args for --preopt (found %d)\n", argc); goto bail; } - int isBootstrap = false; - const char* match = strstr(bcp, inputFileName); - if (match != NULL) { - /* - * TODO: we have a partial string match, but that doesn't mean - * we've matched an entire path component. We should make sure - * that we're matching on the full inputFileName, and if not we - * should re-do the strstr starting at (match+1). - * - * The scenario would be a bootclasspath with something like - * "/system/framework/core.jar" while we're trying to optimize - * "/framework/core.jar". Not very likely since all paths are - * absolute and end with ".jar", but not impossible. - */ - int matchOffset = match - bcp; - if (matchOffset > 0 && bcp[matchOffset-1] == ':') - matchOffset--; - LOGV("DexOptZ: found '%s' in bootclasspath, cutting off at %d\n", - inputFileName, matchOffset); - bcpCopy = strdup(bcp); - bcpCopy[matchOffset] = '\0'; + const char* zipName = argv[2]; + const char* outName = argv[3]; + const char* dexoptFlags = argv[4]; - bcp = bcpCopy; - LOGD("DexOptZ: truncated BOOTCLASSPATH to '%s'\n", bcp); - isBootstrap = true; + int zipFd = -1; + int outFd = -1; + int result = -1; + + zipFd = open(zipName, O_RDONLY); + if (zipFd < 0) { + perror(argv[0]); + goto bail; + } + + outFd = open(outName, O_WRONLY | O_EXCL | O_CREAT); + if (outFd < 0) { + perror(argv[0]); + goto bail; } - result = extractAndProcessZip(zipFd, cacheFd, inputFileName, - isBootstrap, bcp, dexoptFlagStr); + result = processZipFile(zipFd, outFd, zipName, dexoptFlags); bail: - free(bcpCopy); + if (zipFd >= 0) { + close(zipFd); + } + + if (outFd >= 0) { + close(outFd); + } + return result; } @@ -480,8 +559,15 @@ int main(int argc, char* const argv[]) return fromZip(argc, argv); else if (strcmp(argv[1], "--dex") == 0) return fromDex(argc, argv); + else if (strcmp(argv[1], "--preopt") == 0) + return preopt(argc, argv); } - fprintf(stderr, "Usage: don't use this\n"); + fprintf(stderr, + "Usage:\n\n" + "Short version: Don't use this.\n\n" + "Slightly longer version: This system-internal tool is used to\n" + "produce optimized dex files. See the source code for details.\n"); + return 1; } |