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.Arrays;
63 import java.util.List;
64 
65 import jdk.internal.org.objectweb.asm.AnnotationVisitor;
66 import jdk.internal.org.objectweb.asm.Attribute;
67 import jdk.internal.org.objectweb.asm.ClassVisitor;
68 import jdk.internal.org.objectweb.asm.Handle;
69 import jdk.internal.org.objectweb.asm.Label;
70 import jdk.internal.org.objectweb.asm.MethodVisitor;
71 import jdk.internal.org.objectweb.asm.Opcodes;
72 import jdk.internal.org.objectweb.asm.Type;
73 import jdk.internal.org.objectweb.asm.TypePath;
74 
75 /**
76  * A node that represents a method.
77  *
78  * @author Eric Bruneton
79  */
80 public class MethodNode extends MethodVisitor {
81 
82     /**
83      * The method's access flags (see {@link Opcodes}). This field also
84      * indicates if the method is synthetic and/or deprecated.
85      */
86     public int access;
87 
88     /**
89      * The method's name.
90      */
91     public String name;
92 
93     /**
94      * The method's descriptor (see {@link Type}).
95      */
96     public String desc;
97 
98     /**
99      * The method's signature. May be <tt>null</tt>.
100      */
101     public String signature;
102 
103     /**
104      * The internal names of the method's exception classes (see
105      * {@link Type#getInternalName() getInternalName}). This list is a list of
106      * {@link String} objects.
107      */
108     public List<String> exceptions;
109 
110     /**
111      * The method parameter info (access flags and name)
112      */
113     public List<ParameterNode> parameters;
114 
115     /**
116      * The runtime visible annotations of this method. This list is a list of
117      * {@link AnnotationNode} objects. May be <tt>null</tt>.
118      *
119      * @associates jdk.internal.org.objectweb.asm.tree.AnnotationNode
120      * @label visible
121      */
122     public List<AnnotationNode> visibleAnnotations;
123 
124     /**
125      * The runtime invisible annotations of this method. This list is a list of
126      * {@link AnnotationNode} objects. May be <tt>null</tt>.
127      *
128      * @associates jdk.internal.org.objectweb.asm.tree.AnnotationNode
129      * @label invisible
130      */
131     public List<AnnotationNode> invisibleAnnotations;
132 
133     /**
134      * The runtime visible type annotations of this method. This list is a list
135      * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
136      *
137      * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode
138      * @label visible
139      */
140     public List<TypeAnnotationNode> visibleTypeAnnotations;
141 
142     /**
143      * The runtime invisible type annotations of this method. This list is a
144      * list of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
145      *
146      * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode
147      * @label invisible
148      */
149     public List<TypeAnnotationNode> invisibleTypeAnnotations;
150 
151     /**
152      * The non standard attributes of this method. This list is a list of
153      * {@link Attribute} objects. May be <tt>null</tt>.
154      *
155      * @associates jdk.internal.org.objectweb.asm.Attribute
156      */
157     public List<Attribute> attrs;
158 
159     /**
160      * The default value of this annotation interface method. This field must be
161      * a {@link Byte}, {@link Boolean}, {@link Character}, {@link Short},
162      * {@link Integer}, {@link Long}, {@link Float}, {@link Double},
163      * {@link String} or {@link Type}, or an two elements String array (for
164      * enumeration values), a {@link AnnotationNode}, or a {@link List} of
165      * values of one of the preceding types. May be <tt>null</tt>.
166      */
167     public Object annotationDefault;
168 
169     /**
170      * The runtime visible parameter annotations of this method. These lists are
171      * lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
172      *
173      * @associates jdk.internal.org.objectweb.asm.tree.AnnotationNode
174      * @label invisible parameters
175      */
176     public List<AnnotationNode>[] visibleParameterAnnotations;
177 
178     /**
179      * The runtime invisible parameter annotations of this method. These lists
180      * are lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
181      *
182      * @associates jdk.internal.org.objectweb.asm.tree.AnnotationNode
183      * @label visible parameters
184      */
185     public List<AnnotationNode>[] invisibleParameterAnnotations;
186 
187     /**
188      * The instructions of this method. This list is a list of
189      * {@link AbstractInsnNode} objects.
190      *
191      * @associates jdk.internal.org.objectweb.asm.tree.AbstractInsnNode
192      * @label instructions
193      */
194     public InsnList instructions;
195 
196     /**
197      * The try catch blocks of this method. This list is a list of
198      * {@link TryCatchBlockNode} objects.
199      *
200      * @associates jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode
201      */
202     public List<TryCatchBlockNode> tryCatchBlocks;
203 
204     /**
205      * The maximum stack size of this method.
206      */
207     public int maxStack;
208 
209     /**
210      * The maximum number of local variables of this method.
211      */
212     public int maxLocals;
213 
214     /**
215      * The local variables of this method. This list is a list of
216      * {@link LocalVariableNode} objects. May be <tt>null</tt>
217      *
218      * @associates jdk.internal.org.objectweb.asm.tree.LocalVariableNode
219      */
220     public List<LocalVariableNode> localVariables;
221 
222     /**
223      * The visible local variable annotations of this method. This list is a
224      * list of {@link LocalVariableAnnotationNode} objects. May be <tt>null</tt>
225      *
226      * @associates jdk.internal.org.objectweb.asm.tree.LocalVariableAnnotationNode
227      */
228     public List<LocalVariableAnnotationNode> visibleLocalVariableAnnotations;
229 
230     /**
231      * The invisible local variable annotations of this method. This list is a
232      * list of {@link LocalVariableAnnotationNode} objects. May be <tt>null</tt>
233      *
234      * @associates jdk.internal.org.objectweb.asm.tree.LocalVariableAnnotationNode
235      */
236     public List<LocalVariableAnnotationNode> invisibleLocalVariableAnnotations;
237 
238     /**
239      * If the accept method has been called on this object.
240      */
241     private boolean visited;
242 
243     /**
244      * Constructs an uninitialized {@link MethodNode}. <i>Subclasses must not
245      * use this constructor</i>. Instead, they must use the
246      * {@link #MethodNode(int)} version.
247      *
248      * @throws IllegalStateException
249      *             If a subclass calls this constructor.
250      */
MethodNode()251     public MethodNode() {
252         this(Opcodes.ASM6);
253         if (getClass() != MethodNode.class) {
254             throw new IllegalStateException();
255         }
256     }
257 
258     /**
259      * Constructs an uninitialized {@link MethodNode}.
260      *
261      * @param api
262      *            the ASM API version implemented by this visitor. Must be one
263      *            of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
264      */
MethodNode(final int api)265     public MethodNode(final int api) {
266         super(api);
267         this.instructions = new InsnList();
268     }
269 
270     /**
271      * Constructs a new {@link MethodNode}. <i>Subclasses must not use this
272      * constructor</i>. Instead, they must use the
273      * {@link #MethodNode(int, int, String, String, String, String[])} version.
274      *
275      * @param access
276      *            the method's access flags (see {@link Opcodes}). This
277      *            parameter also indicates if the method is synthetic and/or
278      *            deprecated.
279      * @param name
280      *            the method's name.
281      * @param desc
282      *            the method's descriptor (see {@link Type}).
283      * @param signature
284      *            the method's signature. May be <tt>null</tt>.
285      * @param exceptions
286      *            the internal names of the method's exception classes (see
287      *            {@link Type#getInternalName() getInternalName}). May be
288      *            <tt>null</tt>.
289      * @throws IllegalStateException
290      *             If a subclass calls this constructor.
291      */
MethodNode(final int access, final String name, final String desc, final String signature, final String[] exceptions)292     public MethodNode(final int access, final String name, final String desc,
293             final String signature, final String[] exceptions) {
294         this(Opcodes.ASM6, access, name, desc, signature, exceptions);
295         if (getClass() != MethodNode.class) {
296             throw new IllegalStateException();
297         }
298     }
299 
300     /**
301      * Constructs a new {@link MethodNode}.
302      *
303      * @param api
304      *            the ASM API version implemented by this visitor. Must be one
305      *            of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
306      * @param access
307      *            the method's access flags (see {@link Opcodes}). This
308      *            parameter also indicates if the method is synthetic and/or
309      *            deprecated.
310      * @param name
311      *            the method's name.
312      * @param desc
313      *            the method's descriptor (see {@link Type}).
314      * @param signature
315      *            the method's signature. May be <tt>null</tt>.
316      * @param exceptions
317      *            the internal names of the method's exception classes (see
318      *            {@link Type#getInternalName() getInternalName}). May be
319      *            <tt>null</tt>.
320      */
MethodNode(final int api, final int access, final String name, final String desc, final String signature, final String[] exceptions)321     public MethodNode(final int api, final int access, final String name,
322             final String desc, final String signature, final String[] exceptions) {
323         super(api);
324         this.access = access;
325         this.name = name;
326         this.desc = desc;
327         this.signature = signature;
328         this.exceptions = new ArrayList<String>(exceptions == null ? 0
329                 : exceptions.length);
330         boolean isAbstract = (access & Opcodes.ACC_ABSTRACT) != 0;
331         if (!isAbstract) {
332             this.localVariables = new ArrayList<LocalVariableNode>(5);
333         }
334         this.tryCatchBlocks = new ArrayList<TryCatchBlockNode>();
335         if (exceptions != null) {
336             this.exceptions.addAll(Arrays.asList(exceptions));
337         }
338         this.instructions = new InsnList();
339     }
340 
341     // ------------------------------------------------------------------------
342     // Implementation of the MethodVisitor abstract class
343     // ------------------------------------------------------------------------
344 
345     @Override
visitParameter(String name, int access)346     public void visitParameter(String name, int access) {
347         if (parameters == null) {
348             parameters = new ArrayList<ParameterNode>(5);
349         }
350         parameters.add(new ParameterNode(name, access));
351     }
352 
353     @Override
354     @SuppressWarnings("serial")
visitAnnotationDefault()355     public AnnotationVisitor visitAnnotationDefault() {
356         return new AnnotationNode(new ArrayList<Object>(0) {
357             @Override
358             public boolean add(final Object o) {
359                 annotationDefault = o;
360                 return super.add(o);
361             }
362         });
363     }
364 
365     @Override
366     public AnnotationVisitor visitAnnotation(final String desc,
367             final boolean visible) {
368         AnnotationNode an = new AnnotationNode(desc);
369         if (visible) {
370             if (visibleAnnotations == null) {
371                 visibleAnnotations = new ArrayList<AnnotationNode>(1);
372             }
373             visibleAnnotations.add(an);
374         } else {
375             if (invisibleAnnotations == null) {
376                 invisibleAnnotations = new ArrayList<AnnotationNode>(1);
377             }
378             invisibleAnnotations.add(an);
379         }
380         return an;
381     }
382 
383     @Override
384     public AnnotationVisitor visitTypeAnnotation(int typeRef,
385             TypePath typePath, String desc, boolean visible) {
386         TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
387         if (visible) {
388             if (visibleTypeAnnotations == null) {
389                 visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
390             }
391             visibleTypeAnnotations.add(an);
392         } else {
393             if (invisibleTypeAnnotations == null) {
394                 invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
395             }
396             invisibleTypeAnnotations.add(an);
397         }
398         return an;
399     }
400 
401     @Override
402     @SuppressWarnings("unchecked")
403     public AnnotationVisitor visitParameterAnnotation(final int parameter,
404             final String desc, final boolean visible) {
405         AnnotationNode an = new AnnotationNode(desc);
406         if (visible) {
407             if (visibleParameterAnnotations == null) {
408                 int params = Type.getArgumentTypes(this.desc).length;
409                 visibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
410             }
411             if (visibleParameterAnnotations[parameter] == null) {
412                 visibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(
413                         1);
414             }
415             visibleParameterAnnotations[parameter].add(an);
416         } else {
417             if (invisibleParameterAnnotations == null) {
418                 int params = Type.getArgumentTypes(this.desc).length;
419                 invisibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
420             }
421             if (invisibleParameterAnnotations[parameter] == null) {
422                 invisibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(
423                         1);
424             }
425             invisibleParameterAnnotations[parameter].add(an);
426         }
427         return an;
428     }
429 
430     @Override
431     public void visitAttribute(final Attribute attr) {
432         if (attrs == null) {
433             attrs = new ArrayList<Attribute>(1);
434         }
435         attrs.add(attr);
436     }
437 
438     @Override
439     public void visitCode() {
440     }
441 
442     @Override
443     public void visitFrame(final int type, final int nLocal,
444             final Object[] local, final int nStack, final Object[] stack) {
445         instructions.add(new FrameNode(type, nLocal, local == null ? null
446                 : getLabelNodes(local), nStack, stack == null ? null
447                 : getLabelNodes(stack)));
448     }
449 
450     @Override
451     public void visitInsn(final int opcode) {
452         instructions.add(new InsnNode(opcode));
453     }
454 
455     @Override
456     public void visitIntInsn(final int opcode, final int operand) {
457         instructions.add(new IntInsnNode(opcode, operand));
458     }
459 
460     @Override
461     public void visitVarInsn(final int opcode, final int var) {
462         instructions.add(new VarInsnNode(opcode, var));
463     }
464 
465     @Override
466     public void visitTypeInsn(final int opcode, final String type) {
467         instructions.add(new TypeInsnNode(opcode, type));
468     }
469 
470     @Override
471     public void visitFieldInsn(final int opcode, final String owner,
472             final String name, final String desc) {
473         instructions.add(new FieldInsnNode(opcode, owner, name, desc));
474     }
475 
476     @Deprecated
477     @Override
478     public void visitMethodInsn(int opcode, String owner, String name,
479             String desc) {
480         if (api >= Opcodes.ASM5) {
481             super.visitMethodInsn(opcode, owner, name, desc);
482             return;
483         }
484         instructions.add(new MethodInsnNode(opcode, owner, name, desc));
485     }
486 
487     @Override
488     public void visitMethodInsn(int opcode, String owner, String name,
489             String desc, boolean itf) {
490         if (api < Opcodes.ASM5) {
491             super.visitMethodInsn(opcode, owner, name, desc, itf);
492             return;
493         }
494         instructions.add(new MethodInsnNode(opcode, owner, name, desc, itf));
495     }
496 
497     @Override
498     public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
499             Object... bsmArgs) {
500         instructions.add(new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs));
501     }
502 
503     @Override
504     public void visitJumpInsn(final int opcode, final Label label) {
505         instructions.add(new JumpInsnNode(opcode, getLabelNode(label)));
506     }
507 
508     @Override
509     public void visitLabel(final Label label) {
510         instructions.add(getLabelNode(label));
511     }
512 
513     @Override
514     public void visitLdcInsn(final Object cst) {
515         instructions.add(new LdcInsnNode(cst));
516     }
517 
518     @Override
519     public void visitIincInsn(final int var, final int increment) {
520         instructions.add(new IincInsnNode(var, increment));
521     }
522 
523     @Override
524     public void visitTableSwitchInsn(final int min, final int max,
525             final Label dflt, final Label... labels) {
526         instructions.add(new TableSwitchInsnNode(min, max, getLabelNode(dflt),
527                 getLabelNodes(labels)));
528     }
529 
530     @Override
531     public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
532             final Label[] labels) {
533         instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt), keys,
534                 getLabelNodes(labels)));
535     }
536 
537     @Override
538     public void visitMultiANewArrayInsn(final String desc, final int dims) {
539         instructions.add(new MultiANewArrayInsnNode(desc, dims));
540     }
541 
542     @Override
543     public AnnotationVisitor visitInsnAnnotation(int typeRef,
544             TypePath typePath, String desc, boolean visible) {
545         // Finds the last real instruction, i.e. the instruction targeted by
546         // this annotation.
547         AbstractInsnNode insn = instructions.getLast();
548         while (insn.getOpcode() == -1) {
549             insn = insn.getPrevious();
550         }
551         // Adds the annotation to this instruction.
552         TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
553         if (visible) {
554             if (insn.visibleTypeAnnotations == null) {
555                 insn.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
556                         1);
557             }
558             insn.visibleTypeAnnotations.add(an);
559         } else {
560             if (insn.invisibleTypeAnnotations == null) {
561                 insn.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
562                         1);
563             }
564             insn.invisibleTypeAnnotations.add(an);
565         }
566         return an;
567     }
568 
569     @Override
570     public void visitTryCatchBlock(final Label start, final Label end,
571             final Label handler, final String type) {
572         tryCatchBlocks.add(new TryCatchBlockNode(getLabelNode(start),
573                 getLabelNode(end), getLabelNode(handler), type));
574     }
575 
576     @Override
577     public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
578             TypePath typePath, String desc, boolean visible) {
579         TryCatchBlockNode tcb = tryCatchBlocks.get((typeRef & 0x00FFFF00) >> 8);
580         TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
581         if (visible) {
582             if (tcb.visibleTypeAnnotations == null) {
583                 tcb.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
584                         1);
585             }
586             tcb.visibleTypeAnnotations.add(an);
587         } else {
588             if (tcb.invisibleTypeAnnotations == null) {
589                 tcb.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
590                         1);
591             }
592             tcb.invisibleTypeAnnotations.add(an);
593         }
594         return an;
595     }
596 
597     @Override
598     public void visitLocalVariable(final String name, final String desc,
599             final String signature, final Label start, final Label end,
600             final int index) {
601         localVariables.add(new LocalVariableNode(name, desc, signature,
602                 getLabelNode(start), getLabelNode(end), index));
603     }
604 
605     @Override
606     public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
607             TypePath typePath, Label[] start, Label[] end, int[] index,
608             String desc, boolean visible) {
609         LocalVariableAnnotationNode an = new LocalVariableAnnotationNode(
610                 typeRef, typePath, getLabelNodes(start), getLabelNodes(end),
611                 index, desc);
612         if (visible) {
613             if (visibleLocalVariableAnnotations == null) {
614                 visibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>(
615                         1);
616             }
617             visibleLocalVariableAnnotations.add(an);
618         } else {
619             if (invisibleLocalVariableAnnotations == null) {
620                 invisibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>(
621                         1);
622             }
623             invisibleLocalVariableAnnotations.add(an);
624         }
625         return an;
626     }
627 
628     @Override
629     public void visitLineNumber(final int line, final Label start) {
630         instructions.add(new LineNumberNode(line, getLabelNode(start)));
631     }
632 
633     @Override
634     public void visitMaxs(final int maxStack, final int maxLocals) {
635         this.maxStack = maxStack;
636         this.maxLocals = maxLocals;
637     }
638 
639     @Override
640     public void visitEnd() {
641     }
642 
643     /**
644      * Returns the LabelNode corresponding to the given Label. Creates a new
645      * LabelNode if necessary. The default implementation of this method uses
646      * the {@link Label#info} field to store associations between labels and
647      * label nodes.
648      *
649      * @param l
650      *            a Label.
651      * @return the LabelNode corresponding to l.
652      */
653     protected LabelNode getLabelNode(final Label l) {
654         if (!(l.info instanceof LabelNode)) {
655             l.info = new LabelNode();
656         }
657         return (LabelNode) l.info;
658     }
659 
660     private LabelNode[] getLabelNodes(final Label[] l) {
661         LabelNode[] nodes = new LabelNode[l.length];
662         for (int i = 0; i < l.length; ++i) {
663             nodes[i] = getLabelNode(l[i]);
664         }
665         return nodes;
666     }
667 
668     private Object[] getLabelNodes(final Object[] objs) {
669         Object[] nodes = new Object[objs.length];
670         for (int i = 0; i < objs.length; ++i) {
671             Object o = objs[i];
672             if (o instanceof Label) {
673                 o = getLabelNode((Label) o);
674             }
675             nodes[i] = o;
676         }
677         return nodes;
678     }
679 
680     // ------------------------------------------------------------------------
681     // Accept method
682     // ------------------------------------------------------------------------
683 
684     /**
685      * Checks that this method node is compatible with the given ASM API
686      * version. This methods checks that this node, and all its nodes
687      * recursively, do not contain elements that were introduced in more recent
688      * versions of the ASM API than the given version.
689      *
690      * @param api
691      *            an ASM API version. Must be one of {@link Opcodes#ASM4},
692      *            {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
693      */
694     public void check(final int api) {
695         if (api == Opcodes.ASM4) {
696             if (visibleTypeAnnotations != null
697                     && visibleTypeAnnotations.size() > 0) {
698                 throw new RuntimeException();
699             }
700             if (invisibleTypeAnnotations != null
701                     && invisibleTypeAnnotations.size() > 0) {
702                 throw new RuntimeException();
703             }
704             int n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size();
705             for (int i = 0; i < n; ++i) {
706                 TryCatchBlockNode tcb = tryCatchBlocks.get(i);
707                 if (tcb.visibleTypeAnnotations != null
708                         && tcb.visibleTypeAnnotations.size() > 0) {
709                     throw new RuntimeException();
710                 }
711                 if (tcb.invisibleTypeAnnotations != null
712                         && tcb.invisibleTypeAnnotations.size() > 0) {
713                     throw new RuntimeException();
714                 }
715             }
716             for (int i = 0; i < instructions.size(); ++i) {
717                 AbstractInsnNode insn = instructions.get(i);
718                 if (insn.visibleTypeAnnotations != null
719                         && insn.visibleTypeAnnotations.size() > 0) {
720                     throw new RuntimeException();
721                 }
722                 if (insn.invisibleTypeAnnotations != null
723                         && insn.invisibleTypeAnnotations.size() > 0) {
724                     throw new RuntimeException();
725                 }
726                 if (insn instanceof MethodInsnNode) {
727                     boolean itf = ((MethodInsnNode) insn).itf;
728                     if (itf != (insn.opcode == Opcodes.INVOKEINTERFACE)) {
729                         throw new RuntimeException();
730                     }
731                 }
732             }
733             if (visibleLocalVariableAnnotations != null
734                     && visibleLocalVariableAnnotations.size() > 0) {
735                 throw new RuntimeException();
736             }
737             if (invisibleLocalVariableAnnotations != null
738                     && invisibleLocalVariableAnnotations.size() > 0) {
739                 throw new RuntimeException();
740             }
741         }
742     }
743 
744     /**
745      * Makes the given class visitor visit this method.
746      *
747      * @param cv
748      *            a class visitor.
749      */
750     public void accept(final ClassVisitor cv) {
751         String[] exceptions = new String[this.exceptions.size()];
752         this.exceptions.toArray(exceptions);
753         MethodVisitor mv = cv.visitMethod(access, name, desc, signature,
754                 exceptions);
755         if (mv != null) {
756             accept(mv);
757         }
758     }
759 
760     /**
761      * Makes the given method visitor visit this method.
762      *
763      * @param mv
764      *            a method visitor.
765      */
766     public void accept(final MethodVisitor mv) {
767         // visits the method parameters
768         int i, j, n;
769         n = parameters == null ? 0 : parameters.size();
770         for (i = 0; i < n; i++) {
771             ParameterNode parameter = parameters.get(i);
772             mv.visitParameter(parameter.name, parameter.access);
773         }
774         // visits the method attributes
775         if (annotationDefault != null) {
776             AnnotationVisitor av = mv.visitAnnotationDefault();
777             AnnotationNode.accept(av, null, annotationDefault);
778             if (av != null) {
779                 av.visitEnd();
780             }
781         }
782         n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
783         for (i = 0; i < n; ++i) {
784             AnnotationNode an = visibleAnnotations.get(i);
785             an.accept(mv.visitAnnotation(an.desc, true));
786         }
787         n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
788         for (i = 0; i < n; ++i) {
789             AnnotationNode an = invisibleAnnotations.get(i);
790             an.accept(mv.visitAnnotation(an.desc, false));
791         }
792         n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
793         for (i = 0; i < n; ++i) {
794             TypeAnnotationNode an = visibleTypeAnnotations.get(i);
795             an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
796                     true));
797         }
798         n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
799                 .size();
800         for (i = 0; i < n; ++i) {
801             TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
802             an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
803                     false));
804         }
805         n = visibleParameterAnnotations == null ? 0
806                 : visibleParameterAnnotations.length;
807         for (i = 0; i < n; ++i) {
808             List<?> l = visibleParameterAnnotations[i];
809             if (l == null) {
810                 continue;
811             }
812             for (j = 0; j < l.size(); ++j) {
813                 AnnotationNode an = (AnnotationNode) l.get(j);
814                 an.accept(mv.visitParameterAnnotation(i, an.desc, true));
815             }
816         }
817         n = invisibleParameterAnnotations == null ? 0
818                 : invisibleParameterAnnotations.length;
819         for (i = 0; i < n; ++i) {
820             List<?> l = invisibleParameterAnnotations[i];
821             if (l == null) {
822                 continue;
823             }
824             for (j = 0; j < l.size(); ++j) {
825                 AnnotationNode an = (AnnotationNode) l.get(j);
826                 an.accept(mv.visitParameterAnnotation(i, an.desc, false));
827             }
828         }
829         if (visited) {
830             instructions.resetLabels();
831         }
832         n = attrs == null ? 0 : attrs.size();
833         for (i = 0; i < n; ++i) {
834             mv.visitAttribute(attrs.get(i));
835         }
836         // visits the method's code
837         if (instructions.size() > 0) {
838             mv.visitCode();
839             // visits try catch blocks
840             n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size();
841             for (i = 0; i < n; ++i) {
842                 tryCatchBlocks.get(i).updateIndex(i);
843                 tryCatchBlocks.get(i).accept(mv);
844             }
845             // visits instructions
846             instructions.accept(mv);
847             // visits local variables
848             n = localVariables == null ? 0 : localVariables.size();
849             for (i = 0; i < n; ++i) {
850                 localVariables.get(i).accept(mv);
851             }
852             // visits local variable annotations
853             n = visibleLocalVariableAnnotations == null ? 0
854                     : visibleLocalVariableAnnotations.size();
855             for (i = 0; i < n; ++i) {
856                 visibleLocalVariableAnnotations.get(i).accept(mv, true);
857             }
858             n = invisibleLocalVariableAnnotations == null ? 0
859                     : invisibleLocalVariableAnnotations.size();
860             for (i = 0; i < n; ++i) {
861                 invisibleLocalVariableAnnotations.get(i).accept(mv, false);
862             }
863             // visits maxs
864             mv.visitMaxs(maxStack, maxLocals);
865             visited = true;
866         }
867         mv.visitEnd();
868     }
869 }
870