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