summaryrefslogtreecommitdiffstats
path: root/dexopt
diff options
context:
space:
mode:
authorDan Bornstein <danfuzz@android.com>2010-09-12 16:42:28 -0700
committerDan Bornstein <danfuzz@android.com>2010-09-12 17:20:07 -0700
commit4701d5f8d0e691eeb9a0824311d5166d301a5aa5 (patch)
tree053bde789439b3c296b8126f563a738b9189ff20 /dexopt
parentab9d89fb7417157c3972278d1bd899cc091a8168 (diff)
downloadandroid_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.c174
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;
}