1 30 package com.tc.asm.commons; 31 32 import java.util.ArrayList ; 33 import java.util.HashMap ; 34 35 import com.tc.asm.Label; 36 import com.tc.asm.MethodVisitor; 37 import com.tc.asm.Opcodes; 38 import com.tc.asm.Type; 39 40 58 public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes { 59 private static final Object THIS = new Object (); 60 private static final Object OTHER = new Object (); 61 62 protected int methodAccess; 63 protected String methodDesc; 64 65 private boolean constructor; 66 private boolean superInitialized; 67 private ArrayList stackFrame; 68 private HashMap branches; 69 70 71 79 public AdviceAdapter(MethodVisitor mv, int access, String name, String desc) { 80 super(mv, access, name, desc); 81 methodAccess = access; 82 methodDesc = desc; 83 84 constructor = "<init>".equals(name); 85 if (!constructor) { 86 superInitialized = true; 87 onMethodEnter(); 88 } else { 89 stackFrame = new ArrayList (); 90 branches = new HashMap (); 91 } 92 } 93 94 public void visitLabel(Label label) { 95 mv.visitLabel(label); 96 97 if (constructor && branches != null) { 98 ArrayList frame = (ArrayList ) branches.get(label); 99 if (frame != null) { 100 stackFrame = frame; 101 branches.remove(label); 102 } 103 } 104 } 105 106 public void visitInsn(int opcode) { 107 if (constructor) { 108 switch (opcode) { 109 case RETURN: onMethodExit(opcode); 111 break; 112 113 case IRETURN: case FRETURN: case ARETURN: case ATHROW: popValue(); 118 popValue(); 119 onMethodExit(opcode); 120 break; 121 122 case LRETURN: case DRETURN: popValue(); 125 popValue(); 126 onMethodExit(opcode); 127 break; 128 129 case NOP: 130 case LALOAD: case DALOAD: case LNEG: 133 case DNEG: 134 case FNEG: 135 case INEG: 136 case L2D: 137 case D2L: 138 case F2I: 139 case I2B: 140 case I2C: 141 case I2S: 142 case I2F: 143 case Opcodes.ARRAYLENGTH: 144 break; 145 146 case ACONST_NULL: 147 case ICONST_M1: 148 case ICONST_0: 149 case ICONST_1: 150 case ICONST_2: 151 case ICONST_3: 152 case ICONST_4: 153 case ICONST_5: 154 case FCONST_0: 155 case FCONST_1: 156 case FCONST_2: 157 case F2L: case F2D: 159 case I2L: 160 case I2D: 161 pushValue(OTHER); 162 break; 163 164 case LCONST_0: 165 case LCONST_1: 166 case DCONST_0: 167 case DCONST_1: 168 pushValue(OTHER); 169 pushValue(OTHER); 170 break; 171 172 case IALOAD: case FALOAD: case AALOAD: case BALOAD: case CALOAD: case SALOAD: case POP: 179 case IADD: 180 case FADD: 181 case ISUB: 182 case LSHL: case LSHR: case LUSHR: case L2I: case L2F: case D2I: case D2F: case FSUB: 190 case FMUL: 191 case FDIV: 192 case FREM: 193 case FCMPL: case FCMPG: case IMUL: 196 case IDIV: 197 case IREM: 198 case ISHL: 199 case ISHR: 200 case IUSHR: 201 case IAND: 202 case IOR: 203 case IXOR: 204 case MONITORENTER: 205 case MONITOREXIT: 206 popValue(); 207 break; 208 209 case POP2: 210 case LSUB: 211 case LMUL: 212 case LDIV: 213 case LREM: 214 case LADD: 215 case LAND: 216 case LOR: 217 case LXOR: 218 case DADD: 219 case DMUL: 220 case DSUB: 221 case DDIV: 222 case DREM: 223 popValue(); 224 popValue(); 225 break; 226 227 case IASTORE: 228 case FASTORE: 229 case AASTORE: 230 case BASTORE: 231 case CASTORE: 232 case SASTORE: 233 case LCMP: case DCMPL: 235 case DCMPG: 236 popValue(); 237 popValue(); 238 popValue(); 239 break; 240 241 case LASTORE: 242 case DASTORE: 243 popValue(); 244 popValue(); 245 popValue(); 246 popValue(); 247 break; 248 249 case DUP: 250 pushValue(peekValue()); 251 break; 252 253 case DUP_X1: 254 { 256 Object o1 = popValue(); 257 Object o2 = popValue(); 258 pushValue(o1); 259 pushValue(o2); 260 pushValue(o1); 261 } 262 break; 263 264 case DUP_X2: 265 { 267 Object o1 = popValue(); 268 Object o2 = popValue(); 269 Object o3 = popValue(); 270 pushValue(o1); 271 pushValue(o3); 272 pushValue(o2); 273 pushValue(o1); 274 } 275 break; 276 277 case DUP2: 278 { 280 Object o1 = popValue(); 281 Object o2 = popValue(); 282 pushValue(o2); 283 pushValue(o1); 284 pushValue(o2); 285 pushValue(o1); 286 } 287 break; 288 289 case DUP2_X1: 290 { 292 Object o1 = popValue(); 293 Object o2 = popValue(); 294 Object o3 = popValue(); 295 pushValue(o2); 296 pushValue(o1); 297 pushValue(o3); 298 pushValue(o2); 299 pushValue(o1); 300 } 301 break; 302 303 case DUP2_X2: 304 { 306 Object o1 = popValue(); 307 Object o2 = popValue(); 308 Object o3 = popValue(); 309 Object o4 = popValue(); 310 pushValue(o2); 311 pushValue(o1); 312 pushValue(o4); 313 pushValue(o3); 314 pushValue(o2); 315 pushValue(o1); 316 } 317 break; 318 319 case SWAP: { 320 Object o1 = popValue(); 321 Object o2 = popValue(); 322 pushValue(o1); 323 pushValue(o2); 324 } 325 break; 326 } 327 } else { 328 switch (opcode) { 329 case RETURN: 330 case IRETURN: 331 case FRETURN: 332 case ARETURN: 333 case LRETURN: 334 case DRETURN: 335 case ATHROW: 336 onMethodExit(opcode); 337 break; 338 } 339 } 340 mv.visitInsn(opcode); 341 } 342 343 public void visitVarInsn(int opcode, int var) { 344 super.visitVarInsn(opcode, var); 345 346 if (constructor) { 347 switch (opcode) { 348 case ILOAD: 349 case FLOAD: 350 pushValue(OTHER); 351 break; 352 case LLOAD: 353 case DLOAD: 354 pushValue(OTHER); 355 pushValue(OTHER); 356 break; 357 case ALOAD: 358 pushValue(var == 0 ? THIS : OTHER); 359 break; 360 case ASTORE: 361 case ISTORE: 362 case FSTORE: 363 popValue(); 364 break; 365 case LSTORE: 366 case DSTORE: 367 popValue(); 368 popValue(); 369 break; 370 } 371 } 372 } 373 374 public void visitFieldInsn( 375 int opcode, 376 String owner, 377 String name, 378 String desc) 379 { 380 mv.visitFieldInsn(opcode, owner, name, desc); 381 382 if (constructor) { 383 char c = desc.charAt(0); 384 boolean longOrDouble = c == 'J' || c == 'D'; 385 switch (opcode) { 386 case GETSTATIC: 387 pushValue(OTHER); 388 if (longOrDouble) { 389 pushValue(OTHER); 390 } 391 break; 392 case PUTSTATIC: 393 popValue(); 394 if(longOrDouble) { 395 popValue(); 396 } 397 break; 398 case PUTFIELD: 399 popValue(); 400 if(longOrDouble) { 401 popValue(); 402 popValue(); 403 } 404 break; 405 default: 407 if (longOrDouble) { 408 pushValue(OTHER); 409 } 410 } 411 } 412 } 413 414 public void visitIntInsn(int opcode, int operand) { 415 mv.visitIntInsn(opcode, operand); 416 417 if (constructor) { 418 switch (opcode) { 419 case BIPUSH: 420 case SIPUSH: 421 pushValue(OTHER); 422 } 423 } 424 } 425 426 public void visitLdcInsn(Object cst) { 427 mv.visitLdcInsn(cst); 428 429 if (constructor) { 430 pushValue(OTHER); 431 if (cst instanceof Double || cst instanceof Long ) { 432 pushValue(OTHER); 433 } 434 } 435 } 436 437 public void visitMultiANewArrayInsn(String desc, int dims) { 438 mv.visitMultiANewArrayInsn(desc, dims); 439 440 if (constructor) { 441 for (int i = 0; i < dims; i++) { 442 popValue(); 443 } 444 pushValue(OTHER); 445 } 446 } 447 448 public void visitTypeInsn(int opcode, String name) { 449 mv.visitTypeInsn(opcode, name); 450 451 if (constructor && opcode == NEW) { 453 pushValue(OTHER); 454 } 455 } 456 457 public void visitMethodInsn( 458 int opcode, 459 String owner, 460 String name, 461 String desc) 462 { 463 mv.visitMethodInsn(opcode, owner, name, desc); 464 465 if (constructor) { 466 Type[] types = Type.getArgumentTypes(desc); 467 for (int i = 0; i < types.length; i++) { 468 popValue(); 469 if (types[i].getSize() == 2) { 470 popValue(); 471 } 472 } 473 switch (opcode) { 474 477 case INVOKEINTERFACE: 478 case INVOKEVIRTUAL: 479 popValue(); break; 481 482 case INVOKESPECIAL: 483 Object type = popValue(); if (type == THIS && !superInitialized) { 485 onMethodEnter(); 486 superInitialized = true; 487 constructor = false; 490 } 491 break; 492 } 493 494 Type returnType = Type.getReturnType(desc); 495 if (returnType != Type.VOID_TYPE) { 496 pushValue(OTHER); 497 if (returnType.getSize() == 2) { 498 pushValue(OTHER); 499 } 500 } 501 } 502 } 503 504 public void visitJumpInsn(int opcode, Label label) { 505 mv.visitJumpInsn(opcode, label); 506 507 if (constructor) { 508 switch (opcode) { 509 case IFEQ: 510 case IFNE: 511 case IFLT: 512 case IFGE: 513 case IFGT: 514 case IFLE: 515 case IFNULL: 516 case IFNONNULL: 517 popValue(); 518 break; 519 520 case IF_ICMPEQ: 521 case IF_ICMPNE: 522 case IF_ICMPLT: 523 case IF_ICMPGE: 524 case IF_ICMPGT: 525 case IF_ICMPLE: 526 case IF_ACMPEQ: 527 case IF_ACMPNE: 528 popValue(); 529 popValue(); 530 break; 531 532 case JSR: 533 pushValue(OTHER); 534 break; 535 } 536 addBranch(label); 537 } 538 } 539 540 public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { 541 mv.visitLookupSwitchInsn(dflt, keys, labels); 542 543 if (constructor) { 544 popValue(); 545 addBranches(dflt, labels); 546 } 547 } 548 549 public void visitTableSwitchInsn( 550 int min, 551 int max, 552 Label dflt, 553 Label[] labels) 554 { 555 mv.visitTableSwitchInsn(min, max, dflt, labels); 556 557 if (constructor) { 558 popValue(); 559 addBranches(dflt, labels); 560 } 561 } 562 563 private void addBranches(Label dflt, Label[] labels) { 564 addBranch(dflt); 565 for (int i = 0; i < labels.length; i++) { 566 addBranch(labels[i]); 567 } 568 } 569 570 private void addBranch(Label label) { 571 if (branches.containsKey(label)) { 572 return; 573 } 574 ArrayList frame = new ArrayList (); 575 frame.addAll(stackFrame); 576 branches.put(label, frame); 577 } 578 579 private Object popValue() { 580 return stackFrame.remove(stackFrame.size()-1); 581 } 582 583 private Object peekValue() { 584 return stackFrame.get(stackFrame.size()-1); 585 } 586 587 private void pushValue(Object o) { 588 stackFrame.add(o); 589 } 590 591 599 protected abstract void onMethodEnter(); 600 601 638 protected abstract void onMethodExit(int opcode); 639 640 642 } 643 644 | Popular Tags |