rev 47452 : imported patch jdk-new-asmv6.patch
1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /* 26 * This file is available under and governed by the GNU General Public 27 * License version 2 only, as published by the Free Software Foundation. 28 * However, the following notice accompanied the original version of this 29 * file: 30 * 31 * ASM: a very small and fast Java bytecode manipulation framework 32 * Copyright (c) 2000-2011 INRIA, France Telecom 33 * All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. Neither the name of the copyright holders nor the names of its 44 * contributors may be used to endorse or promote products derived from 45 * this software without specific prior written permission. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 51 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 52 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 53 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 54 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 57 * THE POSSIBILITY OF SUCH DAMAGE. 58 */ 59 package jdk.internal.org.objectweb.asm.util; 60 61 import java.io.FileInputStream; 62 import java.io.PrintWriter; 63 import java.util.HashMap; 64 import java.util.Map; 65 66 import jdk.internal.org.objectweb.asm.Attribute; 67 import jdk.internal.org.objectweb.asm.ClassReader; 68 import jdk.internal.org.objectweb.asm.Handle; 69 import jdk.internal.org.objectweb.asm.Label; 70 import jdk.internal.org.objectweb.asm.Opcodes; 71 import jdk.internal.org.objectweb.asm.Type; 72 import jdk.internal.org.objectweb.asm.TypePath; 73 74 /** 75 * A {@link Printer} that prints the ASM code to generate the classes if visits. 76 * 77 * @author Eric Bruneton 78 */ 79 public class ASMifier extends Printer { 80 81 /** 82 * The name of the visitor variable in the produced code. 83 */ 84 protected final String name; 85 86 /** 87 * Identifier of the annotation visitor variable in the produced code. 88 */ 89 protected final int id; 90 91 /** 92 * The label names. This map associates String values to Label keys. It is 93 * used only in ASMifierMethodVisitor. 94 */ 95 protected Map<Label, String> labelNames; 96 97 /** 98 * Pseudo access flag used to distinguish class access flags. 99 */ 100 private static final int ACCESS_CLASS = 262144; 101 102 /** 103 * Pseudo access flag used to distinguish field access flags. 104 */ 105 private static final int ACCESS_FIELD = 524288; 106 107 /** 108 * Pseudo access flag used to distinguish inner class flags. 109 */ 110 private static final int ACCESS_INNER = 1048576; 111 112 /** 113 * Constructs a new {@link ASMifier}. <i>Subclasses must not use this 114 * constructor</i>. Instead, they must use the 115 * {@link #ASMifier(int, String, int)} version. 116 * 117 * @throws IllegalStateException 118 * If a subclass calls this constructor. 119 */ 120 public ASMifier() { 121 this(Opcodes.ASM5, "cw", 0); 122 if (getClass() != ASMifier.class) { 123 throw new IllegalStateException(); 124 } 125 } 126 127 /** 128 * Constructs a new {@link ASMifier}. 129 * 130 * @param api 131 * the ASM API version implemented by this class. Must be one of 132 * {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. 133 * @param name 134 * the name of the visitor variable in the produced code. 135 * @param id 136 * identifier of the annotation visitor variable in the produced 137 * code. 138 */ 139 protected ASMifier(final int api, final String name, final int id) { 140 super(api); 141 this.name = name; 142 this.id = id; 143 } 144 145 /** 146 * Prints the ASM source code to generate the given class to the standard 147 * output. 148 * <p> 149 * Usage: ASMifier [-debug] <binary class name or class file name> 150 * 151 * @param args 152 * the command line arguments. 153 * 154 * @throws Exception 155 * if the class cannot be found, or if an IO exception occurs. 156 */ 157 public static void main(final String[] args) throws Exception { 158 int i = 0; 159 int flags = ClassReader.SKIP_DEBUG; 160 161 boolean ok = true; 162 if (args.length < 1 || args.length > 2) { 163 ok = false; 164 } 165 if (ok && "-debug".equals(args[0])) { 166 i = 1; 167 flags = 0; 168 if (args.length != 2) { 169 ok = false; 170 } 171 } 172 if (!ok) { 173 System.err 174 .println("Prints the ASM code to generate the given class."); 175 System.err.println("Usage: ASMifier [-debug] " 176 + "<fully qualified class name or class file name>"); 177 return; 178 } 179 ClassReader cr; 180 if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1 181 || args[i].indexOf('/') > -1) { 182 cr = new ClassReader(new FileInputStream(args[i])); 183 } else { 184 cr = new ClassReader(args[i]); 185 } 186 cr.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter( 187 System.out)), flags); 188 } 189 190 // ------------------------------------------------------------------------ 191 // Classes 192 // ------------------------------------------------------------------------ 193 194 @Override 195 public void visit(final int version, final int access, final String name, 196 final String signature, final String superName, 197 final String[] interfaces) { 198 String simpleName; 199 int n = name.lastIndexOf('/'); 200 if (n == -1) { 201 simpleName = name; 202 } else { 203 text.add("package asm." + name.substring(0, n).replace('/', '.') 204 + ";\n"); 205 simpleName = name.substring(n + 1); 206 } 207 text.add("import java.util.*;\n"); 208 text.add("import jdk.internal.org.objectweb.asm.*;\n"); 209 text.add("public class " + simpleName + "Dump implements Opcodes {\n\n"); 210 text.add("public static byte[] dump () throws Exception {\n\n"); 211 text.add("ClassWriter cw = new ClassWriter(0);\n"); 212 text.add("FieldVisitor fv;\n"); 213 text.add("MethodVisitor mv;\n"); 214 text.add("AnnotationVisitor av0;\n\n"); 215 216 buf.setLength(0); 217 buf.append("cw.visit("); 218 switch (version) { 219 case Opcodes.V1_1: 220 buf.append("V1_1"); 221 break; 222 case Opcodes.V1_2: 223 buf.append("V1_2"); 224 break; 225 case Opcodes.V1_3: 226 buf.append("V1_3"); 227 break; 228 case Opcodes.V1_4: 229 buf.append("V1_4"); 230 break; 231 case Opcodes.V1_5: 232 buf.append("V1_5"); 233 break; 234 case Opcodes.V1_6: 235 buf.append("V1_6"); 236 break; 237 case Opcodes.V1_7: 238 buf.append("V1_7"); 239 break; 240 default: 241 buf.append(version); 242 break; 243 } 244 buf.append(", "); 245 appendAccess(access | ACCESS_CLASS); 246 buf.append(", "); 247 appendConstant(name); 248 buf.append(", "); 249 appendConstant(signature); 250 buf.append(", "); 251 appendConstant(superName); 252 buf.append(", "); 253 if (interfaces != null && interfaces.length > 0) { 254 buf.append("new String[] {"); 255 for (int i = 0; i < interfaces.length; ++i) { 256 buf.append(i == 0 ? " " : ", "); 257 appendConstant(interfaces[i]); 258 } 259 buf.append(" }"); 260 } else { 261 buf.append("null"); 262 } 263 buf.append(");\n\n"); 264 text.add(buf.toString()); 265 } 266 267 @Override 268 public void visitSource(final String file, final String debug) { 269 buf.setLength(0); 270 buf.append("cw.visitSource("); 271 appendConstant(file); 272 buf.append(", "); 273 appendConstant(debug); 274 buf.append(");\n\n"); 275 text.add(buf.toString()); 276 } 277 278 @Override 279 public void visitOuterClass(final String owner, final String name, 280 final String desc) { 281 buf.setLength(0); 282 buf.append("cw.visitOuterClass("); 283 appendConstant(owner); 284 buf.append(", "); 285 appendConstant(name); 286 buf.append(", "); 287 appendConstant(desc); 288 buf.append(");\n\n"); 289 text.add(buf.toString()); 290 } 291 292 @Override 293 public ASMifier visitClassAnnotation(final String desc, 294 final boolean visible) { 295 return visitAnnotation(desc, visible); 296 } 297 298 @Override 299 public ASMifier visitClassTypeAnnotation(final int typeRef, 300 final TypePath typePath, final String desc, final boolean visible) { 301 return visitTypeAnnotation(typeRef, typePath, desc, visible); 302 } 303 304 @Override 305 public void visitClassAttribute(final Attribute attr) { 306 visitAttribute(attr); 307 } 308 309 @Override 310 public void visitInnerClass(final String name, final String outerName, 311 final String innerName, final int access) { 312 buf.setLength(0); 313 buf.append("cw.visitInnerClass("); 314 appendConstant(name); 315 buf.append(", "); 316 appendConstant(outerName); 317 buf.append(", "); 318 appendConstant(innerName); 319 buf.append(", "); 320 appendAccess(access | ACCESS_INNER); 321 buf.append(");\n\n"); 322 text.add(buf.toString()); 323 } 324 325 @Override 326 public ASMifier visitField(final int access, final String name, 327 final String desc, final String signature, final Object value) { 328 buf.setLength(0); 329 buf.append("{\n"); 330 buf.append("fv = cw.visitField("); 331 appendAccess(access | ACCESS_FIELD); 332 buf.append(", "); 333 appendConstant(name); 334 buf.append(", "); 335 appendConstant(desc); 336 buf.append(", "); 337 appendConstant(signature); 338 buf.append(", "); 339 appendConstant(value); 340 buf.append(");\n"); 341 text.add(buf.toString()); 342 ASMifier a = createASMifier("fv", 0); 343 text.add(a.getText()); 344 text.add("}\n"); 345 return a; 346 } 347 348 @Override 349 public ASMifier visitMethod(final int access, final String name, 350 final String desc, final String signature, final String[] exceptions) { 351 buf.setLength(0); 352 buf.append("{\n"); 353 buf.append("mv = cw.visitMethod("); 354 appendAccess(access); 355 buf.append(", "); 356 appendConstant(name); 357 buf.append(", "); 358 appendConstant(desc); 359 buf.append(", "); 360 appendConstant(signature); 361 buf.append(", "); 362 if (exceptions != null && exceptions.length > 0) { 363 buf.append("new String[] {"); 364 for (int i = 0; i < exceptions.length; ++i) { 365 buf.append(i == 0 ? " " : ", "); 366 appendConstant(exceptions[i]); 367 } 368 buf.append(" }"); 369 } else { 370 buf.append("null"); 371 } 372 buf.append(");\n"); 373 text.add(buf.toString()); 374 ASMifier a = createASMifier("mv", 0); 375 text.add(a.getText()); 376 text.add("}\n"); 377 return a; 378 } 379 380 @Override 381 public void visitClassEnd() { 382 text.add("cw.visitEnd();\n\n"); 383 text.add("return cw.toByteArray();\n"); 384 text.add("}\n"); 385 text.add("}\n"); 386 } 387 388 // ------------------------------------------------------------------------ 389 // Annotations 390 // ------------------------------------------------------------------------ 391 392 @Override 393 public void visit(final String name, final Object value) { 394 buf.setLength(0); 395 buf.append("av").append(id).append(".visit("); 396 appendConstant(buf, name); 397 buf.append(", "); 398 appendConstant(buf, value); 399 buf.append(");\n"); 400 text.add(buf.toString()); 401 } 402 403 @Override 404 public void visitEnum(final String name, final String desc, 405 final String value) { 406 buf.setLength(0); 407 buf.append("av").append(id).append(".visitEnum("); 408 appendConstant(buf, name); 409 buf.append(", "); 410 appendConstant(buf, desc); 411 buf.append(", "); 412 appendConstant(buf, value); 413 buf.append(");\n"); 414 text.add(buf.toString()); 415 } 416 417 @Override 418 public ASMifier visitAnnotation(final String name, final String desc) { 419 buf.setLength(0); 420 buf.append("{\n"); 421 buf.append("AnnotationVisitor av").append(id + 1).append(" = av"); 422 buf.append(id).append(".visitAnnotation("); 423 appendConstant(buf, name); 424 buf.append(", "); 425 appendConstant(buf, desc); 426 buf.append(");\n"); 427 text.add(buf.toString()); 428 ASMifier a = createASMifier("av", id + 1); 429 text.add(a.getText()); 430 text.add("}\n"); 431 return a; 432 } 433 434 @Override 435 public ASMifier visitArray(final String name) { 436 buf.setLength(0); 437 buf.append("{\n"); 438 buf.append("AnnotationVisitor av").append(id + 1).append(" = av"); 439 buf.append(id).append(".visitArray("); 440 appendConstant(buf, name); 441 buf.append(");\n"); 442 text.add(buf.toString()); 443 ASMifier a = createASMifier("av", id + 1); 444 text.add(a.getText()); 445 text.add("}\n"); 446 return a; 447 } 448 449 @Override 450 public void visitAnnotationEnd() { 451 buf.setLength(0); 452 buf.append("av").append(id).append(".visitEnd();\n"); 453 text.add(buf.toString()); 454 } 455 456 // ------------------------------------------------------------------------ 457 // Fields 458 // ------------------------------------------------------------------------ 459 460 @Override 461 public ASMifier visitFieldAnnotation(final String desc, 462 final boolean visible) { 463 return visitAnnotation(desc, visible); 464 } 465 466 @Override 467 public ASMifier visitFieldTypeAnnotation(final int typeRef, 468 final TypePath typePath, final String desc, final boolean visible) { 469 return visitTypeAnnotation(typeRef, typePath, desc, visible); 470 } 471 472 @Override 473 public void visitFieldAttribute(final Attribute attr) { 474 visitAttribute(attr); 475 } 476 477 @Override 478 public void visitFieldEnd() { 479 buf.setLength(0); 480 buf.append(name).append(".visitEnd();\n"); 481 text.add(buf.toString()); 482 } 483 484 // ------------------------------------------------------------------------ 485 // Methods 486 // ------------------------------------------------------------------------ 487 488 @Override 489 public void visitParameter(String parameterName, int access) { 490 buf.setLength(0); 491 buf.append(name).append(".visitParameter("); 492 appendString(buf, parameterName); 493 buf.append(", "); 494 appendAccess(access); 495 text.add(buf.append(");\n").toString()); 496 } 497 498 @Override 499 public ASMifier visitAnnotationDefault() { 500 buf.setLength(0); 501 buf.append("{\n").append("av0 = ").append(name) 502 .append(".visitAnnotationDefault();\n"); 503 text.add(buf.toString()); 504 ASMifier a = createASMifier("av", 0); 505 text.add(a.getText()); 506 text.add("}\n"); 507 return a; 508 } 509 510 @Override 511 public ASMifier visitMethodAnnotation(final String desc, 512 final boolean visible) { 513 return visitAnnotation(desc, visible); 514 } 515 516 @Override 517 public ASMifier visitMethodTypeAnnotation(final int typeRef, 518 final TypePath typePath, final String desc, final boolean visible) { 519 return visitTypeAnnotation(typeRef, typePath, desc, visible); 520 } 521 522 @Override 523 public ASMifier visitParameterAnnotation(final int parameter, 524 final String desc, final boolean visible) { 525 buf.setLength(0); 526 buf.append("{\n").append("av0 = ").append(name) 527 .append(".visitParameterAnnotation(").append(parameter) 528 .append(", "); 529 appendConstant(desc); 530 buf.append(", ").append(visible).append(");\n"); 531 text.add(buf.toString()); 532 ASMifier a = createASMifier("av", 0); 533 text.add(a.getText()); 534 text.add("}\n"); 535 return a; 536 } 537 538 @Override 539 public void visitMethodAttribute(final Attribute attr) { 540 visitAttribute(attr); 541 } 542 543 @Override 544 public void visitCode() { 545 text.add(name + ".visitCode();\n"); 546 } 547 548 @Override 549 public void visitFrame(final int type, final int nLocal, 550 final Object[] local, final int nStack, final Object[] stack) { 551 buf.setLength(0); 552 switch (type) { 553 case Opcodes.F_NEW: 554 case Opcodes.F_FULL: 555 declareFrameTypes(nLocal, local); 556 declareFrameTypes(nStack, stack); 557 if (type == Opcodes.F_NEW) { 558 buf.append(name).append(".visitFrame(Opcodes.F_NEW, "); 559 } else { 560 buf.append(name).append(".visitFrame(Opcodes.F_FULL, "); 561 } 562 buf.append(nLocal).append(", new Object[] {"); 563 appendFrameTypes(nLocal, local); 564 buf.append("}, ").append(nStack).append(", new Object[] {"); 565 appendFrameTypes(nStack, stack); 566 buf.append('}'); 567 break; 568 case Opcodes.F_APPEND: 569 declareFrameTypes(nLocal, local); 570 buf.append(name).append(".visitFrame(Opcodes.F_APPEND,") 571 .append(nLocal).append(", new Object[] {"); 572 appendFrameTypes(nLocal, local); 573 buf.append("}, 0, null"); 574 break; 575 case Opcodes.F_CHOP: 576 buf.append(name).append(".visitFrame(Opcodes.F_CHOP,") 577 .append(nLocal).append(", null, 0, null"); 578 break; 579 case Opcodes.F_SAME: 580 buf.append(name).append( 581 ".visitFrame(Opcodes.F_SAME, 0, null, 0, null"); 582 break; 583 case Opcodes.F_SAME1: 584 declareFrameTypes(1, stack); 585 buf.append(name).append( 586 ".visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"); 587 appendFrameTypes(1, stack); 588 buf.append('}'); 589 break; 590 } 591 buf.append(");\n"); 592 text.add(buf.toString()); 593 } 594 595 @Override 596 public void visitInsn(final int opcode) { 597 buf.setLength(0); 598 buf.append(name).append(".visitInsn(").append(OPCODES[opcode]) 599 .append(");\n"); 600 text.add(buf.toString()); 601 } 602 603 @Override 604 public void visitIntInsn(final int opcode, final int operand) { 605 buf.setLength(0); 606 buf.append(name) 607 .append(".visitIntInsn(") 608 .append(OPCODES[opcode]) 609 .append(", ") 610 .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer 611 .toString(operand)).append(");\n"); 612 text.add(buf.toString()); 613 } 614 615 @Override 616 public void visitVarInsn(final int opcode, final int var) { 617 buf.setLength(0); 618 buf.append(name).append(".visitVarInsn(").append(OPCODES[opcode]) 619 .append(", ").append(var).append(");\n"); 620 text.add(buf.toString()); 621 } 622 623 @Override 624 public void visitTypeInsn(final int opcode, final String type) { 625 buf.setLength(0); 626 buf.append(name).append(".visitTypeInsn(").append(OPCODES[opcode]) 627 .append(", "); 628 appendConstant(type); 629 buf.append(");\n"); 630 text.add(buf.toString()); 631 } 632 633 @Override 634 public void visitFieldInsn(final int opcode, final String owner, 635 final String name, final String desc) { 636 buf.setLength(0); 637 buf.append(this.name).append(".visitFieldInsn(") 638 .append(OPCODES[opcode]).append(", "); 639 appendConstant(owner); 640 buf.append(", "); 641 appendConstant(name); 642 buf.append(", "); 643 appendConstant(desc); 644 buf.append(");\n"); 645 text.add(buf.toString()); 646 } 647 648 @Deprecated 649 @Override 650 public void visitMethodInsn(final int opcode, final String owner, 651 final String name, final String desc) { 652 if (api >= Opcodes.ASM5) { 653 super.visitMethodInsn(opcode, owner, name, desc); 654 return; 655 } 656 doVisitMethodInsn(opcode, owner, name, desc, 657 opcode == Opcodes.INVOKEINTERFACE); 658 } 659 660 @Override 661 public void visitMethodInsn(final int opcode, final String owner, 662 final String name, final String desc, final boolean itf) { 663 if (api < Opcodes.ASM5) { 664 super.visitMethodInsn(opcode, owner, name, desc, itf); 665 return; 666 } 667 doVisitMethodInsn(opcode, owner, name, desc, itf); 668 } 669 670 private void doVisitMethodInsn(final int opcode, final String owner, 671 final String name, final String desc, final boolean itf) { 672 buf.setLength(0); 673 buf.append(this.name).append(".visitMethodInsn(") 674 .append(OPCODES[opcode]).append(", "); 675 appendConstant(owner); 676 buf.append(", "); 677 appendConstant(name); 678 buf.append(", "); 679 appendConstant(desc); 680 buf.append(", "); 681 buf.append(itf ? "true" : "false"); 682 buf.append(");\n"); 683 text.add(buf.toString()); 684 } 685 686 @Override 687 public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, 688 Object... bsmArgs) { 689 buf.setLength(0); 690 buf.append(this.name).append(".visitInvokeDynamicInsn("); 691 appendConstant(name); 692 buf.append(", "); 693 appendConstant(desc); 694 buf.append(", "); 695 appendConstant(bsm); 696 buf.append(", new Object[]{"); 697 for (int i = 0; i < bsmArgs.length; ++i) { 698 appendConstant(bsmArgs[i]); 699 if (i != bsmArgs.length - 1) { 700 buf.append(", "); 701 } 702 } 703 buf.append("});\n"); 704 text.add(buf.toString()); 705 } 706 707 @Override 708 public void visitJumpInsn(final int opcode, final Label label) { 709 buf.setLength(0); 710 declareLabel(label); 711 buf.append(name).append(".visitJumpInsn(").append(OPCODES[opcode]) 712 .append(", "); 713 appendLabel(label); 714 buf.append(");\n"); 715 text.add(buf.toString()); 716 } 717 718 @Override 719 public void visitLabel(final Label label) { 720 buf.setLength(0); 721 declareLabel(label); 722 buf.append(name).append(".visitLabel("); 723 appendLabel(label); 724 buf.append(");\n"); 725 text.add(buf.toString()); 726 } 727 728 @Override 729 public void visitLdcInsn(final Object cst) { 730 buf.setLength(0); 731 buf.append(name).append(".visitLdcInsn("); 732 appendConstant(cst); 733 buf.append(");\n"); 734 text.add(buf.toString()); 735 } 736 737 @Override 738 public void visitIincInsn(final int var, final int increment) { 739 buf.setLength(0); 740 buf.append(name).append(".visitIincInsn(").append(var).append(", ") 741 .append(increment).append(");\n"); 742 text.add(buf.toString()); 743 } 744 745 @Override 746 public void visitTableSwitchInsn(final int min, final int max, 747 final Label dflt, final Label... labels) { 748 buf.setLength(0); 749 for (int i = 0; i < labels.length; ++i) { 750 declareLabel(labels[i]); 751 } 752 declareLabel(dflt); 753 754 buf.append(name).append(".visitTableSwitchInsn(").append(min) 755 .append(", ").append(max).append(", "); 756 appendLabel(dflt); 757 buf.append(", new Label[] {"); 758 for (int i = 0; i < labels.length; ++i) { 759 buf.append(i == 0 ? " " : ", "); 760 appendLabel(labels[i]); 761 } 762 buf.append(" });\n"); 763 text.add(buf.toString()); 764 } 765 766 @Override 767 public void visitLookupSwitchInsn(final Label dflt, final int[] keys, 768 final Label[] labels) { 769 buf.setLength(0); 770 for (int i = 0; i < labels.length; ++i) { 771 declareLabel(labels[i]); 772 } 773 declareLabel(dflt); 774 775 buf.append(name).append(".visitLookupSwitchInsn("); 776 appendLabel(dflt); 777 buf.append(", new int[] {"); 778 for (int i = 0; i < keys.length; ++i) { 779 buf.append(i == 0 ? " " : ", ").append(keys[i]); 780 } 781 buf.append(" }, new Label[] {"); 782 for (int i = 0; i < labels.length; ++i) { 783 buf.append(i == 0 ? " " : ", "); 784 appendLabel(labels[i]); 785 } 786 buf.append(" });\n"); 787 text.add(buf.toString()); 788 } 789 790 @Override 791 public void visitMultiANewArrayInsn(final String desc, final int dims) { 792 buf.setLength(0); 793 buf.append(name).append(".visitMultiANewArrayInsn("); 794 appendConstant(desc); 795 buf.append(", ").append(dims).append(");\n"); 796 text.add(buf.toString()); 797 } 798 799 @Override 800 public ASMifier visitInsnAnnotation(final int typeRef, 801 final TypePath typePath, final String desc, final boolean visible) { 802 return visitTypeAnnotation("visitInsnAnnotation", typeRef, typePath, 803 desc, visible); 804 } 805 806 @Override 807 public void visitTryCatchBlock(final Label start, final Label end, 808 final Label handler, final String type) { 809 buf.setLength(0); 810 declareLabel(start); 811 declareLabel(end); 812 declareLabel(handler); 813 buf.append(name).append(".visitTryCatchBlock("); 814 appendLabel(start); 815 buf.append(", "); 816 appendLabel(end); 817 buf.append(", "); 818 appendLabel(handler); 819 buf.append(", "); 820 appendConstant(type); 821 buf.append(");\n"); 822 text.add(buf.toString()); 823 } 824 825 @Override 826 public ASMifier visitTryCatchAnnotation(final int typeRef, 827 final TypePath typePath, final String desc, final boolean visible) { 828 return visitTypeAnnotation("visitTryCatchAnnotation", typeRef, 829 typePath, desc, visible); 830 } 831 832 @Override 833 public void visitLocalVariable(final String name, final String desc, 834 final String signature, final Label start, final Label end, 835 final int index) { 836 buf.setLength(0); 837 buf.append(this.name).append(".visitLocalVariable("); 838 appendConstant(name); 839 buf.append(", "); 840 appendConstant(desc); 841 buf.append(", "); 842 appendConstant(signature); 843 buf.append(", "); 844 appendLabel(start); 845 buf.append(", "); 846 appendLabel(end); 847 buf.append(", ").append(index).append(");\n"); 848 text.add(buf.toString()); 849 } 850 851 @Override 852 public Printer visitLocalVariableAnnotation(int typeRef, TypePath typePath, 853 Label[] start, Label[] end, int[] index, String desc, 854 boolean visible) { 855 buf.setLength(0); 856 buf.append("{\n").append("av0 = ").append(name) 857 .append(".visitLocalVariableAnnotation("); 858 buf.append(typeRef); 859 if (typePath == null) { 860 buf.append(", null, "); 861 } else { 862 buf.append(", TypePath.fromString(\"").append(typePath).append("\"), "); 863 } 864 buf.append("new Label[] {"); 865 for (int i = 0; i < start.length; ++i) { 866 buf.append(i == 0 ? " " : ", "); 867 appendLabel(start[i]); 868 } 869 buf.append(" }, new Label[] {"); 870 for (int i = 0; i < end.length; ++i) { 871 buf.append(i == 0 ? " " : ", "); 872 appendLabel(end[i]); 873 } 874 buf.append(" }, new int[] {"); 875 for (int i = 0; i < index.length; ++i) { 876 buf.append(i == 0 ? " " : ", ").append(index[i]); 877 } 878 buf.append(" }, "); 879 appendConstant(desc); 880 buf.append(", ").append(visible).append(");\n"); 881 text.add(buf.toString()); 882 ASMifier a = createASMifier("av", 0); 883 text.add(a.getText()); 884 text.add("}\n"); 885 return a; 886 } 887 888 @Override 889 public void visitLineNumber(final int line, final Label start) { 890 buf.setLength(0); 891 buf.append(name).append(".visitLineNumber(").append(line).append(", "); 892 appendLabel(start); 893 buf.append(");\n"); 894 text.add(buf.toString()); 895 } 896 897 @Override 898 public void visitMaxs(final int maxStack, final int maxLocals) { 899 buf.setLength(0); 900 buf.append(name).append(".visitMaxs(").append(maxStack).append(", ") 901 .append(maxLocals).append(");\n"); 902 text.add(buf.toString()); 903 } 904 905 @Override 906 public void visitMethodEnd() { 907 buf.setLength(0); 908 buf.append(name).append(".visitEnd();\n"); 909 text.add(buf.toString()); 910 } 911 912 // ------------------------------------------------------------------------ 913 // Common methods 914 // ------------------------------------------------------------------------ 915 916 public ASMifier visitAnnotation(final String desc, final boolean visible) { 917 buf.setLength(0); 918 buf.append("{\n").append("av0 = ").append(name) 919 .append(".visitAnnotation("); 920 appendConstant(desc); 921 buf.append(", ").append(visible).append(");\n"); 922 text.add(buf.toString()); 923 ASMifier a = createASMifier("av", 0); 924 text.add(a.getText()); 925 text.add("}\n"); 926 return a; 927 } 928 929 public ASMifier visitTypeAnnotation(final int typeRef, 930 final TypePath typePath, final String desc, final boolean visible) { 931 return visitTypeAnnotation("visitTypeAnnotation", typeRef, typePath, 932 desc, visible); 933 } 934 935 public ASMifier visitTypeAnnotation(final String method, final int typeRef, 936 final TypePath typePath, final String desc, final boolean visible) { 937 buf.setLength(0); 938 buf.append("{\n").append("av0 = ").append(name).append(".") 939 .append(method).append("("); 940 buf.append(typeRef); 941 if (typePath == null) { 942 buf.append(", null, "); 943 } else { 944 buf.append(", TypePath.fromString(\"").append(typePath).append("\"), "); 945 } 946 appendConstant(desc); 947 buf.append(", ").append(visible).append(");\n"); 948 text.add(buf.toString()); 949 ASMifier a = createASMifier("av", 0); 950 text.add(a.getText()); 951 text.add("}\n"); 952 return a; 953 } 954 955 public void visitAttribute(final Attribute attr) { 956 buf.setLength(0); 957 buf.append("// ATTRIBUTE ").append(attr.type).append('\n'); 958 if (attr instanceof ASMifiable) { 959 if (labelNames == null) { 960 labelNames = new HashMap<Label, String>(); 961 } 962 buf.append("{\n"); 963 ((ASMifiable) attr).asmify(buf, "attr", labelNames); 964 buf.append(name).append(".visitAttribute(attr);\n"); 965 buf.append("}\n"); 966 } 967 text.add(buf.toString()); 968 } 969 970 // ------------------------------------------------------------------------ 971 // Utility methods 972 // ------------------------------------------------------------------------ 973 974 protected ASMifier createASMifier(final String name, final int id) { 975 return new ASMifier(Opcodes.ASM5, name, id); 976 } 977 978 /** 979 * Appends a string representation of the given access modifiers to 980 * {@link #buf buf}. 981 * 982 * @param access 983 * some access modifiers. 984 */ 985 void appendAccess(final int access) { 986 boolean first = true; 987 if ((access & Opcodes.ACC_PUBLIC) != 0) { 988 buf.append("ACC_PUBLIC"); 989 first = false; 990 } 991 if ((access & Opcodes.ACC_PRIVATE) != 0) { 992 buf.append("ACC_PRIVATE"); 993 first = false; 994 } 995 if ((access & Opcodes.ACC_PROTECTED) != 0) { 996 buf.append("ACC_PROTECTED"); 997 first = false; 998 } 999 if ((access & Opcodes.ACC_FINAL) != 0) { 1000 if (!first) { 1001 buf.append(" + "); 1002 } 1003 buf.append("ACC_FINAL"); 1004 first = false; 1005 } 1006 if ((access & Opcodes.ACC_STATIC) != 0) { 1007 if (!first) { 1008 buf.append(" + "); 1009 } 1010 buf.append("ACC_STATIC"); 1011 first = false; 1012 } 1013 if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) { 1014 if (!first) { 1015 buf.append(" + "); 1016 } 1017 if ((access & ACCESS_CLASS) == 0) { 1018 buf.append("ACC_SYNCHRONIZED"); 1019 } else { 1020 buf.append("ACC_SUPER"); 1021 } 1022 first = false; 1023 } 1024 if ((access & Opcodes.ACC_VOLATILE) != 0 1025 && (access & ACCESS_FIELD) != 0) { 1026 if (!first) { 1027 buf.append(" + "); 1028 } 1029 buf.append("ACC_VOLATILE"); 1030 first = false; 1031 } 1032 if ((access & Opcodes.ACC_BRIDGE) != 0 && (access & ACCESS_CLASS) == 0 1033 && (access & ACCESS_FIELD) == 0) { 1034 if (!first) { 1035 buf.append(" + "); 1036 } 1037 buf.append("ACC_BRIDGE"); 1038 first = false; 1039 } 1040 if ((access & Opcodes.ACC_VARARGS) != 0 && (access & ACCESS_CLASS) == 0 1041 && (access & ACCESS_FIELD) == 0) { 1042 if (!first) { 1043 buf.append(" + "); 1044 } 1045 buf.append("ACC_VARARGS"); 1046 first = false; 1047 } 1048 if ((access & Opcodes.ACC_TRANSIENT) != 0 1049 && (access & ACCESS_FIELD) != 0) { 1050 if (!first) { 1051 buf.append(" + "); 1052 } 1053 buf.append("ACC_TRANSIENT"); 1054 first = false; 1055 } 1056 if ((access & Opcodes.ACC_NATIVE) != 0 && (access & ACCESS_CLASS) == 0 1057 && (access & ACCESS_FIELD) == 0) { 1058 if (!first) { 1059 buf.append(" + "); 1060 } 1061 buf.append("ACC_NATIVE"); 1062 first = false; 1063 } 1064 if ((access & Opcodes.ACC_ENUM) != 0 1065 && ((access & ACCESS_CLASS) != 0 1066 || (access & ACCESS_FIELD) != 0 || (access & ACCESS_INNER) != 0)) { 1067 if (!first) { 1068 buf.append(" + "); 1069 } 1070 buf.append("ACC_ENUM"); 1071 first = false; 1072 } 1073 if ((access & Opcodes.ACC_ANNOTATION) != 0 1074 && ((access & ACCESS_CLASS) != 0 || (access & ACCESS_INNER) != 0)) { 1075 if (!first) { 1076 buf.append(" + "); 1077 } 1078 buf.append("ACC_ANNOTATION"); 1079 first = false; 1080 } 1081 if ((access & Opcodes.ACC_ABSTRACT) != 0) { 1082 if (!first) { 1083 buf.append(" + "); 1084 } 1085 buf.append("ACC_ABSTRACT"); 1086 first = false; 1087 } 1088 if ((access & Opcodes.ACC_INTERFACE) != 0) { 1089 if (!first) { 1090 buf.append(" + "); 1091 } 1092 buf.append("ACC_INTERFACE"); 1093 first = false; 1094 } 1095 if ((access & Opcodes.ACC_STRICT) != 0) { 1096 if (!first) { 1097 buf.append(" + "); 1098 } 1099 buf.append("ACC_STRICT"); 1100 first = false; 1101 } 1102 if ((access & Opcodes.ACC_SYNTHETIC) != 0) { 1103 if (!first) { 1104 buf.append(" + "); 1105 } 1106 buf.append("ACC_SYNTHETIC"); 1107 first = false; 1108 } 1109 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 1110 if (!first) { 1111 buf.append(" + "); 1112 } 1113 buf.append("ACC_DEPRECATED"); 1114 first = false; 1115 } 1116 if ((access & Opcodes.ACC_MANDATED) != 0) { 1117 if (!first) { 1118 buf.append(" + "); 1119 } 1120 buf.append("ACC_MANDATED"); 1121 first = false; 1122 } 1123 if (first) { 1124 buf.append('0'); 1125 } 1126 } 1127 1128 /** 1129 * Appends a string representation of the given constant to the given 1130 * buffer. 1131 * 1132 * @param cst 1133 * an {@link Integer}, {@link Float}, {@link Long}, 1134 * {@link Double} or {@link String} object. May be <tt>null</tt>. 1135 */ 1136 protected void appendConstant(final Object cst) { 1137 appendConstant(buf, cst); 1138 } 1139 1140 /** 1141 * Appends a string representation of the given constant to the given 1142 * buffer. 1143 * 1144 * @param buf 1145 * a string buffer. 1146 * @param cst 1147 * an {@link Integer}, {@link Float}, {@link Long}, 1148 * {@link Double} or {@link String} object. May be <tt>null</tt>. 1149 */ 1150 static void appendConstant(final StringBuffer buf, final Object cst) { 1151 if (cst == null) { 1152 buf.append("null"); 1153 } else if (cst instanceof String) { 1154 appendString(buf, (String) cst); 1155 } else if (cst instanceof Type) { 1156 buf.append("Type.getType(\""); 1157 buf.append(((Type) cst).getDescriptor()); 1158 buf.append("\")"); 1159 } else if (cst instanceof Handle) { 1160 buf.append("new Handle("); 1161 Handle h = (Handle) cst; 1162 buf.append("Opcodes.").append(HANDLE_TAG[h.getTag()]) 1163 .append(", \""); 1164 buf.append(h.getOwner()).append("\", \""); 1165 buf.append(h.getName()).append("\", \""); 1166 buf.append(h.getDesc()).append("\")"); 1167 } else if (cst instanceof Byte) { 1168 buf.append("new Byte((byte)").append(cst).append(')'); 1169 } else if (cst instanceof Boolean) { 1170 buf.append(((Boolean) cst).booleanValue() ? "Boolean.TRUE" 1171 : "Boolean.FALSE"); 1172 } else if (cst instanceof Short) { 1173 buf.append("new Short((short)").append(cst).append(')'); 1174 } else if (cst instanceof Character) { 1175 int c = ((Character) cst).charValue(); 1176 buf.append("new Character((char)").append(c).append(')'); 1177 } else if (cst instanceof Integer) { 1178 buf.append("new Integer(").append(cst).append(')'); 1179 } else if (cst instanceof Float) { 1180 buf.append("new Float(\"").append(cst).append("\")"); 1181 } else if (cst instanceof Long) { 1182 buf.append("new Long(").append(cst).append("L)"); 1183 } else if (cst instanceof Double) { 1184 buf.append("new Double(\"").append(cst).append("\")"); 1185 } else if (cst instanceof byte[]) { 1186 byte[] v = (byte[]) cst; 1187 buf.append("new byte[] {"); 1188 for (int i = 0; i < v.length; i++) { 1189 buf.append(i == 0 ? "" : ",").append(v[i]); 1190 } 1191 buf.append('}'); 1192 } else if (cst instanceof boolean[]) { 1193 boolean[] v = (boolean[]) cst; 1194 buf.append("new boolean[] {"); 1195 for (int i = 0; i < v.length; i++) { 1196 buf.append(i == 0 ? "" : ",").append(v[i]); 1197 } 1198 buf.append('}'); 1199 } else if (cst instanceof short[]) { 1200 short[] v = (short[]) cst; 1201 buf.append("new short[] {"); 1202 for (int i = 0; i < v.length; i++) { 1203 buf.append(i == 0 ? "" : ",").append("(short)").append(v[i]); 1204 } 1205 buf.append('}'); 1206 } else if (cst instanceof char[]) { 1207 char[] v = (char[]) cst; 1208 buf.append("new char[] {"); 1209 for (int i = 0; i < v.length; i++) { 1210 buf.append(i == 0 ? "" : ",").append("(char)") 1211 .append((int) v[i]); 1212 } 1213 buf.append('}'); 1214 } else if (cst instanceof int[]) { 1215 int[] v = (int[]) cst; 1216 buf.append("new int[] {"); 1217 for (int i = 0; i < v.length; i++) { 1218 buf.append(i == 0 ? "" : ",").append(v[i]); 1219 } 1220 buf.append('}'); 1221 } else if (cst instanceof long[]) { 1222 long[] v = (long[]) cst; 1223 buf.append("new long[] {"); 1224 for (int i = 0; i < v.length; i++) { 1225 buf.append(i == 0 ? "" : ",").append(v[i]).append('L'); 1226 } 1227 buf.append('}'); 1228 } else if (cst instanceof float[]) { 1229 float[] v = (float[]) cst; 1230 buf.append("new float[] {"); 1231 for (int i = 0; i < v.length; i++) { 1232 buf.append(i == 0 ? "" : ",").append(v[i]).append('f'); 1233 } 1234 buf.append('}'); 1235 } else if (cst instanceof double[]) { 1236 double[] v = (double[]) cst; 1237 buf.append("new double[] {"); 1238 for (int i = 0; i < v.length; i++) { 1239 buf.append(i == 0 ? "" : ",").append(v[i]).append('d'); 1240 } 1241 buf.append('}'); 1242 } 1243 } 1244 1245 private void declareFrameTypes(final int n, final Object[] o) { 1246 for (int i = 0; i < n; ++i) { 1247 if (o[i] instanceof Label) { 1248 declareLabel((Label) o[i]); 1249 } 1250 } 1251 } 1252 1253 private void appendFrameTypes(final int n, final Object[] o) { 1254 for (int i = 0; i < n; ++i) { 1255 if (i > 0) { 1256 buf.append(", "); 1257 } 1258 if (o[i] instanceof String) { 1259 appendConstant(o[i]); 1260 } else if (o[i] instanceof Integer) { 1261 switch (((Integer) o[i]).intValue()) { 1262 case 0: 1263 buf.append("Opcodes.TOP"); 1264 break; 1265 case 1: 1266 buf.append("Opcodes.INTEGER"); 1267 break; 1268 case 2: 1269 buf.append("Opcodes.FLOAT"); 1270 break; 1271 case 3: 1272 buf.append("Opcodes.DOUBLE"); 1273 break; 1274 case 4: 1275 buf.append("Opcodes.LONG"); 1276 break; 1277 case 5: 1278 buf.append("Opcodes.NULL"); 1279 break; 1280 case 6: 1281 buf.append("Opcodes.UNINITIALIZED_THIS"); 1282 break; 1283 } 1284 } else { 1285 appendLabel((Label) o[i]); 1286 } 1287 } 1288 } 1289 1290 /** 1291 * Appends a declaration of the given label to {@link #buf buf}. This 1292 * declaration is of the form "Label lXXX = new Label();". Does nothing if 1293 * the given label has already been declared. 1294 * 1295 * @param l 1296 * a label. 1297 */ 1298 protected void declareLabel(final Label l) { 1299 if (labelNames == null) { 1300 labelNames = new HashMap<Label, String>(); 1301 } 1302 String name = labelNames.get(l); 1303 if (name == null) { 1304 name = "l" + labelNames.size(); 1305 labelNames.put(l, name); 1306 buf.append("Label ").append(name).append(" = new Label();\n"); 1307 } 1308 } 1309 1310 /** 1311 * Appends the name of the given label to {@link #buf buf}. The given label 1312 * <i>must</i> already have a name. One way to ensure this is to always call 1313 * {@link #declareLabel declared} before calling this method. 1314 * 1315 * @param l 1316 * a label. 1317 */ 1318 protected void appendLabel(final Label l) { 1319 buf.append(labelNames.get(l)); 1320 } 1321 } --- EOF ---