KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jode > obfuscator > modules > RemovePopAnalyzer


1 /* RemovePopAnalyzer Copyright (C) 1999-2002 Jochen Hoenicke.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; see the file COPYING. If not, write to
15  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16  *
17  * $Id: RemovePopAnalyzer.java.in,v 1.1.2.1 2002/05/28 17:34:17 hoenicke Exp $
18  */

19
20 package jode.obfuscator.modules;
21 import jode.bytecode.*;
22 import jode.obfuscator.*;
23 import jode.AssertError;
24 import jode.GlobalOptions;
25
26 import java.util.ListIterator JavaDoc;
27
28 public class RemovePopAnalyzer implements CodeTransformer, Opcodes {
29     public RemovePopAnalyzer() {
30     }
31
32     public void transformCode(BytecodeInfo bytecode) {
33     int poppush[] = new int[2];
34     ListIterator JavaDoc iter = bytecode.getInstructions().listIterator();
35     next_pop:
36     while (iter.hasNext()) {
37         Instruction popInstr = (Instruction) iter.next();
38         boolean isPop2 = false;
39         switch (popInstr.getOpcode()) {
40         case opc_nop: {
41         iter.remove();
42         continue;
43         }
44
45         case opc_pop2:
46         isPop2 = true;
47         case opc_pop:
48         if (popInstr.getPreds() != null)
49             // Can't handle pop with multiple predecessors
50
continue next_pop;
51         Handler[] handlers = bytecode.getExceptionHandlers();
52         for (int i=0; i < handlers.length; i++)
53             if (handlers[i].catcher == popInstr)
54             continue next_pop;
55
56         // remove pop, we will insert it again if something
57
// bad happened.
58
iter.remove();
59
60         // remember position of pop, so we can insert it again.
61
Instruction popPrevious = (Instruction) iter.previous();
62         Instruction instr = popPrevious;
63         int count = 0;
64         while (true) {
65             if (instr.getSuccs() != null
66             || instr.doesAlwaysJump()) {
67             instr = null;
68             break;
69             }
70             instr.getStackPopPush(poppush);
71
72             if (count < poppush[1]) {
73             if (count == 0)
74                 break;
75
76             int opcode = instr.getOpcode();
77             /* If this is a dup and the instruction popped is the
78              * duplicated element, remove the dup and the pop
79              */

80             if (count <= 3 && opcode == (opc_dup + count - 1)) {
81                 iter.remove();
82                 if (!isPop2)
83                 continue next_pop;
84
85                 // We have to consider a pop instead of a
86
// pop2 now.
87
popInstr = new Instruction(opc_pop);
88                 isPop2 = false;
89                 instr = (Instruction) iter.previous();
90                 continue;
91             }
92             
93             if (isPop2
94                 && count > 1 && count <= 4
95                 && opcode == (opc_dup2 + count-2)) {
96                 iter.remove();
97                 continue next_pop;
98             }
99             /* Otherwise popping is not possible */
100             instr = null;
101             break;
102             }
103             count += poppush[0] - poppush[1];
104             instr = (Instruction) iter.previous();
105         }
106
107         if (instr == null) {
108             // We insert the pop at the previous position
109
while (iter.next() != popPrevious)
110             {}
111             if (!isPop2 && popPrevious.getOpcode() == opc_pop) {
112             // merge pop with popPrevious
113
iter.set(new Instruction(opc_pop2));
114             } else
115             iter.add(popInstr);
116             continue;
117         }
118         int opcode = instr.getOpcode();
119         switch (opcode) {
120         case opc_ldc2_w:
121         case opc_lload: case opc_dload:
122             if (!isPop2)
123             throw new AssertError("pop on long");
124             iter.remove();
125             continue;
126         case opc_ldc:
127         case opc_iload: case opc_fload: case opc_aload:
128         case opc_dup:
129         case opc_new:
130             if (isPop2)
131             iter.set(new Instruction(opc_pop));
132             else
133             iter.remove();
134             continue;
135         case opc_iaload: case opc_faload: case opc_aaload:
136         case opc_baload: case opc_caload: case opc_saload:
137         case opc_iadd: case opc_fadd:
138         case opc_isub: case opc_fsub:
139         case opc_imul: case opc_fmul:
140         case opc_idiv: case opc_fdiv:
141         case opc_irem: case opc_frem:
142         case opc_iand: case opc_ior : case opc_ixor:
143         case opc_ishl: case opc_ishr: case opc_iushr:
144         case opc_fcmpl: case opc_fcmpg:
145             /* We have to pop one entry more. */
146             iter.next();
147             iter.add(popInstr);
148             iter.previous();
149             iter.previous();
150             iter.set(new Instruction(opc_pop));
151             continue;
152
153         case opc_dup_x1:
154             iter.set(new Instruction(opc_swap));
155             iter.next();
156             if (isPop2)
157             iter.add(new Instruction(opc_pop));
158             continue;
159
160         case opc_dup2:
161             if (isPop2) {
162             iter.remove();
163             continue;
164             }
165             break;
166         case opc_swap:
167             if (isPop2) {
168             iter.set(popInstr);
169             continue;
170             }
171             break;
172
173         case opc_lneg: case opc_dneg:
174         case opc_l2d: case opc_d2l:
175         case opc_laload: case opc_daload:
176             if (!isPop2)
177             throw new AssertError("pop on long");
178             /* fall through */
179         case opc_ineg: case opc_fneg:
180         case opc_i2f: case opc_f2i:
181         case opc_i2b: case opc_i2c: case opc_i2s:
182         case opc_newarray: case opc_anewarray:
183         case opc_arraylength:
184         case opc_instanceof:
185             iter.set(popInstr);
186             continue;
187
188         case opc_l2i: case opc_l2f:
189         case opc_d2i: case opc_d2f:
190             if (isPop2) {
191             iter.next();
192             iter.add(new Instruction(opc_pop));
193             iter.previous();
194             iter.previous();
195             }
196             iter.set(new Instruction(opc_pop2));
197             continue;
198
199         case opc_ladd: case opc_dadd:
200         case opc_lsub: case opc_dsub:
201         case opc_lmul: case opc_dmul:
202         case opc_ldiv: case opc_ddiv:
203         case opc_lrem: case opc_drem:
204         case opc_land: case opc_lor : case opc_lxor:
205             if (!isPop2)
206             throw new AssertError("pop on long");
207             iter.next();
208             iter.add(popInstr);
209             iter.previous();
210             iter.previous();
211             iter.set(new Instruction(opc_pop2));
212             continue;
213         case opc_lshl: case opc_lshr: case opc_lushr:
214             if (!isPop2)
215             throw new AssertError("pop on long");
216             iter.next();
217             iter.add(popInstr);
218             iter.previous();
219             iter.previous();
220             iter.set(new Instruction(opc_pop));
221             continue;
222
223         case opc_i2l: case opc_i2d:
224         case opc_f2l: case opc_f2d:
225             if (!isPop2)
226             throw new AssertError("pop on long");
227             iter.set(new Instruction(opc_pop));
228             continue;
229             
230         case opc_lcmp:
231         case opc_dcmpl: case opc_dcmpg:
232             iter.next();
233             iter.add(new Instruction(opc_pop2));
234             if (isPop2) {
235             iter.add(new Instruction(opc_pop));
236             iter.previous();
237             }
238             iter.previous();
239             iter.previous();
240             iter.set(new Instruction(opc_pop2));
241             continue;
242                     
243         case opc_getstatic:
244         case opc_getfield: {
245             Reference ref = instr.getReference();
246             int size = TypeSignature.getTypeSize(ref.getType());
247             if (size == 2 && !isPop2)
248             throw new AssertError("pop on long");
249             if (opcode == opc_getfield)
250             size--;
251             switch (size) {
252             case 0:
253             iter.set(popInstr);
254             break;
255             case 1:
256             if (isPop2) {
257                 iter.set(new Instruction(opc_pop));
258                 break;
259             }
260             /* fall through */
261             case 2:
262             iter.remove();
263             }
264             continue;
265         }
266
267         case opc_multianewarray: {
268             int dims = instr.getDimensions();
269             if (--dims > 0) {
270             iter.next();
271             while (dims-- > 0) {
272                 iter.add(new Instruction(opc_pop));
273                 iter.previous();
274             }
275             iter.previous();
276             }
277             iter.set(popInstr);
278             continue;
279         }
280
281         case opc_invokevirtual:
282         case opc_invokespecial:
283         case opc_invokestatic:
284         case opc_invokeinterface:
285             if (TypeSignature.getReturnSize
286             (instr.getReference().getType()) != 1)
287             break;
288             /* fall through */
289         case opc_checkcast:
290             if (isPop2) {
291             /* This is/may be a double pop on a single value
292              * split it and continue with second half
293              */

294             iter.next();
295             iter.add(new Instruction(opc_pop));
296             iter.add(new Instruction(opc_pop));
297             iter.previous();
298             continue;
299             }
300         }
301         // append the pop behind the unresolvable opcode.
302
iter.next();
303         iter.add(popInstr);
304         continue;
305         }
306     }
307     }
308 }
309
Popular Tags