KickJava   Java API By Example, From Geeks To Geeks.

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


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.attribute.CodeAttribute;
25 import proguard.classfile.editor.CodeAttributeEditor;
26 import proguard.classfile.instruction.*;
27 import proguard.classfile.instruction.visitor.InstructionVisitor;
28 import proguard.classfile.util.SimplifiedVisitor;
29
30 /**
31  * This InstructionVisitor replaces store/load instruction pairs by equivalent
32  * dup/store instruction pairs.
33  *
34  * @author Eric Lafortune
35  */

36 public class StoreLoadReplacer
37 extends SimplifiedVisitor
38 implements InstructionVisitor
39 {
40     // Some Instruction objects that can be reused.
41
private Instruction dupInstruction = new SimpleInstruction(InstructionConstants.OP_DUP);
42     private Instruction dup2Instruction = new SimpleInstruction(InstructionConstants.OP_DUP2);
43
44     private BranchTargetFinder branchTargetFinder;
45     private CodeAttributeEditor codeAttributeEditor;
46     private InstructionVisitor extraInstructionVisitor;
47
48
49     /**
50      * Creates a new StoreLoadReplacer.
51      * @param branchTargetFinder a branch target finder that has been
52      * initialized to indicate branch targets
53      * in the visited code.
54      * @param codeAttributeEditor a code editor that can be used for
55      * accumulating changes to the code.
56      */

57     public StoreLoadReplacer(BranchTargetFinder branchTargetFinder,
58                              CodeAttributeEditor codeAttributeEditor)
59     {
60         this(branchTargetFinder, codeAttributeEditor, null);
61     }
62
63
64     /**
65      * Creates a new StoreLoadReplacer.
66      * @param branchTargetFinder a branch target finder that has been
67      * initialized to indicate branch targets
68      * in the visited code.
69      * @param codeAttributeEditor a code editor that can be used for
70      * accumulating changes to the code.
71      * @param extraInstructionVisitor an optional extra visitor for all replaced
72      * store instructions.
73      */

74     public StoreLoadReplacer(BranchTargetFinder branchTargetFinder,
75                              CodeAttributeEditor codeAttributeEditor,
76                              InstructionVisitor extraInstructionVisitor)
77     {
78         this.branchTargetFinder = branchTargetFinder;
79         this.codeAttributeEditor = codeAttributeEditor;
80         this.extraInstructionVisitor = extraInstructionVisitor;
81     }
82
83
84     // Implementations for InstructionVisitor.
85

86     public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
87
88
89     public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
90     {
91         // Is this instruction a regular store instruction?
92
if (!variableInstruction.isLoad() &&
93             variableInstruction.opcode != InstructionConstants.OP_IINC)
94         {
95             byte opcode = variableInstruction.opcode;
96             int variableIndex = variableInstruction.variableIndex;
97
98             int nextOffset = offset + variableInstruction.length(offset);
99
100             if (!codeAttributeEditor.isModified(offset) &&
101                 !codeAttributeEditor.isModified(nextOffset) &&
102                 !branchTargetFinder.isTarget(nextOffset))
103             {
104                 // Is the next instruction a corresponding load instruction?
105
Instruction nextInstruction = InstructionFactory.create(codeAttribute.code,
106                                                                         nextOffset);
107
108                 if (nextInstruction instanceof VariableInstruction)
109                 {
110                     variableInstruction = (VariableInstruction)nextInstruction;
111                     if (variableInstruction.isLoad() &&
112                         variableInstruction.opcode != InstructionConstants.OP_RET &&
113                         variableInstruction.variableIndex == variableIndex)
114                     {
115                         // Replace the store instruction by a matching dup instruction.
116
Instruction matchingDupInstruction = variableInstruction.isCategory2() ?
117                                                              dup2Instruction :
118                                                              dupInstruction;
119
120                         codeAttributeEditor.replaceInstruction(offset,
121                                                                matchingDupInstruction);
122
123                         // Replace the load instruction by the store instruction.
124
Instruction storeInstruction =
125                              new VariableInstruction(opcode,
126                                                      variableInstruction.variableIndex).shrink();
127
128                         codeAttributeEditor.replaceInstruction(nextOffset,
129                                                                storeInstruction);
130
131                         // Visit the instruction, if required.
132
if (extraInstructionVisitor != null)
133                         {
134                             extraInstructionVisitor.visitVariableInstruction(clazz, method, codeAttribute, offset, variableInstruction);
135                         }
136                     }
137                 }
138             }
139         }
140     }
141 }
142
Popular Tags