blob: a66421e76710017c00bfe027be6235e8ebb84d6d [file] [log] [blame]
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.dx.dex.cf;
import com.android.dx.rop.code.RopMethod;
import com.android.dx.rop.code.TranslationAdvice;
import com.android.dx.ssa.Optimizer;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.EnumSet;
import java.util.HashSet;
/**
* Settings for optimization of code.
*/
public class OptimizerOptions {
/**
* {@code null-ok;} hash set of class name + method names that
* should be optimized. {@code null} if this constraint was not
* specified on the command line
*/
private static HashSet<String> optimizeList;
/**
* {@code null-ok;} hash set of class name + method names that should NOT
* be optimized. null if this constraint was not specified on the
* command line
*/
private static HashSet<String> dontOptimizeList;
/** true if the above lists have been loaded */
private static boolean optimizeListsLoaded;
/**
* This class is uninstantiable.
*/
private OptimizerOptions() {
// This space intentionally left blank.
}
/**
* Loads the optimize/don't optimize lists from files.
*
* @param optimizeListFile Pathname
* @param dontOptimizeListFile Pathname
*/
public static void loadOptimizeLists(String optimizeListFile,
String dontOptimizeListFile) {
if (optimizeListsLoaded) {
return;
}
if (optimizeListFile != null && dontOptimizeListFile != null) {
/*
* We shouldn't get this far. The condition should have
* been caught in the arg processor.
*/
throw new RuntimeException("optimize and don't optimize lists "
+ " are mutually exclusive.");
}
if (optimizeListFile != null) {
optimizeList = loadStringsFromFile(optimizeListFile);
}
if (dontOptimizeListFile != null) {
dontOptimizeList = loadStringsFromFile(dontOptimizeListFile);
}
optimizeListsLoaded = true;
}
/**
* Loads a list of newline-separated strings into a new HashSet and returns
* the HashSet.
*
* @param filename filename to process
* @return set of all unique lines in the file
*/
private static HashSet<String> loadStringsFromFile(String filename) {
HashSet<String> result = new HashSet<String>();
try {
FileReader fr = new FileReader(filename);
BufferedReader bfr = new BufferedReader(fr);
String line;
while (null != (line = bfr.readLine())) {
result.add(line);
}
fr.close();
} catch (IOException ex) {
// Let the exception percolate up as a RuntimeException.
throw new RuntimeException("Error with optimize list: " +
filename, ex);
}
return result;
}
/**
* Compares the output of the optimizer run normally with a run skipping
* some optional steps. Results are printed to stderr.
*
* @param nonOptRmeth {@code non-null;} origional rop method
* @param paramSize {@code >= 0;} parameter size of method
* @param isStatic true if this method has no 'this' pointer argument.
* @param args {@code non-null;} translator arguments
* @param advice {@code non-null;} translation advice
* @param rmeth {@code non-null;} method with all optimization steps run.
*/
public static void compareOptimizerStep(RopMethod nonOptRmeth,
int paramSize, boolean isStatic, CfOptions args,
TranslationAdvice advice, RopMethod rmeth) {
EnumSet<Optimizer.OptionalStep> steps;
steps = EnumSet.allOf(Optimizer.OptionalStep.class);
// This is the step to skip.
steps.remove(Optimizer.OptionalStep.CONST_COLLECTOR);
RopMethod skipRopMethod
= Optimizer.optimize(nonOptRmeth,
paramSize, isStatic, args.localInfo, advice, steps);
int normalInsns
= rmeth.getBlocks().getEffectiveInstructionCount();
int skipInsns
= skipRopMethod.getBlocks().getEffectiveInstructionCount();
System.err.printf(
"optimize step regs:(%d/%d/%.2f%%)"
+ " insns:(%d/%d/%.2f%%)\n",
rmeth.getBlocks().getRegCount(),
skipRopMethod.getBlocks().getRegCount(),
100.0 * ((skipRopMethod.getBlocks().getRegCount()
- rmeth.getBlocks().getRegCount())
/ (float) skipRopMethod.getBlocks().getRegCount()),
normalInsns, skipInsns,
100.0 * ((skipInsns - normalInsns) / (float) skipInsns));
}
/**
* Checks whether the specified method should be optimized
*
* @param canonicalMethodName name of method being considered
* @return true if it should be optimized
*/
public static boolean shouldOptimize(String canonicalMethodName) {
// Optimize only what's in the optimize list.
if (optimizeList != null) {
return optimizeList.contains(canonicalMethodName);
}
/*
* Or don't optimize what's listed here. (The two lists are
* mutually exclusive.
*/
if (dontOptimizeList != null) {
return !dontOptimizeList.contains(canonicalMethodName);
}
// If neither list has been specified, then optimize everything.
return true;
}
}