case 'n': dexOptMode = OPTIMIZE_MODE_NONE; break;
case 'v': dexOptMode = OPTIMIZE_MODE_VERIFIED; break;
case 'a': dexOptMode = OPTIMIZE_MODE_ALL; break;
+ case 'f': dexOptMode = OPTIMIZE_MODE_FULL; break;
default: break;
}
}
dvmFprintf(stderr, "\n");
dvmFprintf(stderr, "These are unique to Dalvik:\n");
dvmFprintf(stderr, " -Xzygote\n");
- dvmFprintf(stderr, " -Xdexopt:{none,verified,all}\n");
+ dvmFprintf(stderr, " -Xdexopt:{none,verified,all,full}\n");
dvmFprintf(stderr, " -Xnoquithandler\n");
dvmFprintf(stderr,
" -Xjnigreflimit:N (must be multiple of 100, >= 200)\n");
gDvm.dexOptMode = OPTIMIZE_MODE_VERIFIED;
else if (strcmp(argv[i] + 9, "all") == 0)
gDvm.dexOptMode = OPTIMIZE_MODE_ALL;
+ else if (strcmp(argv[i] + 9, "full") == 0)
+ gDvm.dexOptMode = OPTIMIZE_MODE_FULL;
else {
dvmFprintf(stderr, "Unrecognized dexopt option '%s'\n",argv[i]);
return -1;
} else {
bool expectVerify, expectOpt;
- if (gDvm.classVerifyMode == VERIFY_MODE_NONE)
+ if (gDvm.classVerifyMode == VERIFY_MODE_NONE) {
expectVerify = false;
- else if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE)
+ } else if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE) {
expectVerify = !isBootstrap;
- else /*if (gDvm.classVerifyMode == VERIFY_MODE_ALL)*/
+ } else /*if (gDvm.classVerifyMode == VERIFY_MODE_ALL)*/ {
expectVerify = true;
+ }
- if (gDvm.dexOptMode == OPTIMIZE_MODE_NONE)
+ if (gDvm.dexOptMode == OPTIMIZE_MODE_NONE) {
expectOpt = false;
- else if (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED)
+ } else if (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED ||
+ gDvm.dexOptMode == OPTIMIZE_MODE_FULL) {
expectOpt = expectVerify;
- else /*if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)*/
+ } else /*if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)*/ {
expectOpt = true;
+ }
LOGV("checking deps, expecting vfy=%d opt=%d\n",
expectVerify, expectOpt);
*pHeaderFlags |= DEX_OPT_FLAG_BIG;
#endif
- if (gDvm.classVerifyMode == VERIFY_MODE_NONE)
+ if (gDvm.classVerifyMode == VERIFY_MODE_NONE) {
doVerify = false;
- else if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE)
+ } else if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE) {
doVerify = !gDvm.optimizingBootstrapClass;
- else /*if (gDvm.classVerifyMode == VERIFY_MODE_ALL)*/
+ } else /*if (gDvm.classVerifyMode == VERIFY_MODE_ALL)*/ {
doVerify = true;
+ }
- if (gDvm.dexOptMode == OPTIMIZE_MODE_NONE)
+ if (gDvm.dexOptMode == OPTIMIZE_MODE_NONE) {
doOpt = false;
- else if (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED)
+ } else if (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED ||
+ gDvm.dexOptMode == OPTIMIZE_MODE_FULL) {
doOpt = doVerify;
- else /*if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)*/
+ } else /*if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)*/ {
doOpt = true;
+ }
/* TODO: decide if this is actually useful */
if (doVerify)
}
if (doOpt) {
- if (!verified && gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED) {
+ bool needVerify = (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED ||
+ gDvm.dexOptMode == OPTIMIZE_MODE_FULL);
+ if (!verified && needVerify) {
LOGV("DexOpt: not optimizing '%s': not verified\n",
classDescriptor);
} else {
/*
* Global DEX optimizer control. Determines the circumstances in which we
* try to rewrite instructions in the DEX file.
+ *
+ * Optimizing is performed ahead-of-time by dexopt and, in some cases, at
+ * load time by the VM.
*/
typedef enum DexOptimizerMode {
OPTIMIZE_MODE_UNKNOWN = 0,
- OPTIMIZE_MODE_NONE, /* never optimize */
+ OPTIMIZE_MODE_NONE, /* never optimize (except "essential") */
OPTIMIZE_MODE_VERIFIED, /* only optimize verified classes (default) */
- OPTIMIZE_MODE_ALL /* optimize all classes */
+ OPTIMIZE_MODE_ALL, /* optimize verified & unverified (risky) */
+ OPTIMIZE_MODE_FULL /* fully opt verified classes at load time */
} DexOptimizerMode;
/* some additional bit flags for dexopt */
u2* insns;
u2 inst;
- if (!gDvm.optimizing && !essentialOnly) {
- /* unexpected; will force copy-on-write of a lot of pages */
- LOGD("NOTE: doing full bytecode optimization outside dexopt\n");
- }
-
if (dvmIsNativeMethod(method) || dvmIsAbstractMethod(method))
return;
/*
* essential substitutions:
* {iget,iput,sget,sput}-wide --> *-wide-volatile
- * invoke-{virtual,direct,static}[/range] --> execute-inline
* invoke-direct --> invoke-object-init
*
* essential-on-SMP substitutions:
rewriteStaticField(method, insns, volatileOpc);
break;
- case OP_INVOKE_VIRTUAL:
- if (!rewriteExecuteInline(method, insns, METHOD_VIRTUAL)) {
- /* may want to try -quick, below */
- notMatched = true;
- }
- break;
- case OP_INVOKE_VIRTUAL_RANGE:
- if (!rewriteExecuteInlineRange(method, insns, METHOD_VIRTUAL)) {
- /* may want to try -quick, below */
- notMatched = true;
- }
- break;
case OP_INVOKE_DIRECT:
- if (!rewriteExecuteInline(method, insns, METHOD_DIRECT)) {
- rewriteInvokeObjectInit(method, insns);
+ /* TODO: also handle invoke-direct/range */
+ if (!rewriteInvokeObjectInit(method, insns)) {
+ /* may want to try execute-inline, below */
+ notMatched = true;
}
break;
- case OP_INVOKE_DIRECT_RANGE:
- rewriteExecuteInlineRange(method, insns, METHOD_DIRECT);
- break;
- case OP_INVOKE_STATIC:
- rewriteExecuteInline(method, insns, METHOD_STATIC);
- break;
- case OP_INVOKE_STATIC_RANGE:
- rewriteExecuteInlineRange(method, insns, METHOD_STATIC);
- break;
-
default:
notMatched = true;
break;
/*
* non-essential substitutions:
+ * invoke-{virtual,direct,static}[/range] --> execute-inline
* invoke-{virtual,super}[/range] --> invoke-*-quick
*/
if (notMatched && !essentialOnly) {
switch (inst) {
case OP_INVOKE_VIRTUAL:
- rewriteVirtualInvoke(method, insns, OP_INVOKE_VIRTUAL_QUICK);
+ if (!rewriteExecuteInline(method, insns, METHOD_VIRTUAL)) {
+ rewriteVirtualInvoke(method, insns,
+ OP_INVOKE_VIRTUAL_QUICK);
+ }
break;
case OP_INVOKE_VIRTUAL_RANGE:
- rewriteVirtualInvoke(method, insns,
- OP_INVOKE_VIRTUAL_QUICK_RANGE);
+ if (!rewriteExecuteInlineRange(method, insns, METHOD_VIRTUAL)) {
+ rewriteVirtualInvoke(method, insns,
+ OP_INVOKE_VIRTUAL_QUICK_RANGE);
+ }
break;
case OP_INVOKE_SUPER:
rewriteVirtualInvoke(method, insns, OP_INVOKE_SUPER_QUICK);
case OP_INVOKE_SUPER_RANGE:
rewriteVirtualInvoke(method, insns, OP_INVOKE_SUPER_QUICK_RANGE);
break;
-
+ case OP_INVOKE_DIRECT:
+ rewriteExecuteInline(method, insns, METHOD_DIRECT);
+ break;
+ case OP_INVOKE_DIRECT_RANGE:
+ rewriteExecuteInlineRange(method, insns, METHOD_DIRECT);
+ break;
+ case OP_INVOKE_STATIC:
+ rewriteExecuteInline(method, insns, METHOD_STATIC);
+ break;
+ case OP_INVOKE_STATIC_RANGE:
+ rewriteExecuteInlineRange(method, insns, METHOD_STATIC);
+ break;
default:
/* nothing to do for this instruction */
;
if (!IS_CLASS_FLAG_SET(clazz, CLASS_ISOPTIMIZED) && !gDvm.optimizing) {
LOGV("+++ late optimize on %s (pv=%d)\n",
clazz->descriptor, IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED));
- dvmOptimizeClass(clazz, true);
+ bool essentialOnly = (gDvm.dexOptMode != OPTIMIZE_MODE_FULL);
+ dvmOptimizeClass(clazz, essentialOnly);
SET_CLASS_FLAG(clazz, CLASS_ISOPTIMIZED);
}