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.dex.code.DalvCode;
20 import com.android.dx.rop.code.RopMethod;
21 import java.io.PrintStream;
22 
23 /**
24  * Static methods and variables for collecting statistics on generated
25  * code.
26  */
27 public final class CodeStatistics {
28     /** set to {@code true} to enable development-time debugging code */
29     private static final boolean DEBUG = false;
30 
31     /**
32      * running sum of the number of registers added/removed in
33      * SSA form by the optimizer
34      */
35     public int runningDeltaRegisters = 0;
36 
37     /**
38      * running sum of the number of insns added/removed in
39      * SSA form by the optimizer
40      */
41     public int runningDeltaInsns = 0;
42 
43     /** running sum of the total number of Rop insns processed */
44     public int runningTotalInsns = 0;
45 
46     /**
47      * running sum of the number of dex-form registers added/removed in
48      * SSA form by the optimizer. Only valid if args.statistics is true.
49      */
50     public int dexRunningDeltaRegisters = 0;
51 
52     /**
53      * running sum of the number of dex-form insns (actually code
54      * units) added/removed in SSA form by the optimizer. Only valid
55      * if args.statistics is true.
56      */
57     public int dexRunningDeltaInsns = 0;
58 
59     /**
60      * running sum of the total number of dex insns (actually code
61      * units) processed
62      */
63     public int dexRunningTotalInsns = 0;
64 
65     /** running sum of original class bytecode bytes */
66     public int runningOriginalBytes = 0;
67 
68     /**
69      * Updates the number of original bytecode bytes processed.
70      *
71      * @param count {@code >= 0;} the number of bytes to add
72      */
updateOriginalByteCount(int count)73     public void updateOriginalByteCount(int count) {
74         runningOriginalBytes += count;
75     }
76 
77     /**
78      * Updates the dex statistics.
79      *
80      * @param nonOptCode non-optimized code block
81      * @param code optimized code block
82      */
updateDexStatistics(DalvCode nonOptCode, DalvCode code)83     public void updateDexStatistics(DalvCode nonOptCode,
84             DalvCode code) {
85         if (DEBUG) {
86             System.err.println("dex insns (old/new) "
87                     + nonOptCode.getInsns().codeSize()
88                     + "/" + code.getInsns().codeSize()
89                     + " regs (o/n) "
90                     + nonOptCode.getInsns().getRegistersSize()
91                     + "/" + code.getInsns().getRegistersSize()
92             );
93         }
94 
95         dexRunningDeltaInsns
96             += (code.getInsns().codeSize()
97                 - nonOptCode.getInsns().codeSize());
98 
99         dexRunningDeltaRegisters
100             += (code.getInsns().getRegistersSize()
101                 - nonOptCode.getInsns().getRegistersSize());
102 
103         dexRunningTotalInsns += code.getInsns().codeSize();
104     }
105 
106     /**
107      * Updates the ROP statistics.
108      *
109      * @param nonOptRmeth non-optimized method
110      * @param rmeth optimized method
111      */
updateRopStatistics(RopMethod nonOptRmeth, RopMethod rmeth)112     public void updateRopStatistics(RopMethod nonOptRmeth,
113             RopMethod rmeth) {
114         int oldCountInsns
115                 = nonOptRmeth.getBlocks().getEffectiveInstructionCount();
116         int oldCountRegs = nonOptRmeth.getBlocks().getRegCount();
117 
118         if (DEBUG) {
119             System.err.println("insns (old/new): "
120                     + oldCountInsns + "/"
121                     + rmeth.getBlocks().getEffectiveInstructionCount()
122                     + " regs (o/n):" + oldCountRegs
123                     + "/"  +  rmeth.getBlocks().getRegCount());
124         }
125 
126         int newCountInsns
127                 = rmeth.getBlocks().getEffectiveInstructionCount();
128 
129         runningDeltaInsns
130             += (newCountInsns - oldCountInsns);
131 
132         runningDeltaRegisters
133             += (rmeth.getBlocks().getRegCount() - oldCountRegs);
134 
135         runningTotalInsns += newCountInsns;
136     }
137 
138     /**
139      * Prints out the collected statistics.
140      *
141      * @param out {@code non-null;} where to output to
142      */
dumpStatistics(PrintStream out)143     public void dumpStatistics(PrintStream out) {
144         out.printf("Optimizer Delta Rop Insns: %d total: %d "
145                 + "(%.2f%%) Delta Registers: %d\n",
146                 runningDeltaInsns,
147                 runningTotalInsns,
148                 (100.0 * (((float) runningDeltaInsns)
149                         / (runningTotalInsns + Math.abs(runningDeltaInsns)))),
150                 runningDeltaRegisters);
151 
152         out.printf("Optimizer Delta Dex Insns: Insns: %d total: %d "
153                 + "(%.2f%%) Delta Registers: %d\n",
154                 dexRunningDeltaInsns,
155                 dexRunningTotalInsns,
156                 (100.0 * (((float) dexRunningDeltaInsns)
157                         / (dexRunningTotalInsns
158                                 + Math.abs(dexRunningDeltaInsns)))),
159                 dexRunningDeltaRegisters);
160 
161         out.printf("Original bytecode byte count: %d\n",
162                 runningOriginalBytes);
163     }
164 }
165