1 /*** 2 * ASM: a very small and fast Java bytecode manipulation framework 3 * Copyright (c) 2000-2005 INRIA, France Telecom 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the copyright holders nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 package org.objectweb.asm.util; 31 32 import org.objectweb.asm.AnnotationVisitor; 33 import org.objectweb.asm.MethodVisitor; 34 import org.objectweb.asm.Label; 35 import org.objectweb.asm.Opcodes; 36 37 import java.util.HashMap; 38 39 /** 40 * A {@link MethodVisitor} that prints the ASM code that generates the methods 41 * it visits. 42 * 43 * @author Eric Bruneton 44 * @author Eugene Kuleshov 45 */ 46 public class ASMifierMethodVisitor extends ASMifierAbstractVisitor implements 47 MethodVisitor 48 { 49 50 /** 51 * Constructs a new {@link ASMifierMethodVisitor} object. 52 */ ASMifierMethodVisitor()53 public ASMifierMethodVisitor() { 54 super("mv"); 55 this.labelNames = new HashMap(); 56 } 57 visitAnnotationDefault()58 public AnnotationVisitor visitAnnotationDefault() { 59 buf.setLength(0); 60 buf.append("{\n").append("av0 = mv.visitAnnotationDefault();\n"); 61 text.add(buf.toString()); 62 ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0); 63 text.add(av.getText()); 64 text.add("}\n"); 65 return av; 66 } 67 visitParameterAnnotation( final int parameter, final String desc, final boolean visible)68 public AnnotationVisitor visitParameterAnnotation( 69 final int parameter, 70 final String desc, 71 final boolean visible) 72 { 73 buf.setLength(0); 74 buf.append("{\n") 75 .append("av0 = mv.visitParameterAnnotation(") 76 .append(parameter) 77 .append(", "); 78 appendConstant(desc); 79 buf.append(", ").append(visible).append(");\n"); 80 text.add(buf.toString()); 81 ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0); 82 text.add(av.getText()); 83 text.add("}\n"); 84 return av; 85 } 86 visitCode()87 public void visitCode() { 88 text.add("mv.visitCode();\n"); 89 } 90 visitInsn(final int opcode)91 public void visitInsn(final int opcode) { 92 buf.setLength(0); 93 buf.append("mv.visitInsn(").append(OPCODES[opcode]).append(");\n"); 94 text.add(buf.toString()); 95 } 96 visitIntInsn(final int opcode, final int operand)97 public void visitIntInsn(final int opcode, final int operand) { 98 buf.setLength(0); 99 buf.append("mv.visitIntInsn(") 100 .append(OPCODES[opcode]) 101 .append(", ") 102 .append(opcode == Opcodes.NEWARRAY 103 ? TYPES[operand] 104 : Integer.toString(operand)) 105 .append(");\n"); 106 text.add(buf.toString()); 107 } 108 visitVarInsn(final int opcode, final int var)109 public void visitVarInsn(final int opcode, final int var) { 110 buf.setLength(0); 111 buf.append("mv.visitVarInsn(") 112 .append(OPCODES[opcode]) 113 .append(", ") 114 .append(var) 115 .append(");\n"); 116 text.add(buf.toString()); 117 } 118 visitTypeInsn(final int opcode, final String desc)119 public void visitTypeInsn(final int opcode, final String desc) { 120 buf.setLength(0); 121 buf.append("mv.visitTypeInsn(").append(OPCODES[opcode]).append(", "); 122 appendConstant(desc); 123 buf.append(");\n"); 124 text.add(buf.toString()); 125 } 126 visitFieldInsn( final int opcode, final String owner, final String name, final String desc)127 public void visitFieldInsn( 128 final int opcode, 129 final String owner, 130 final String name, 131 final String desc) 132 { 133 buf.setLength(0); 134 buf.append("mv.visitFieldInsn(").append(OPCODES[opcode]).append(", "); 135 appendConstant(owner); 136 buf.append(", "); 137 appendConstant(name); 138 buf.append(", "); 139 appendConstant(desc); 140 buf.append(");\n"); 141 text.add(buf.toString()); 142 } 143 visitMethodInsn( final int opcode, final String owner, final String name, final String desc)144 public void visitMethodInsn( 145 final int opcode, 146 final String owner, 147 final String name, 148 final String desc) 149 { 150 buf.setLength(0); 151 buf.append("mv.visitMethodInsn(").append(OPCODES[opcode]).append(", "); 152 appendConstant(owner); 153 buf.append(", "); 154 appendConstant(name); 155 buf.append(", "); 156 appendConstant(desc); 157 buf.append(");\n"); 158 text.add(buf.toString()); 159 } 160 visitJumpInsn(final int opcode, final Label label)161 public void visitJumpInsn(final int opcode, final Label label) { 162 buf.setLength(0); 163 declareLabel(label); 164 buf.append("mv.visitJumpInsn(").append(OPCODES[opcode]).append(", "); 165 appendLabel(label); 166 buf.append(");\n"); 167 text.add(buf.toString()); 168 } 169 visitLabel(final Label label)170 public void visitLabel(final Label label) { 171 buf.setLength(0); 172 declareLabel(label); 173 buf.append("mv.visitLabel("); 174 appendLabel(label); 175 buf.append(");\n"); 176 text.add(buf.toString()); 177 } 178 visitLdcInsn(final Object cst)179 public void visitLdcInsn(final Object cst) { 180 buf.setLength(0); 181 buf.append("mv.visitLdcInsn("); 182 appendConstant(cst); 183 buf.append(");\n"); 184 text.add(buf.toString()); 185 } 186 visitIincInsn(final int var, final int increment)187 public void visitIincInsn(final int var, final int increment) { 188 buf.setLength(0); 189 buf.append("mv.visitIincInsn(") 190 .append(var) 191 .append(", ") 192 .append(increment) 193 .append(");\n"); 194 text.add(buf.toString()); 195 } 196 visitTableSwitchInsn( final int min, final int max, final Label dflt, final Label labels[])197 public void visitTableSwitchInsn( 198 final int min, 199 final int max, 200 final Label dflt, 201 final Label labels[]) 202 { 203 buf.setLength(0); 204 for (int i = 0; i < labels.length; ++i) { 205 declareLabel(labels[i]); 206 } 207 declareLabel(dflt); 208 209 buf.append("mv.visitTableSwitchInsn(") 210 .append(min) 211 .append(", ") 212 .append(max) 213 .append(", "); 214 appendLabel(dflt); 215 buf.append(", new Label[] {"); 216 for (int i = 0; i < labels.length; ++i) { 217 buf.append(i == 0 ? " " : ", "); 218 appendLabel(labels[i]); 219 } 220 buf.append(" });\n"); 221 text.add(buf.toString()); 222 } 223 visitLookupSwitchInsn( final Label dflt, final int keys[], final Label labels[])224 public void visitLookupSwitchInsn( 225 final Label dflt, 226 final int keys[], 227 final Label labels[]) 228 { 229 buf.setLength(0); 230 for (int i = 0; i < labels.length; ++i) { 231 declareLabel(labels[i]); 232 } 233 declareLabel(dflt); 234 235 buf.append("mv.visitLookupSwitchInsn("); 236 appendLabel(dflt); 237 buf.append(", new int[] {"); 238 for (int i = 0; i < keys.length; ++i) { 239 buf.append(i == 0 ? " " : ", ").append(keys[i]); 240 } 241 buf.append(" }, new Label[] {"); 242 for (int i = 0; i < labels.length; ++i) { 243 buf.append(i == 0 ? " " : ", "); 244 appendLabel(labels[i]); 245 } 246 buf.append(" });\n"); 247 text.add(buf.toString()); 248 } 249 visitMultiANewArrayInsn(final String desc, final int dims)250 public void visitMultiANewArrayInsn(final String desc, final int dims) { 251 buf.setLength(0); 252 buf.append("mv.visitMultiANewArrayInsn("); 253 appendConstant(desc); 254 buf.append(", ").append(dims).append(");\n"); 255 text.add(buf.toString()); 256 } 257 visitTryCatchBlock( final Label start, final Label end, final Label handler, final String type)258 public void visitTryCatchBlock( 259 final Label start, 260 final Label end, 261 final Label handler, 262 final String type) 263 { 264 buf.setLength(0); 265 declareLabel(start); 266 declareLabel(end); 267 declareLabel(handler); 268 buf.append("mv.visitTryCatchBlock("); 269 appendLabel(start); 270 buf.append(", "); 271 appendLabel(end); 272 buf.append(", "); 273 appendLabel(handler); 274 buf.append(", "); 275 appendConstant(type); 276 buf.append(");\n"); 277 text.add(buf.toString()); 278 } 279 visitLocalVariable( final String name, final String desc, final String signature, final Label start, final Label end, final int index)280 public void visitLocalVariable( 281 final String name, 282 final String desc, 283 final String signature, 284 final Label start, 285 final Label end, 286 final int index) 287 { 288 buf.setLength(0); 289 buf.append("mv.visitLocalVariable("); 290 appendConstant(name); 291 buf.append(", "); 292 appendConstant(desc); 293 buf.append(", "); 294 appendConstant(signature); 295 buf.append(", "); 296 appendLabel(start); 297 buf.append(", "); 298 appendLabel(end); 299 buf.append(", ").append(index).append(");\n"); 300 text.add(buf.toString()); 301 } 302 visitLineNumber(final int line, final Label start)303 public void visitLineNumber(final int line, final Label start) { 304 buf.setLength(0); 305 buf.append("mv.visitLineNumber(").append(line).append(", "); 306 appendLabel(start); 307 buf.append(");\n"); 308 text.add(buf.toString()); 309 } 310 visitMaxs(final int maxStack, final int maxLocals)311 public void visitMaxs(final int maxStack, final int maxLocals) { 312 buf.setLength(0); 313 buf.append("mv.visitMaxs(") 314 .append(maxStack) 315 .append(", ") 316 .append(maxLocals) 317 .append(");\n"); 318 text.add(buf.toString()); 319 } 320 321 /** 322 * Appends a declaration of the given label to {@link #buf buf}. This 323 * declaration is of the form "Label lXXX = new Label();". Does nothing if 324 * the given label has already been declared. 325 * 326 * @param l a label. 327 */ declareLabel(final Label l)328 private void declareLabel(final Label l) { 329 String name = (String) labelNames.get(l); 330 if (name == null) { 331 name = "l" + labelNames.size(); 332 labelNames.put(l, name); 333 buf.append("Label ").append(name).append(" = new Label();\n"); 334 } 335 } 336 337 /** 338 * Appends the name of the given label to {@link #buf buf}. The given label 339 * <i>must</i> already have a name. One way to ensure this is to always 340 * call {@link #declareLabel declared} before calling this method. 341 * 342 * @param l a label. 343 */ appendLabel(final Label l)344 private void appendLabel(final Label l) { 345 buf.append((String) labelNames.get(l)); 346 } 347 } 348