1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/*
2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification
3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *             of Java bytecode.
4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
59f606f95f03a75961498803e24bee6799a7c0885Ying Wang * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
6b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
7b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is free software; you can redistribute it and/or modify it
8b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * under the terms of the GNU General Public License as published by the Free
9b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Software Foundation; either version 2 of the License, or (at your option)
10b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * any later version.
11b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
12b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is distributed in the hope that it will be useful, but WITHOUT
13b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * more details.
16b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
17b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * You should have received a copy of the GNU General Public License along
18b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * with this program; if not, write to the Free Software Foundation, Inc.,
19b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
21b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopackage proguard.optimize.peephole;
22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.*;
24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.*;
25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.visitor.AttributeVisitor;
26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.editor.CodeAttributeEditor;
27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.instruction.Instruction;
28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.instruction.visitor.InstructionVisitor;
29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.util.SimplifiedVisitor;
30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/**
32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This InstructionVisitor deletes blocks of code that can never be reached by
33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * regular calls or branches.
34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
35b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune
36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class UnreachableCodeRemover
38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoextends      SimplifiedVisitor
39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimplements   AttributeVisitor,
40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato             InstructionVisitor
41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{
42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    //*
43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static final boolean DEBUG = false;
44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /*/
45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static       boolean DEBUG = true;
46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    //*/
47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final InstructionVisitor  extraInstructionVisitor;
49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final ReachableCodeMarker reachableCodeMarker = new ReachableCodeMarker();
51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new UnreachableCodeRemover.
56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public UnreachableCodeRemover()
58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this(null);
60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new UnreachableCodeRemover.
65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param extraInstructionVisitor an optional extra visitor for all
66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                deleted instructions.
67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public UnreachableCodeRemover(InstructionVisitor  extraInstructionVisitor)
69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.extraInstructionVisitor = extraInstructionVisitor;
71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for AttributeVisitor.
75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato//        DEBUG =
82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato//            clazz.getName().equals("abc/Def") &&
83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato//            method.getName(clazz).equals("abc");
84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // TODO: Remove this when the code has stabilized.
86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Catch any unexpected exceptions from the actual visiting method.
87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        try
88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Process the code.
90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            visitCodeAttribute0(clazz, method, codeAttribute);
91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        catch (RuntimeException ex)
93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            System.err.println("Unexpected error while removing unreachable code:");
95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            System.err.println("  Class       = ["+clazz.getName()+"]");
96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            System.err.println("  Method      = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]");
97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            System.err.println("  Exception   = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")");
98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            throw ex;
100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (DEBUG)
107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            System.out.println("UnreachableCodeRemover: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        reachableCodeMarker.visitCodeAttribute(clazz, method, codeAttribute);
112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        codeAttributeEditor.reset(codeAttribute.u4codeLength);
114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        codeAttribute.instructionsAccept(clazz, method, this);
116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for InstructionVisitor.
122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (DEBUG)
126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            System.out.println("  "+(reachableCodeMarker.isReachable(offset) ? "+" : "-")+" "+instruction.toString(offset));
128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Is this instruction unreachable?
131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (!reachableCodeMarker.isReachable(offset))
132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Then delete it.
134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            codeAttributeEditor.deleteInstruction(offset);
135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Visit the instruction, if required.
137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (extraInstructionVisitor != null)
138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                instruction.accept(clazz, method, codeAttribute, offset, extraInstructionVisitor);
140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}
144