1 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 ; 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 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 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 iter.remove(); 59 60 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 80 if (count <= 3 && opcode == (opc_dup + count - 1)) { 81 iter.remove(); 82 if (!isPop2) 83 continue next_pop; 84 85 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 100 instr = null; 101 break; 102 } 103 count += poppush[0] - poppush[1]; 104 instr = (Instruction) iter.previous(); 105 } 106 107 if (instr == null) { 108 while (iter.next() != popPrevious) 110 {} 111 if (!isPop2 && popPrevious.getOpcode() == opc_pop) { 112 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 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 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 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 289 case opc_checkcast: 290 if (isPop2) { 291 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 iter.next(); 303 iter.add(popInstr); 304 continue; 305 } 306 } 307 } 308 } 309 | Popular Tags |