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}