KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > proguard > optimize > peephole > GotoGotoReplacer


1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  * of Java bytecode.
4  *
5  * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu)
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */

21 package proguard.optimize.peephole;
22
23 import proguard.classfile.*;
24 import proguard.classfile.visitor.ClassPrinter;
25 import proguard.classfile.attribute.CodeAttribute;
26 import proguard.classfile.editor.CodeAttributeEditor;
27 import proguard.classfile.instruction.*;
28 import proguard.classfile.instruction.visitor.InstructionVisitor;
29 import proguard.classfile.util.SimplifiedVisitor;
30
31 /**
32  * This InstructionVisitor simplifies unconditional branches to other
33  * unconditional branches.
34  *
35  * @author Eric Lafortune
36  */

37 public class GotoGotoReplacer
38 extends SimplifiedVisitor
39 implements InstructionVisitor
40 {
41     private CodeAttributeEditor codeAttributeEditor;
42     private InstructionVisitor extraInstructionVisitor;
43
44
45     /**
46      * Creates a new GotoGotoReplacer.
47      * @param codeAttributeEditor a code editor that can be used for
48      * accumulating changes to the code.
49      */

50     public GotoGotoReplacer(CodeAttributeEditor codeAttributeEditor)
51     {
52         this(codeAttributeEditor, null);
53     }
54
55
56     /**
57      * Creates a new GotoGotoReplacer.
58      * @param codeAttributeEditor a code editor that can be used for
59      * accumulating changes to the code.
60      * @param extraInstructionVisitor an optional extra visitor for all replaced
61      * goto instructions.
62      */

63     public GotoGotoReplacer(CodeAttributeEditor codeAttributeEditor,
64                             InstructionVisitor extraInstructionVisitor)
65     {
66         this.codeAttributeEditor = codeAttributeEditor;
67         this.extraInstructionVisitor = extraInstructionVisitor;
68     }
69
70
71     // Implementations for InstructionVisitor.
72

73     public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
74
75
76     public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
77     {
78         // Check if the instruction is an unconditional goto instruction.
79
byte opcode = branchInstruction.opcode;
80         if (opcode == InstructionConstants.OP_GOTO ||
81             opcode == InstructionConstants.OP_GOTO_W)
82         {
83             // Check if the goto instruction points to another simple goto
84
// instruction.
85
int branchOffset = branchInstruction.branchOffset;
86             int targetOffset = offset + branchOffset;
87
88             if (branchOffset != branchInstruction.length(offset) &&
89                 !codeAttributeEditor.isModified(offset) &&
90                 !codeAttributeEditor.isModified(targetOffset))
91             {
92                 Instruction targetInstruction =
93                     InstructionFactory.create(codeAttribute.code, targetOffset);
94                 
95                 if (targetInstruction.opcode == InstructionConstants.OP_GOTO)
96                 {
97                     // Simplify the goto instruction.
98
int targetBranchOffset = ((BranchInstruction)targetInstruction).branchOffset;
99
100                     Instruction newBranchInstruction =
101                          new BranchInstruction(opcode,
102                                                (branchOffset + targetBranchOffset));
103                     codeAttributeEditor.replaceInstruction(offset,
104                                                            newBranchInstruction);
105
106                     // Visit the instruction, if required.
107
if (extraInstructionVisitor != null)
108                     {
109                         extraInstructionVisitor.visitBranchInstruction(clazz, method, codeAttribute, offset, branchInstruction);
110                     }
111                 }
112             }
113         }
114     }
115 }
116
Popular Tags