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