| /* |
| * 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; |
| } |
| } |