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.tree;
60 
61 import java.util.ArrayList;
62 import java.util.List;
63 import java.util.Map;
64 
65 import jdk.internal.org.objectweb.asm.MethodVisitor;
66 
67 /**
68  * A node that represents a bytecode instruction. <i>An instruction can appear
69  * at most once in at most one {@link InsnList} at a time</i>.
70  *
71  * @author Eric Bruneton
72  */
73 public abstract class AbstractInsnNode {
74 
75     /**
76      * The type of {@link InsnNode} instructions.
77      */
78     public static final int INSN = 0;
79 
80     /**
81      * The type of {@link IntInsnNode} instructions.
82      */
83     public static final int INT_INSN = 1;
84 
85     /**
86      * The type of {@link VarInsnNode} instructions.
87      */
88     public static final int VAR_INSN = 2;
89 
90     /**
91      * The type of {@link TypeInsnNode} instructions.
92      */
93     public static final int TYPE_INSN = 3;
94 
95     /**
96      * The type of {@link FieldInsnNode} instructions.
97      */
98     public static final int FIELD_INSN = 4;
99 
100     /**
101      * The type of {@link MethodInsnNode} instructions.
102      */
103     public static final int METHOD_INSN = 5;
104 
105     /**
106      * The type of {@link InvokeDynamicInsnNode} instructions.
107      */
108     public static final int INVOKE_DYNAMIC_INSN = 6;
109 
110     /**
111      * The type of {@link JumpInsnNode} instructions.
112      */
113     public static final int JUMP_INSN = 7;
114 
115     /**
116      * The type of {@link LabelNode} "instructions".
117      */
118     public static final int LABEL = 8;
119 
120     /**
121      * The type of {@link LdcInsnNode} instructions.
122      */
123     public static final int LDC_INSN = 9;
124 
125     /**
126      * The type of {@link IincInsnNode} instructions.
127      */
128     public static final int IINC_INSN = 10;
129 
130     /**
131      * The type of {@link TableSwitchInsnNode} instructions.
132      */
133     public static final int TABLESWITCH_INSN = 11;
134 
135     /**
136      * The type of {@link LookupSwitchInsnNode} instructions.
137      */
138     public static final int LOOKUPSWITCH_INSN = 12;
139 
140     /**
141      * The type of {@link MultiANewArrayInsnNode} instructions.
142      */
143     public static final int MULTIANEWARRAY_INSN = 13;
144 
145     /**
146      * The type of {@link FrameNode} "instructions".
147      */
148     public static final int FRAME = 14;
149 
150     /**
151      * The type of {@link LineNumberNode} "instructions".
152      */
153     public static final int LINE = 15;
154 
155     /**
156      * The opcode of this instruction.
157      */
158     protected int opcode;
159 
160     /**
161      * The runtime visible type annotations of this instruction. This field is
162      * only used for real instructions (i.e. not for labels, frames, or line
163      * number nodes). This list is a list of {@link TypeAnnotationNode} objects.
164      * May be <tt>null</tt>.
165      *
166      * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode
167      * @label visible
168      */
169     public List<TypeAnnotationNode> visibleTypeAnnotations;
170 
171     /**
172      * The runtime invisible type annotations of this instruction. This field is
173      * only used for real instructions (i.e. not for labels, frames, or line
174      * number nodes). This list is a list of {@link TypeAnnotationNode} objects.
175      * May be <tt>null</tt>.
176      *
177      * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode
178      * @label invisible
179      */
180     public List<TypeAnnotationNode> invisibleTypeAnnotations;
181 
182     /**
183      * Previous instruction in the list to which this instruction belongs.
184      */
185     AbstractInsnNode prev;
186 
187     /**
188      * Next instruction in the list to which this instruction belongs.
189      */
190     AbstractInsnNode next;
191 
192     /**
193      * Index of this instruction in the list to which it belongs. The value of
194      * this field is correct only when {@link InsnList#cache} is not null. A
195      * value of -1 indicates that this instruction does not belong to any
196      * {@link InsnList}.
197      */
198     int index;
199 
200     /**
201      * Constructs a new {@link AbstractInsnNode}.
202      *
203      * @param opcode
204      *            the opcode of the instruction to be constructed.
205      */
AbstractInsnNode(final int opcode)206     protected AbstractInsnNode(final int opcode) {
207         this.opcode = opcode;
208         this.index = -1;
209     }
210 
211     /**
212      * Returns the opcode of this instruction.
213      *
214      * @return the opcode of this instruction.
215      */
getOpcode()216     public int getOpcode() {
217         return opcode;
218     }
219 
220     /**
221      * Returns the type of this instruction.
222      *
223      * @return the type of this instruction, i.e. one the constants defined in
224      *         this class.
225      */
getType()226     public abstract int getType();
227 
228     /**
229      * Returns the previous instruction in the list to which this instruction
230      * belongs, if any.
231      *
232      * @return the previous instruction in the list to which this instruction
233      *         belongs, if any. May be <tt>null</tt>.
234      */
getPrevious()235     public AbstractInsnNode getPrevious() {
236         return prev;
237     }
238 
239     /**
240      * Returns the next instruction in the list to which this instruction
241      * belongs, if any.
242      *
243      * @return the next instruction in the list to which this instruction
244      *         belongs, if any. May be <tt>null</tt>.
245      */
getNext()246     public AbstractInsnNode getNext() {
247         return next;
248     }
249 
250     /**
251      * Makes the given code visitor visit this instruction.
252      *
253      * @param cv
254      *            a code visitor.
255      */
accept(final MethodVisitor cv)256     public abstract void accept(final MethodVisitor cv);
257 
258     /**
259      * Makes the given visitor visit the annotations of this instruction.
260      *
261      * @param mv
262      *            a method visitor.
263      */
acceptAnnotations(final MethodVisitor mv)264     protected final void acceptAnnotations(final MethodVisitor mv) {
265         int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations
266                 .size();
267         for (int i = 0; i < n; ++i) {
268             TypeAnnotationNode an = visibleTypeAnnotations.get(i);
269             an.accept(mv.visitInsnAnnotation(an.typeRef, an.typePath, an.desc,
270                     true));
271         }
272         n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
273                 .size();
274         for (int i = 0; i < n; ++i) {
275             TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
276             an.accept(mv.visitInsnAnnotation(an.typeRef, an.typePath, an.desc,
277                     false));
278         }
279     }
280 
281     /**
282      * Returns a copy of this instruction.
283      *
284      * @param labels
285      *            a map from LabelNodes to cloned LabelNodes.
286      * @return a copy of this instruction. The returned instruction does not
287      *         belong to any {@link InsnList}.
288      */
clone( final Map<LabelNode, LabelNode> labels)289     public abstract AbstractInsnNode clone(
290             final Map<LabelNode, LabelNode> labels);
291 
292     /**
293      * Returns the clone of the given label.
294      *
295      * @param label
296      *            a label.
297      * @param map
298      *            a map from LabelNodes to cloned LabelNodes.
299      * @return the clone of the given label.
300      */
clone(final LabelNode label, final Map<LabelNode, LabelNode> map)301     static LabelNode clone(final LabelNode label,
302             final Map<LabelNode, LabelNode> map) {
303         return map.get(label);
304     }
305 
306     /**
307      * Returns the clones of the given labels.
308      *
309      * @param labels
310      *            a list of labels.
311      * @param map
312      *            a map from LabelNodes to cloned LabelNodes.
313      * @return the clones of the given labels.
314      */
clone(final List<LabelNode> labels, final Map<LabelNode, LabelNode> map)315     static LabelNode[] clone(final List<LabelNode> labels,
316             final Map<LabelNode, LabelNode> map) {
317         LabelNode[] clones = new LabelNode[labels.size()];
318         for (int i = 0; i < clones.length; ++i) {
319             clones[i] = map.get(labels.get(i));
320         }
321         return clones;
322     }
323 
324     /**
325      * Clones the annotations of the given instruction into this instruction.
326      *
327      * @param insn
328      *            the source instruction.
329      * @return this instruction.
330      */
cloneAnnotations( final AbstractInsnNode insn)331     protected final AbstractInsnNode cloneAnnotations(
332             final AbstractInsnNode insn) {
333         if (insn.visibleTypeAnnotations != null) {
334             this.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>();
335             for (int i = 0; i < insn.visibleTypeAnnotations.size(); ++i) {
336                 TypeAnnotationNode src = insn.visibleTypeAnnotations.get(i);
337                 TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef,
338                         src.typePath, src.desc);
339                 src.accept(ann);
340                 this.visibleTypeAnnotations.add(ann);
341             }
342         }
343         if (insn.invisibleTypeAnnotations != null) {
344             this.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>();
345             for (int i = 0; i < insn.invisibleTypeAnnotations.size(); ++i) {
346                 TypeAnnotationNode src = insn.invisibleTypeAnnotations.get(i);
347                 TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef,
348                         src.typePath, src.desc);
349                 src.accept(ann);
350                 this.invisibleTypeAnnotations.add(ann);
351             }
352         }
353         return this;
354     }
355 }
356