• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 import org.objectweb.asm.Opcodes;
35 
36 /**
37  * A node that represents a stack map frame. These nodes are pseudo instruction nodes in order to be
38  * inserted in an instruction list. In fact these nodes must(*) be inserted <i>just before</i> any
39  * instruction node <b>i</b> that follows an unconditionnal branch instruction such as GOTO or
40  * THROW, that is the target of a jump instruction, or that starts an exception handler block. The
41  * stack map frame types must describe the values of the local variables and of the operand stack
42  * elements <i>just before</i> <b>i</b> is executed. <br>
43  * <br>
44  * (*) this is mandatory only for classes whose version is greater than or equal to {@link
45  * Opcodes#V1_6}.
46  *
47  * @author Eric Bruneton
48  */
49 public class FrameNode extends AbstractInsnNode {
50 
51   /**
52    * The type of this frame. Must be {@link Opcodes#F_NEW} for expanded frames, or {@link
53    * Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
54    * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
55    */
56   public int type;
57 
58   /**
59    * The types of the local variables of this stack map frame. Elements of this list can be Integer,
60    * String or LabelNode objects (for primitive, reference and uninitialized types respectively -
61    * see {@link MethodVisitor}).
62    */
63   public List<Object> local;
64 
65   /**
66    * The types of the operand stack elements of this stack map frame. Elements of this list can be
67    * Integer, String or LabelNode objects (for primitive, reference and uninitialized types
68    * respectively - see {@link MethodVisitor}).
69    */
70   public List<Object> stack;
71 
FrameNode()72   private FrameNode() {
73     super(-1);
74   }
75 
76   /**
77    * Constructs a new {@link FrameNode}.
78    *
79    * @param type the type of this frame. Must be {@link Opcodes#F_NEW} for expanded frames, or
80    *     {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, {@link
81    *     Opcodes#F_SAME} or {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
82    * @param numLocal number of local variables of this stack map frame. Long and double values count
83    *     for one variable.
84    * @param local the types of the local variables of this stack map frame. Elements of this list
85    *     can be Integer, String or LabelNode objects (for primitive, reference and uninitialized
86    *     types respectively - see {@link MethodVisitor}). Long and double values are represented by
87    *     a single element.
88    * @param numStack number of operand stack elements of this stack map frame. Long and double
89    *     values count for one stack element.
90    * @param stack the types of the operand stack elements of this stack map frame. Elements of this
91    *     list can be Integer, String or LabelNode objects (for primitive, reference and
92    *     uninitialized types respectively - see {@link MethodVisitor}). Long and double values are
93    *     represented by a single element.
94    */
FrameNode( final int type, final int numLocal, final Object[] local, final int numStack, final Object[] stack)95   public FrameNode(
96       final int type,
97       final int numLocal,
98       final Object[] local,
99       final int numStack,
100       final Object[] stack) {
101     super(-1);
102     this.type = type;
103     switch (type) {
104       case Opcodes.F_NEW:
105       case Opcodes.F_FULL:
106         this.local = Util.asArrayList(numLocal, local);
107         this.stack = Util.asArrayList(numStack, stack);
108         break;
109       case Opcodes.F_APPEND:
110         this.local = Util.asArrayList(numLocal, local);
111         break;
112       case Opcodes.F_CHOP:
113         this.local = Util.asArrayList(numLocal);
114         break;
115       case Opcodes.F_SAME:
116         break;
117       case Opcodes.F_SAME1:
118         this.stack = Util.asArrayList(1, stack);
119         break;
120       default:
121         throw new IllegalArgumentException();
122     }
123   }
124 
125   @Override
getType()126   public int getType() {
127     return FRAME;
128   }
129 
130   @Override
accept(final MethodVisitor methodVisitor)131   public void accept(final MethodVisitor methodVisitor) {
132     switch (type) {
133       case Opcodes.F_NEW:
134       case Opcodes.F_FULL:
135         methodVisitor.visitFrame(type, local.size(), asArray(local), stack.size(), asArray(stack));
136         break;
137       case Opcodes.F_APPEND:
138         methodVisitor.visitFrame(type, local.size(), asArray(local), 0, null);
139         break;
140       case Opcodes.F_CHOP:
141         methodVisitor.visitFrame(type, local.size(), null, 0, null);
142         break;
143       case Opcodes.F_SAME:
144         methodVisitor.visitFrame(type, 0, null, 0, null);
145         break;
146       case Opcodes.F_SAME1:
147         methodVisitor.visitFrame(type, 0, null, 1, asArray(stack));
148         break;
149       default:
150         throw new IllegalArgumentException();
151     }
152   }
153 
154   @Override
clone(final Map<LabelNode, LabelNode> clonedLabels)155   public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
156     FrameNode clone = new FrameNode();
157     clone.type = type;
158     if (local != null) {
159       clone.local = new ArrayList<>();
160       for (int i = 0, n = local.size(); i < n; ++i) {
161         Object localElement = local.get(i);
162         if (localElement instanceof LabelNode) {
163           localElement = clonedLabels.get(localElement);
164         }
165         clone.local.add(localElement);
166       }
167     }
168     if (stack != null) {
169       clone.stack = new ArrayList<>();
170       for (int i = 0, n = stack.size(); i < n; ++i) {
171         Object stackElement = stack.get(i);
172         if (stackElement instanceof LabelNode) {
173           stackElement = clonedLabels.get(stackElement);
174         }
175         clone.stack.add(stackElement);
176       }
177     }
178     return clone;
179   }
180 
asArray(final List<Object> list)181   private static Object[] asArray(final List<Object> list) {
182     Object[] array = new Object[list.size()];
183     for (int i = 0, n = array.length; i < n; ++i) {
184       Object o = list.get(i);
185       if (o instanceof LabelNode) {
186         o = ((LabelNode) o).getLabel();
187       }
188       array[i] = o;
189     }
190     return array;
191   }
192 }
193