• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.dx.dex.cf;
18 
19 import com.android.dx.rop.code.RopMethod;
20 import com.android.dx.rop.code.TranslationAdvice;
21 import com.android.dx.ssa.Optimizer;
22 
23 import java.io.BufferedReader;
24 import java.io.FileReader;
25 import java.io.IOException;
26 import java.util.EnumSet;
27 import java.util.HashSet;
28 
29 /**
30  * Settings for optimization of code.
31  */
32 public class OptimizerOptions {
33     /**
34      * {@code null-ok;} hash set of class name + method names that
35      * should be optimized. {@code null} if this constraint was not
36      * specified on the command line
37      */
38     private static HashSet<String> optimizeList;
39 
40     /**
41      * {@code null-ok;} hash set of class name + method names that should NOT
42      * be optimized.  null if this constraint was not specified on the
43      * command line
44      */
45     private static HashSet<String> dontOptimizeList;
46 
47     /** true if the above lists have been loaded */
48     private static boolean optimizeListsLoaded;
49 
50     /**
51      * This class is uninstantiable.
52      */
OptimizerOptions()53     private OptimizerOptions() {
54         // This space intentionally left blank.
55     }
56 
57     /**
58      * Loads the optimize/don't optimize lists from files.
59      *
60      * @param optimizeListFile Pathname
61      * @param dontOptimizeListFile Pathname
62      */
loadOptimizeLists(String optimizeListFile, String dontOptimizeListFile)63     public static void loadOptimizeLists(String optimizeListFile,
64             String dontOptimizeListFile) {
65         if (optimizeListsLoaded) {
66             return;
67         }
68 
69         if (optimizeListFile != null && dontOptimizeListFile != null) {
70             /*
71              * We shouldn't get this far. The condition should have
72              * been caught in the arg processor.
73              */
74             throw new RuntimeException("optimize and don't optimize lists "
75                     + " are mutually exclusive.");
76         }
77 
78         if (optimizeListFile != null) {
79             optimizeList = loadStringsFromFile(optimizeListFile);
80         }
81 
82         if (dontOptimizeListFile != null) {
83             dontOptimizeList = loadStringsFromFile(dontOptimizeListFile);
84         }
85 
86         optimizeListsLoaded = true;
87     }
88 
89     /**
90      * Loads a list of newline-separated strings into a new HashSet and returns
91      * the HashSet.
92      *
93      * @param filename filename to process
94      * @return set of all unique lines in the file
95      */
loadStringsFromFile(String filename)96     private static HashSet<String> loadStringsFromFile(String filename) {
97         HashSet<String> result = new HashSet<String>();
98 
99         try {
100             FileReader fr = new FileReader(filename);
101             BufferedReader bfr = new BufferedReader(fr);
102 
103             String line;
104 
105             while (null != (line = bfr.readLine())) {
106                 result.add(line);
107             }
108 
109             fr.close();
110         } catch (IOException ex) {
111             // Let the exception percolate up as a RuntimeException.
112             throw new RuntimeException("Error with optimize list: " +
113                     filename, ex);
114         }
115 
116         return result;
117     }
118 
119     /**
120      * Compares the output of the optimizer run normally with a run skipping
121      * some optional steps. Results are printed to stderr.
122      *
123      * @param nonOptRmeth {@code non-null;} origional rop method
124      * @param paramSize {@code >= 0;} parameter size of method
125      * @param isStatic true if this method has no 'this' pointer argument.
126      * @param args {@code non-null;} translator arguments
127      * @param advice {@code non-null;} translation advice
128      * @param rmeth {@code non-null;} method with all optimization steps run.
129      */
compareOptimizerStep(RopMethod nonOptRmeth, int paramSize, boolean isStatic, CfOptions args, TranslationAdvice advice, RopMethod rmeth)130     public static void compareOptimizerStep(RopMethod nonOptRmeth,
131             int paramSize, boolean isStatic, CfOptions args,
132             TranslationAdvice advice, RopMethod rmeth) {
133         EnumSet<Optimizer.OptionalStep> steps;
134 
135         steps = EnumSet.allOf(Optimizer.OptionalStep.class);
136 
137         // This is the step to skip.
138         steps.remove(Optimizer.OptionalStep.CONST_COLLECTOR);
139 
140         RopMethod skipRopMethod
141                 = Optimizer.optimize(nonOptRmeth,
142                         paramSize, isStatic, args.localInfo, advice, steps);
143 
144         int normalInsns
145                 = rmeth.getBlocks().getEffectiveInstructionCount();
146         int skipInsns
147                 = skipRopMethod.getBlocks().getEffectiveInstructionCount();
148 
149         System.err.printf(
150                 "optimize step regs:(%d/%d/%.2f%%)"
151                 + " insns:(%d/%d/%.2f%%)\n",
152                 rmeth.getBlocks().getRegCount(),
153                 skipRopMethod.getBlocks().getRegCount(),
154                 100.0 * ((skipRopMethod.getBlocks().getRegCount()
155                         - rmeth.getBlocks().getRegCount())
156                         / (float) skipRopMethod.getBlocks().getRegCount()),
157                 normalInsns, skipInsns,
158                 100.0 * ((skipInsns - normalInsns) / (float) skipInsns));
159     }
160 
161     /**
162      * Checks whether the specified method should be optimized
163      *
164      * @param canonicalMethodName name of method being considered
165      * @return true if it should be optimized
166      */
shouldOptimize(String canonicalMethodName)167     public static boolean shouldOptimize(String canonicalMethodName) {
168         // Optimize only what's in the optimize list.
169         if (optimizeList != null) {
170             return optimizeList.contains(canonicalMethodName);
171         }
172 
173         /*
174          * Or don't optimize what's listed here. (The two lists are
175          * mutually exclusive.
176          */
177 
178         if (dontOptimizeList != null) {
179             return !dontOptimizeList.contains(canonicalMethodName);
180         }
181 
182         // If neither list has been specified, then optimize everything.
183         return true;
184     }
185 }
186