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