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
17package com.android.dx.dex.cf;
18
19import com.android.dx.dex.code.DalvCode;
20import com.android.dx.rop.code.RopMethod;
21import java.io.PrintStream;
22
23/**
24 * Static methods and variables for collecting statistics on generated
25 * code.
26 */
27public 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 static 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 static int runningDeltaInsns = 0;
42
43    /** running sum of the total number of Rop insns processed */
44    public static 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 static 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 static int dexRunningDeltaInsns = 0;
58
59    /**
60     * running sum of the total number of dex insns (actually code
61     * units) processed
62     */
63    public static int dexRunningTotalInsns = 0;
64
65    /** running sum of original class bytecode bytes */
66    public static int runningOriginalBytes = 0;
67
68    /**
69     * This class is uninstantiable.
70     */
71    private CodeStatistics() {
72        // This space intentionally left blank.
73    }
74
75    /**
76     * Updates the number of original bytecode bytes processed.
77     *
78     * @param count {@code >= 0;} the number of bytes to add
79     */
80    public static void updateOriginalByteCount(int count) {
81        runningOriginalBytes += count;
82    }
83
84    /**
85     * Updates the dex statistics.
86     *
87     * @param nonOptCode non-optimized code block
88     * @param code optimized code block
89     */
90    public static void updateDexStatistics(DalvCode nonOptCode,
91            DalvCode code) {
92        if (DEBUG) {
93            System.err.println("dex insns (old/new) "
94                    + nonOptCode.getInsns().codeSize()
95                    + "/" + code.getInsns().codeSize()
96                    + " regs (o/n) "
97                    + nonOptCode.getInsns().getRegistersSize()
98                    + "/" + code.getInsns().getRegistersSize()
99            );
100        }
101
102        dexRunningDeltaInsns
103            += (code.getInsns().codeSize()
104                - nonOptCode.getInsns().codeSize());
105
106        dexRunningDeltaRegisters
107            += (code.getInsns().getRegistersSize()
108                - nonOptCode.getInsns().getRegistersSize());
109
110        dexRunningTotalInsns += code.getInsns().codeSize();
111    }
112
113    /**
114     * Updates the ROP statistics.
115     *
116     * @param nonOptRmeth non-optimized method
117     * @param rmeth optimized method
118     */
119    public static void updateRopStatistics(RopMethod nonOptRmeth,
120            RopMethod rmeth) {
121        int oldCountInsns
122                = nonOptRmeth.getBlocks().getEffectiveInstructionCount();
123        int oldCountRegs = nonOptRmeth.getBlocks().getRegCount();
124
125        if (DEBUG) {
126            System.err.println("insns (old/new): "
127                    + oldCountInsns + "/"
128                    + rmeth.getBlocks().getEffectiveInstructionCount()
129                    + " regs (o/n):" + oldCountRegs
130                    + "/"  +  rmeth.getBlocks().getRegCount());
131        }
132
133        int newCountInsns
134                = rmeth.getBlocks().getEffectiveInstructionCount();
135
136        runningDeltaInsns
137            += (newCountInsns - oldCountInsns);
138
139        runningDeltaRegisters
140            += (rmeth.getBlocks().getRegCount() - oldCountRegs);
141
142        runningTotalInsns += newCountInsns;
143    }
144
145    /**
146     * Prints out the collected statistics.
147     *
148     * @param out {@code non-null;} where to output to
149     */
150    public static void dumpStatistics(PrintStream out) {
151        out.printf("Optimizer Delta Rop Insns: %d total: %d "
152                + "(%.2f%%) Delta Registers: %d\n",
153                runningDeltaInsns,
154                runningTotalInsns,
155                (100.0 * (((float) runningDeltaInsns)
156                        / (runningTotalInsns + Math.abs(runningDeltaInsns)))),
157                runningDeltaRegisters);
158
159        out.printf("Optimizer Delta Dex Insns: Insns: %d total: %d "
160                + "(%.2f%%) Delta Registers: %d\n",
161                dexRunningDeltaInsns,
162                dexRunningTotalInsns,
163                (100.0 * (((float) dexRunningDeltaInsns)
164                        / (dexRunningTotalInsns
165                                + Math.abs(dexRunningDeltaInsns)))),
166                dexRunningDeltaRegisters);
167
168        out.printf("Original bytecode byte count: %d\n",
169                runningOriginalBytes);
170    }
171}
172