Merge "Better handling of various types of compilation in DexOptimizer" into nyc-dev

am: 0c9ef61944

* commit '0c9ef61944e883219dd167f765a504ab8cdb7710':
  Better handling of various types of compilation in DexOptimizer
This commit is contained in:
Calin Juravle
2016-03-03 10:58:44 +00:00
committed by android-build-merger
5 changed files with 50 additions and 94 deletions

View File

@@ -4690,9 +4690,6 @@ public class PackageParser {
// preferred up order.
public int mPreferredOrder = 0;
// For use by package manager to keep track of where it needs to do dexopt.
public final ArraySet<String> mDexOptPerformed = new ArraySet<>(4);
// For use by package manager to keep track of when a package was last used.
public long mLastPackageUsageTimeInMills;

View File

@@ -499,11 +499,11 @@ public class ZygoteInit {
try {
for (String classPathElement : classPathElements) {
// System server is fully AOTed and never profiled
// for profile guided compilation.
final int dexoptNeeded = DexFile.getDexOptNeeded(
classPathElement, "*", instructionSet, false /* defer */);
classPathElement, instructionSet, DexFile.COMPILATION_TYPE_FULL);
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
// System server is fully AOTed and never profiled
// for profile guided compilation.
installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet,
dexoptNeeded, 0 /*dexFlags*/, null /*volumeUuid*/,
false /*useProfiles*/);

View File

@@ -180,10 +180,5 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
return dexoptFlags | DEXOPT_OTA;
}
@Override
protected void recordSuccessfulDexopt(Package pkg, String instructionSet) {
// Never record the dexopt, as it's in the B partition.
}
}
}

View File

@@ -112,15 +112,6 @@ class PackageDexOptimizer {
}
}
/**
* Determine whether the package should be skipped for the given instruction set. A return
* value of true means the package will be skipped. A return value of false means that the
* package will be further investigated, and potentially compiled.
*/
protected boolean shouldSkipBasedOnISA(PackageParser.Package pkg, String instructionSet) {
return pkg.mDexOptPerformed.contains(instructionSet);
}
/**
* Adjust the given dexopt-needed value. Can be overridden to influence the decision to
* optimize or not (and in what way).
@@ -136,13 +127,6 @@ class PackageDexOptimizer {
return dexoptFlags;
}
/**
* Update the package status after a successful compilation.
*/
protected void recordSuccessfulDexopt(PackageParser.Package pkg, String instructionSet) {
pkg.mDexOptPerformed.add(instructionSet);
}
private int performDexOptLI(PackageParser.Package pkg, String[] targetInstructionSets,
boolean useProfiles, boolean extractOnly) {
final String[] instructionSets = targetInstructionSets != null ?
@@ -159,11 +143,6 @@ class PackageDexOptimizer {
boolean performedDexOpt = false;
final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
for (String dexCodeInstructionSet : dexCodeInstructionSets) {
if (!useProfiles && shouldSkipBasedOnISA(pkg, dexCodeInstructionSet)) {
// Skip only if we do not use profiles since they might trigger a recompilation.
continue;
}
for (String path : paths) {
if (useProfiles && isUsedByOtherApps(path)) {
// We cannot use profile guided compilation if the apk was used by another app.
@@ -172,35 +151,44 @@ class PackageDexOptimizer {
int dexoptNeeded;
try {
dexoptNeeded = DexFile.getDexOptNeeded(path, pkg.packageName,
dexCodeInstructionSet, /* defer */false);
int compilationTypeMask = 0;
if (extractOnly) {
// For extract only, any type of compilation is good.
compilationTypeMask = DexFile.COMPILATION_TYPE_FULL
| DexFile.COMPILATION_TYPE_PROFILE_GUIDE
| DexFile.COMPILATION_TYPE_EXTRACT_ONLY;
} else {
// Branch taken for profile guide and full compilation.
// Profile guide compilation should only recompile a previous
// profile compiled/extract only file and should not be attempted if the
// apk is already fully compiled. So test against a full compilation type.
compilationTypeMask = DexFile.COMPILATION_TYPE_FULL;
}
dexoptNeeded = DexFile.getDexOptNeeded(path,
dexCodeInstructionSet, compilationTypeMask);
} catch (IOException ioe) {
Slog.w(TAG, "IOException reading apk: " + path, ioe);
return DEX_OPT_FAILED;
}
dexoptNeeded = adjustDexoptNeeded(dexoptNeeded);
if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) {
if (useProfiles) {
// Profiles may trigger re-compilation. The final decision is taken in
// installd.
dexoptNeeded = DexFile.DEX2OAT_NEEDED;
} else {
// No dexopt needed and we don't use profiles. Nothing to do.
continue;
}
}
final String dexoptType;
String oatDir = null;
if (dexoptNeeded == DexFile.DEX2OAT_NEEDED) {
dexoptType = "dex2oat";
oatDir = createOatDirIfSupported(pkg, dexCodeInstructionSet);
} else if (dexoptNeeded == DexFile.PATCHOAT_NEEDED) {
dexoptType = "patchoat";
} else if (dexoptNeeded == DexFile.SELF_PATCHOAT_NEEDED) {
dexoptType = "self patchoat";
} else {
throw new IllegalStateException("Invalid dexopt needed: " + dexoptNeeded);
switch (dexoptNeeded) {
case DexFile.NO_DEXOPT_NEEDED:
continue;
case DexFile.DEX2OAT_NEEDED:
dexoptType = "dex2oat";
oatDir = createOatDirIfSupported(pkg, dexCodeInstructionSet);
break;
case DexFile.PATCHOAT_NEEDED:
dexoptType = "patchoat";
break;
case DexFile.SELF_PATCHOAT_NEEDED:
dexoptType = "self patchoat";
break;
default:
throw new IllegalStateException("Invalid dexopt:" + dexoptNeeded);
}
@@ -226,15 +214,6 @@ class PackageDexOptimizer {
Slog.w(TAG, "Failed to dexopt", e);
}
}
if (!extractOnly) {
// At this point we haven't failed dexopt and we haven't deferred dexopt. We must
// either have either succeeded dexopt, or have had getDexOptNeeded tell us
// it isn't required. We therefore mark that this package doesn't need dexopt unless
// it's forced. performedDexOpt will tell us whether we performed dex-opt or skipped
// it.
recordSuccessfulDexopt(pkg, dexCodeInstructionSet);
}
}
// If we've gotten here, we're sure that no error occurred and that we haven't
@@ -316,12 +295,6 @@ class PackageDexOptimizer {
super(from);
}
@Override
protected boolean shouldSkipBasedOnISA(Package pkg, String instructionSet) {
// Forced compilation, never skip.
return false;
}
@Override
protected int adjustDexoptNeeded(int dexoptNeeded) {
// Ensure compilation, no matter the current state.

View File

@@ -639,9 +639,6 @@ public class PackageManagerService extends IPackageManager.Stub {
// List of packages names to keep cached, even if they are uninstalled for all users
private List<String> mKeepUninstalledPackages;
private boolean mUseJitProfiles =
SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
private static class IFVerificationParams {
PackageParser.Package pkg;
boolean replacing;
@@ -2161,10 +2158,12 @@ public class PackageManagerService extends IPackageManager.Stub {
}
try {
int dexoptNeeded = DexFile.getDexOptNeeded(lib, null, dexCodeInstructionSet, false);
// Shared libraries do not have profiles so we perform a full
// AOT compilation (if needed).
int dexoptNeeded = DexFile.getDexOptNeeded(
lib, dexCodeInstructionSet,
DexFile.COMPILATION_TYPE_FULL);
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
// Shared libraries do not have profiles so we perform a full
// AOT compilation.
mInstaller.dexopt(lib, Process.SYSTEM_UID, dexCodeInstructionSet,
dexoptNeeded, DEXOPT_PUBLIC /*dexFlags*/,
StorageManager.UUID_PRIVATE_INTERNAL,
@@ -6838,7 +6837,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Extract pacakges only if profile-guided compilation is enabled because
// otherwise BackgroundDexOptService will not dexopt them later.
if (!mUseJitProfiles || !isUpgrade()) {
if (!isUpgrade()) {
return;
}
@@ -6920,10 +6919,6 @@ public class PackageManagerService extends IPackageManager.Stub {
targetInstructionSet = instructionSet != null ? instructionSet :
getPrimaryInstructionSet(p.applicationInfo);
if (!force && !useProfiles && p.mDexOptPerformed.contains(targetInstructionSet)) {
// Skip only if we do not use profiles since they might trigger a recompilation.
return false;
}
}
long callingId = Binder.clearCallingIdentity();
try {
@@ -13853,21 +13848,17 @@ public class PackageManagerService extends IPackageManager.Stub {
return;
}
// Extract package to save the VM unzipping the APK in memory during
// launch. Only do this if profile-guided compilation is enabled because
// otherwise BackgroundDexOptService will not dexopt the package later.
if (mUseJitProfiles) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
// Do not run PackageDexOptimizer through the local performDexOpt
// method because `pkg` is not in `mPackages` yet.
int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instructionSets */,
false /* useProfiles */, true /* extractOnly */);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
String msg = "Extracking package failed for " + pkgName;
res.setError(INSTALL_FAILED_DEXOPT, msg);
return;
}
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
// Do not run PackageDexOptimizer through the local performDexOpt
// method because `pkg` is not in `mPackages` yet.
int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instructionSets */,
false /* useProfiles */, true /* extractOnly */);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
String msg = "Extracking package failed for " + pkgName;
res.setError(INSTALL_FAILED_DEXOPT, msg);
return;
}
}