001/*** 002 * ASM: a very small and fast Java bytecode manipulation framework 003 * Copyright (c) 2000-2011 INRIA, France Telecom 004 * All rights reserved. 005 * 006 * Redistribution and use in source and binary forms, with or without 007 * modification, are permitted provided that the following conditions 008 * are met: 009 * 1. Redistributions of source code must retain the above copyright 010 * notice, this list of conditions and the following disclaimer. 011 * 2. Redistributions in binary form must reproduce the above copyright 012 * notice, this list of conditions and the following disclaimer in the 013 * documentation and/or other materials provided with the distribution. 014 * 3. Neither the name of the copyright holders nor the names of its 015 * contributors may be used to endorse or promote products derived from 016 * this software without specific prior written permission. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 028 * THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package io.ebean.enhance.asm.tree; 031 032import io.ebean.enhance.asm.MethodVisitor; 033 034import java.util.ArrayList; 035import java.util.List; 036import java.util.Map; 037 038/** 039 * A node that represents a bytecode instruction. <i>An instruction can appear 040 * at most once in at most one {@link InsnList} at a time</i>. 041 * 042 * @author Eric Bruneton 043 */ 044public abstract class AbstractInsnNode { 045 046 /** 047 * The type of {@link InsnNode} instructions. 048 */ 049 public static final int INSN = 0; 050 051 /** 052 * The type of {@link IntInsnNode} instructions. 053 */ 054 public static final int INT_INSN = 1; 055 056 /** 057 * The type of {@link VarInsnNode} instructions. 058 */ 059 public static final int VAR_INSN = 2; 060 061 /** 062 * The type of {@link TypeInsnNode} instructions. 063 */ 064 public static final int TYPE_INSN = 3; 065 066 /** 067 * The type of {@link FieldInsnNode} instructions. 068 */ 069 public static final int FIELD_INSN = 4; 070 071 /** 072 * The type of {@link MethodInsnNode} instructions. 073 */ 074 public static final int METHOD_INSN = 5; 075 076 /** 077 * The type of {@link InvokeDynamicInsnNode} instructions. 078 */ 079 public static final int INVOKE_DYNAMIC_INSN = 6; 080 081 /** 082 * The type of {@link JumpInsnNode} instructions. 083 */ 084 public static final int JUMP_INSN = 7; 085 086 /** 087 * The type of {@link LabelNode} "instructions". 088 */ 089 public static final int LABEL = 8; 090 091 /** 092 * The type of {@link LdcInsnNode} instructions. 093 */ 094 public static final int LDC_INSN = 9; 095 096 /** 097 * The type of {@link IincInsnNode} instructions. 098 */ 099 public static final int IINC_INSN = 10; 100 101 /** 102 * The type of {@link TableSwitchInsnNode} instructions. 103 */ 104 public static final int TABLESWITCH_INSN = 11; 105 106 /** 107 * The type of {@link LookupSwitchInsnNode} instructions. 108 */ 109 public static final int LOOKUPSWITCH_INSN = 12; 110 111 /** 112 * The type of {@link MultiANewArrayInsnNode} instructions. 113 */ 114 public static final int MULTIANEWARRAY_INSN = 13; 115 116 /** 117 * The type of {@link FrameNode} "instructions". 118 */ 119 public static final int FRAME = 14; 120 121 /** 122 * The type of {@link LineNumberNode} "instructions". 123 */ 124 public static final int LINE = 15; 125 126 /** 127 * The opcode of this instruction. 128 */ 129 protected int opcode; 130 131 /** 132 * The runtime visible type annotations of this instruction. This field is 133 * only used for real instructions (i.e. not for labels, frames, or line 134 * number nodes). This list is a list of {@link TypeAnnotationNode} objects. 135 * May be <tt>null</tt>. 136 * 137 * @associates org.objectweb.asm.tree.TypeAnnotationNode 138 * @label visible 139 */ 140 public List<TypeAnnotationNode> visibleTypeAnnotations; 141 142 /** 143 * The runtime invisible type annotations of this instruction. This field is 144 * only used for real instructions (i.e. not for labels, frames, or line 145 * number nodes). This list is a list of {@link TypeAnnotationNode} objects. 146 * May be <tt>null</tt>. 147 * 148 * @associates org.objectweb.asm.tree.TypeAnnotationNode 149 * @label invisible 150 */ 151 public List<TypeAnnotationNode> invisibleTypeAnnotations; 152 153 /** 154 * Previous instruction in the list to which this instruction belongs. 155 */ 156 AbstractInsnNode prev; 157 158 /** 159 * Next instruction in the list to which this instruction belongs. 160 */ 161 AbstractInsnNode next; 162 163 /** 164 * Index of this instruction in the list to which it belongs. The value of 165 * this field is correct only when {@link InsnList#cache} is not null. A 166 * value of -1 indicates that this instruction does not belong to any 167 * {@link InsnList}. 168 */ 169 int index; 170 171 /** 172 * Constructs a new {@link AbstractInsnNode}. 173 * 174 * @param opcode 175 * the opcode of the instruction to be constructed. 176 */ 177 protected AbstractInsnNode(final int opcode) { 178 this.opcode = opcode; 179 this.index = -1; 180 } 181 182 /** 183 * Returns the opcode of this instruction. 184 * 185 * @return the opcode of this instruction. 186 */ 187 public int getOpcode() { 188 return opcode; 189 } 190 191 /** 192 * Returns the type of this instruction. 193 * 194 * @return the type of this instruction, i.e. one the constants defined in 195 * this class. 196 */ 197 public abstract int getType(); 198 199 /** 200 * Returns the previous instruction in the list to which this instruction 201 * belongs, if any. 202 * 203 * @return the previous instruction in the list to which this instruction 204 * belongs, if any. May be <tt>null</tt>. 205 */ 206 public AbstractInsnNode getPrevious() { 207 return prev; 208 } 209 210 /** 211 * Returns the next instruction in the list to which this instruction 212 * belongs, if any. 213 * 214 * @return the next instruction in the list to which this instruction 215 * belongs, if any. May be <tt>null</tt>. 216 */ 217 public AbstractInsnNode getNext() { 218 return next; 219 } 220 221 /** 222 * Makes the given code visitor visit this instruction. 223 * 224 * @param cv 225 * a code visitor. 226 */ 227 public abstract void accept(final MethodVisitor cv); 228 229 /** 230 * Makes the given visitor visit the annotations of this instruction. 231 * 232 * @param mv 233 * a method visitor. 234 */ 235 protected final void acceptAnnotations(final MethodVisitor mv) { 236 int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations 237 .size(); 238 for (int i = 0; i < n; ++i) { 239 TypeAnnotationNode an = visibleTypeAnnotations.get(i); 240 an.accept(mv.visitInsnAnnotation(an.typeRef, an.typePath, an.desc, 241 true)); 242 } 243 n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations 244 .size(); 245 for (int i = 0; i < n; ++i) { 246 TypeAnnotationNode an = invisibleTypeAnnotations.get(i); 247 an.accept(mv.visitInsnAnnotation(an.typeRef, an.typePath, an.desc, 248 false)); 249 } 250 } 251 252 /** 253 * Returns a copy of this instruction. 254 * 255 * @param labels 256 * a map from LabelNodes to cloned LabelNodes. 257 * @return a copy of this instruction. The returned instruction does not 258 * belong to any {@link InsnList}. 259 */ 260 public abstract AbstractInsnNode clone( 261 final Map<LabelNode, LabelNode> labels); 262 263 /** 264 * Returns the clone of the given label. 265 * 266 * @param label 267 * a label. 268 * @param map 269 * a map from LabelNodes to cloned LabelNodes. 270 * @return the clone of the given label. 271 */ 272 static LabelNode clone(final LabelNode label, 273 final Map<LabelNode, LabelNode> map) { 274 return map.get(label); 275 } 276 277 /** 278 * Returns the clones of the given labels. 279 * 280 * @param labels 281 * a list of labels. 282 * @param map 283 * a map from LabelNodes to cloned LabelNodes. 284 * @return the clones of the given labels. 285 */ 286 static LabelNode[] clone(final List<LabelNode> labels, 287 final Map<LabelNode, LabelNode> map) { 288 LabelNode[] clones = new LabelNode[labels.size()]; 289 for (int i = 0; i < clones.length; ++i) { 290 clones[i] = map.get(labels.get(i)); 291 } 292 return clones; 293 } 294 295 /** 296 * Clones the annotations of the given instruction into this instruction. 297 * 298 * @param insn 299 * the source instruction. 300 * @return this instruction. 301 */ 302 protected final AbstractInsnNode cloneAnnotations( 303 final AbstractInsnNode insn) { 304 if (insn.visibleTypeAnnotations != null) { 305 this.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(); 306 for (int i = 0; i < insn.visibleTypeAnnotations.size(); ++i) { 307 TypeAnnotationNode src = insn.visibleTypeAnnotations.get(i); 308 TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef, 309 src.typePath, src.desc); 310 src.accept(ann); 311 this.visibleTypeAnnotations.add(ann); 312 } 313 } 314 if (insn.invisibleTypeAnnotations != null) { 315 this.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(); 316 for (int i = 0; i < insn.invisibleTypeAnnotations.size(); ++i) { 317 TypeAnnotationNode src = insn.invisibleTypeAnnotations.get(i); 318 TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef, 319 src.typePath, src.desc); 320 src.accept(ann); 321 this.invisibleTypeAnnotations.add(ann); 322 } 323 } 324 return this; 325 } 326}