xref: /aosp_15_r20/external/apache-commons-bcel/src/examples/Peephole.java (revision 0c56280ab0842982c46a149f7b9eaa497e31e292)
1*0c56280aSSorin Basca /*
2*0c56280aSSorin Basca  * Licensed to the Apache Software Foundation (ASF) under one or more
3*0c56280aSSorin Basca  * contributor license agreements.  See the NOTICE file distributed with
4*0c56280aSSorin Basca  * this work for additional information regarding copyright ownership.
5*0c56280aSSorin Basca  * The ASF licenses this file to You under the Apache License, Version 2.0
6*0c56280aSSorin Basca  * (the "License"); you may not use this file except in compliance with
7*0c56280aSSorin Basca  * the License.  You may obtain a copy of the License at
8*0c56280aSSorin Basca  *
9*0c56280aSSorin Basca  *      http://www.apache.org/licenses/LICENSE-2.0
10*0c56280aSSorin Basca  *
11*0c56280aSSorin Basca  *  Unless required by applicable law or agreed to in writing, software
12*0c56280aSSorin Basca  *  distributed under the License is distributed on an "AS IS" BASIS,
13*0c56280aSSorin Basca  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*0c56280aSSorin Basca  *  See the License for the specific language governing permissions and
15*0c56280aSSorin Basca  *  limitations under the License.
16*0c56280aSSorin Basca  *
17*0c56280aSSorin Basca  */
18*0c56280aSSorin Basca 
19*0c56280aSSorin Basca import java.util.Iterator;
20*0c56280aSSorin Basca 
21*0c56280aSSorin Basca import org.apache.bcel.Repository;
22*0c56280aSSorin Basca import org.apache.bcel.classfile.JavaClass;
23*0c56280aSSorin Basca import org.apache.bcel.classfile.Method;
24*0c56280aSSorin Basca import org.apache.bcel.generic.ConstantPoolGen;
25*0c56280aSSorin Basca import org.apache.bcel.generic.InstructionHandle;
26*0c56280aSSorin Basca import org.apache.bcel.generic.InstructionList;
27*0c56280aSSorin Basca import org.apache.bcel.generic.InstructionTargeter;
28*0c56280aSSorin Basca import org.apache.bcel.generic.MethodGen;
29*0c56280aSSorin Basca import org.apache.bcel.generic.TargetLostException;
30*0c56280aSSorin Basca import org.apache.bcel.util.InstructionFinder;
31*0c56280aSSorin Basca 
32*0c56280aSSorin Basca /**
33*0c56280aSSorin Basca  * Remove NOPs from given class
34*0c56280aSSorin Basca  *
35*0c56280aSSorin Basca  * @version $Id$
36*0c56280aSSorin Basca  */
37*0c56280aSSorin Basca public class Peephole {
38*0c56280aSSorin Basca 
main(String[] argv)39*0c56280aSSorin Basca     public static void main(String[] argv) {
40*0c56280aSSorin Basca         try {
41*0c56280aSSorin Basca             // Load the class from CLASSPATH.
42*0c56280aSSorin Basca             JavaClass clazz = Repository.lookupClass(argv[0]);
43*0c56280aSSorin Basca             Method[] methods = clazz.getMethods();
44*0c56280aSSorin Basca             ConstantPoolGen cp = new ConstantPoolGen(clazz.getConstantPool());
45*0c56280aSSorin Basca 
46*0c56280aSSorin Basca             for (int i = 0; i < methods.length; i++) {
47*0c56280aSSorin Basca                 if (!(methods[i].isAbstract() || methods[i].isNative())) {
48*0c56280aSSorin Basca                     MethodGen mg = new MethodGen(methods[i], clazz.getClassName(), cp);
49*0c56280aSSorin Basca                     Method stripped = removeNOPs(mg);
50*0c56280aSSorin Basca 
51*0c56280aSSorin Basca                     if (stripped != null) {
52*0c56280aSSorin Basca                         methods[i] = stripped; // Overwrite with stripped method
53*0c56280aSSorin Basca                     }
54*0c56280aSSorin Basca                 }
55*0c56280aSSorin Basca             }
56*0c56280aSSorin Basca 
57*0c56280aSSorin Basca             // Dump the class to <class name>_.class
58*0c56280aSSorin Basca             clazz.setConstantPool(cp.getFinalConstantPool());
59*0c56280aSSorin Basca             clazz.dump(clazz.getClassName() + "_.class");
60*0c56280aSSorin Basca         } catch (Exception e) {
61*0c56280aSSorin Basca             e.printStackTrace();
62*0c56280aSSorin Basca         }
63*0c56280aSSorin Basca     }
64*0c56280aSSorin Basca 
removeNOPs(MethodGen mg)65*0c56280aSSorin Basca     private static Method removeNOPs(MethodGen mg) {
66*0c56280aSSorin Basca         InstructionList il = mg.getInstructionList();
67*0c56280aSSorin Basca         InstructionFinder f = new InstructionFinder(il);
68*0c56280aSSorin Basca         String pat = "NOP+"; // Find at least one NOP
69*0c56280aSSorin Basca         InstructionHandle next = null;
70*0c56280aSSorin Basca         int count = 0;
71*0c56280aSSorin Basca 
72*0c56280aSSorin Basca         for (Iterator<InstructionHandle[]> e = f.search(pat); e.hasNext(); ) {
73*0c56280aSSorin Basca             InstructionHandle[] match = e.next();
74*0c56280aSSorin Basca             InstructionHandle first = match[0];
75*0c56280aSSorin Basca             InstructionHandle last = match[match.length - 1];
76*0c56280aSSorin Basca 
77*0c56280aSSorin Basca             // Some nasty Java compilers may add NOP at end of method.
78*0c56280aSSorin Basca             if ((next = last.getNext()) == null) {
79*0c56280aSSorin Basca                 break;
80*0c56280aSSorin Basca             }
81*0c56280aSSorin Basca 
82*0c56280aSSorin Basca             count += match.length;
83*0c56280aSSorin Basca 
84*0c56280aSSorin Basca             // Delete NOPs and redirect any references to them to the following (non-nop) instruction.
85*0c56280aSSorin Basca             try {
86*0c56280aSSorin Basca                 il.delete(first, last);
87*0c56280aSSorin Basca             } catch (TargetLostException e2) {
88*0c56280aSSorin Basca                 for (InstructionHandle target : e2.getTargets()) {
89*0c56280aSSorin Basca                     for (InstructionTargeter targeter : target.getTargeters()) {
90*0c56280aSSorin Basca                         targeter.updateTarget(target, next);
91*0c56280aSSorin Basca                     }
92*0c56280aSSorin Basca                 }
93*0c56280aSSorin Basca             }
94*0c56280aSSorin Basca         }
95*0c56280aSSorin Basca 
96*0c56280aSSorin Basca         Method m = null;
97*0c56280aSSorin Basca 
98*0c56280aSSorin Basca         if (count > 0) {
99*0c56280aSSorin Basca             System.out.println("Removed " + count + " NOP instructions from method " + mg.getName());
100*0c56280aSSorin Basca             m = mg.getMethod();
101*0c56280aSSorin Basca         }
102*0c56280aSSorin Basca 
103*0c56280aSSorin Basca         il.dispose(); // Reuse instruction handles
104*0c56280aSSorin Basca         return m;
105*0c56280aSSorin Basca     }
106*0c56280aSSorin Basca }
107