1 // ASM: a very small and fast Java bytecode manipulation framework 2 // Copyright (c) 2000-2011 INRIA, France Telecom 3 // All rights reserved. 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions 7 // are met: 8 // 1. Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // 2. Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // 3. Neither the name of the copyright holders nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 // THE POSSIBILITY OF SUCH DAMAGE. 28 package org.objectweb.asm.tree; 29 30 import java.util.ArrayList; 31 import java.util.List; 32 import java.util.Map; 33 import org.objectweb.asm.MethodVisitor; 34 35 /** 36 * A node that represents a bytecode instruction. <i>An instruction can appear at most once in at 37 * most one {@link InsnList} at a time</i>. 38 * 39 * @author Eric Bruneton 40 */ 41 public abstract class AbstractInsnNode { 42 43 /** The type of {@link InsnNode} instructions. */ 44 public static final int INSN = 0; 45 46 /** The type of {@link IntInsnNode} instructions. */ 47 public static final int INT_INSN = 1; 48 49 /** The type of {@link VarInsnNode} instructions. */ 50 public static final int VAR_INSN = 2; 51 52 /** The type of {@link TypeInsnNode} instructions. */ 53 public static final int TYPE_INSN = 3; 54 55 /** The type of {@link FieldInsnNode} instructions. */ 56 public static final int FIELD_INSN = 4; 57 58 /** The type of {@link MethodInsnNode} instructions. */ 59 public static final int METHOD_INSN = 5; 60 61 /** The type of {@link InvokeDynamicInsnNode} instructions. */ 62 public static final int INVOKE_DYNAMIC_INSN = 6; 63 64 /** The type of {@link JumpInsnNode} instructions. */ 65 public static final int JUMP_INSN = 7; 66 67 /** The type of {@link LabelNode} "instructions". */ 68 public static final int LABEL = 8; 69 70 /** The type of {@link LdcInsnNode} instructions. */ 71 public static final int LDC_INSN = 9; 72 73 /** The type of {@link IincInsnNode} instructions. */ 74 public static final int IINC_INSN = 10; 75 76 /** The type of {@link TableSwitchInsnNode} instructions. */ 77 public static final int TABLESWITCH_INSN = 11; 78 79 /** The type of {@link LookupSwitchInsnNode} instructions. */ 80 public static final int LOOKUPSWITCH_INSN = 12; 81 82 /** The type of {@link MultiANewArrayInsnNode} instructions. */ 83 public static final int MULTIANEWARRAY_INSN = 13; 84 85 /** The type of {@link FrameNode} "instructions". */ 86 public static final int FRAME = 14; 87 88 /** The type of {@link LineNumberNode} "instructions". */ 89 public static final int LINE = 15; 90 91 /** 92 * The opcode of this instruction, or -1 if this is not a JVM instruction (e.g. a label or a line 93 * number). 94 */ 95 protected int opcode; 96 97 /** 98 * The runtime visible type annotations of this instruction. This field is only used for real 99 * instructions (i.e. not for labels, frames, or line number nodes). This list is a list of {@link 100 * TypeAnnotationNode} objects. May be {@literal null}. 101 */ 102 public List<TypeAnnotationNode> visibleTypeAnnotations; 103 104 /** 105 * The runtime invisible type annotations of this instruction. This field is only used for real 106 * instructions (i.e. not for labels, frames, or line number nodes). This list is a list of {@link 107 * TypeAnnotationNode} objects. May be {@literal null}. 108 */ 109 public List<TypeAnnotationNode> invisibleTypeAnnotations; 110 111 /** The previous instruction in the list to which this instruction belongs. */ 112 AbstractInsnNode previousInsn; 113 114 /** The next instruction in the list to which this instruction belongs. */ 115 AbstractInsnNode nextInsn; 116 117 /** 118 * The index of this instruction in the list to which it belongs. The value of this field is 119 * correct only when {@link InsnList#cache} is not null. A value of -1 indicates that this 120 * instruction does not belong to any {@link InsnList}. 121 */ 122 int index; 123 124 /** 125 * Constructs a new {@link AbstractInsnNode}. 126 * 127 * @param opcode the opcode of the instruction to be constructed. 128 */ AbstractInsnNode(final int opcode)129 protected AbstractInsnNode(final int opcode) { 130 this.opcode = opcode; 131 this.index = -1; 132 } 133 134 /** 135 * Returns the opcode of this instruction. 136 * 137 * @return the opcode of this instruction, or -1 if this is not a JVM instruction (e.g. a label or 138 * a line number). 139 */ getOpcode()140 public int getOpcode() { 141 return opcode; 142 } 143 144 /** 145 * Returns the type of this instruction. 146 * 147 * @return the type of this instruction, i.e. one the constants defined in this class. 148 */ getType()149 public abstract int getType(); 150 151 /** 152 * Returns the previous instruction in the list to which this instruction belongs, if any. 153 * 154 * @return the previous instruction in the list to which this instruction belongs, if any. May be 155 * {@literal null}. 156 */ getPrevious()157 public AbstractInsnNode getPrevious() { 158 return previousInsn; 159 } 160 161 /** 162 * Returns the next instruction in the list to which this instruction belongs, if any. 163 * 164 * @return the next instruction in the list to which this instruction belongs, if any. May be 165 * {@literal null}. 166 */ getNext()167 public AbstractInsnNode getNext() { 168 return nextInsn; 169 } 170 171 /** 172 * Makes the given method visitor visit this instruction. 173 * 174 * @param methodVisitor a method visitor. 175 */ accept(MethodVisitor methodVisitor)176 public abstract void accept(MethodVisitor methodVisitor); 177 178 /** 179 * Makes the given visitor visit the annotations of this instruction. 180 * 181 * @param methodVisitor a method visitor. 182 */ acceptAnnotations(final MethodVisitor methodVisitor)183 protected final void acceptAnnotations(final MethodVisitor methodVisitor) { 184 if (visibleTypeAnnotations != null) { 185 for (int i = 0, n = visibleTypeAnnotations.size(); i < n; ++i) { 186 TypeAnnotationNode typeAnnotation = visibleTypeAnnotations.get(i); 187 typeAnnotation.accept( 188 methodVisitor.visitInsnAnnotation( 189 typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, true)); 190 } 191 } 192 if (invisibleTypeAnnotations != null) { 193 for (int i = 0, n = invisibleTypeAnnotations.size(); i < n; ++i) { 194 TypeAnnotationNode typeAnnotation = invisibleTypeAnnotations.get(i); 195 typeAnnotation.accept( 196 methodVisitor.visitInsnAnnotation( 197 typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, false)); 198 } 199 } 200 } 201 202 /** 203 * Returns a copy of this instruction. 204 * 205 * @param clonedLabels a map from LabelNodes to cloned LabelNodes. 206 * @return a copy of this instruction. The returned instruction does not belong to any {@link 207 * InsnList}. 208 */ clone(Map<LabelNode, LabelNode> clonedLabels)209 public abstract AbstractInsnNode clone(Map<LabelNode, LabelNode> clonedLabels); 210 211 /** 212 * Returns the clone of the given label. 213 * 214 * @param label a label. 215 * @param clonedLabels a map from LabelNodes to cloned LabelNodes. 216 * @return the clone of the given label. 217 */ clone(final LabelNode label, final Map<LabelNode, LabelNode> clonedLabels)218 static LabelNode clone(final LabelNode label, final Map<LabelNode, LabelNode> clonedLabels) { 219 return clonedLabels.get(label); 220 } 221 222 /** 223 * Returns the clones of the given labels. 224 * 225 * @param labels a list of labels. 226 * @param clonedLabels a map from LabelNodes to cloned LabelNodes. 227 * @return the clones of the given labels. 228 */ clone( final List<LabelNode> labels, final Map<LabelNode, LabelNode> clonedLabels)229 static LabelNode[] clone( 230 final List<LabelNode> labels, final Map<LabelNode, LabelNode> clonedLabels) { 231 LabelNode[] clones = new LabelNode[labels.size()]; 232 for (int i = 0, n = clones.length; i < n; ++i) { 233 clones[i] = clonedLabels.get(labels.get(i)); 234 } 235 return clones; 236 } 237 238 /** 239 * Clones the annotations of the given instruction into this instruction. 240 * 241 * @param insnNode the source instruction. 242 * @return this instruction. 243 */ cloneAnnotations(final AbstractInsnNode insnNode)244 protected final AbstractInsnNode cloneAnnotations(final AbstractInsnNode insnNode) { 245 if (insnNode.visibleTypeAnnotations != null) { 246 this.visibleTypeAnnotations = new ArrayList<>(); 247 for (int i = 0, n = insnNode.visibleTypeAnnotations.size(); i < n; ++i) { 248 TypeAnnotationNode sourceAnnotation = insnNode.visibleTypeAnnotations.get(i); 249 TypeAnnotationNode cloneAnnotation = 250 new TypeAnnotationNode( 251 sourceAnnotation.typeRef, sourceAnnotation.typePath, sourceAnnotation.desc); 252 sourceAnnotation.accept(cloneAnnotation); 253 this.visibleTypeAnnotations.add(cloneAnnotation); 254 } 255 } 256 if (insnNode.invisibleTypeAnnotations != null) { 257 this.invisibleTypeAnnotations = new ArrayList<>(); 258 for (int i = 0, n = insnNode.invisibleTypeAnnotations.size(); i < n; ++i) { 259 TypeAnnotationNode sourceAnnotation = insnNode.invisibleTypeAnnotations.get(i); 260 TypeAnnotationNode cloneAnnotation = 261 new TypeAnnotationNode( 262 sourceAnnotation.typeRef, sourceAnnotation.typePath, sourceAnnotation.desc); 263 sourceAnnotation.accept(cloneAnnotation); 264 this.invisibleTypeAnnotations.add(cloneAnnotation); 265 } 266 } 267 return this; 268 } 269 } 270