001: /***
002: * ASM: a very small and fast Java bytecode manipulation framework
003: * Copyright (c) 2000-2005 INRIA, France Telecom
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: * 2. Redistributions in binary form must reproduce the above copyright
012: * notice, this list of conditions and the following disclaimer in the
013: * documentation and/or other materials provided with the distribution.
014: * 3. Neither the name of the copyright holders nor the names of its
015: * contributors may be used to endorse or promote products derived from
016: * this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028: * THE POSSIBILITY OF SUCH DAMAGE.
029: */package org.ejb3unit.asm.tree;
030:
031: import java.util.ArrayList;
032: import java.util.List;
033: import java.util.Map;
034:
035: import org.ejb3unit.asm.MethodVisitor;
036: import org.ejb3unit.asm.Opcodes;
037:
038: /**
039: * A node that represents a stack map frame. These nodes are pseudo instruction
040: * nodes in order to be inserted in an instruction list. In fact these nodes
041: * must(*) be inserted <i>just before</i> any instruction node <b>i</b> that
042: * follows an unconditionnal branch instruction such as GOTO or THROW, that is
043: * the target of a jump instruction, or that starts an exception handler block.
044: * The stack map frame types must describe the values of the local variables and
045: * of the operand stack elements <i>just before</i> <b>i</b> is executed. <br>
046: * <br> (*) this is mandatory only for classes whose version is greater than or
047: * equal to {@link Opcodes#V1_6 V1_6}.
048: *
049: * @author Eric Bruneton
050: */
051: public class FrameNode extends AbstractInsnNode {
052:
053: /**
054: * The type of this frame. Must be {@link Opcodes#F_NEW} for expanded
055: * frames, or {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
056: * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
057: * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
058: */
059: public int type;
060:
061: /**
062: * The types of the local variables of this stack map frame. Elements of
063: * this list can be Integer, String or LabelNode objects (for primitive,
064: * reference and uninitialized types respectively - see
065: * {@link MethodVisitor}).
066: */
067: public List local;
068:
069: /**
070: * The types of the operand stack elements of this stack map frame. Elements
071: * of this list can be Integer, String or LabelNode objects (for primitive,
072: * reference and uninitialized types respectively - see
073: * {@link MethodVisitor}).
074: */
075: public List stack;
076:
077: private FrameNode() {
078: super (-1);
079: }
080:
081: /**
082: * Constructs a new {@link FrameNode}.
083: *
084: * @param type the type of this frame. Must be {@link Opcodes#F_NEW} for
085: * expanded frames, or {@link Opcodes#F_FULL},
086: * {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP},
087: * {@link Opcodes#F_SAME} or {@link Opcodes#F_APPEND},
088: * {@link Opcodes#F_SAME1} for compressed frames.
089: * @param nLocal number of local variables of this stack map frame.
090: * @param local the types of the local variables of this stack map frame.
091: * Elements of this list can be Integer, String or LabelNode objects
092: * (for primitive, reference and uninitialized types respectively -
093: * see {@link MethodVisitor}).
094: * @param nStack number of operand stack elements of this stack map frame.
095: * @param stack the types of the operand stack elements of this stack map
096: * frame. Elements of this list can be Integer, String or LabelNode
097: * objects (for primitive, reference and uninitialized types
098: * respectively - see {@link MethodVisitor}).
099: */
100: public FrameNode(final int type, final int nLocal,
101: final Object[] local, final int nStack, final Object[] stack) {
102: super (-1);
103: this .type = type;
104: switch (type) {
105: case Opcodes.F_NEW:
106: case Opcodes.F_FULL:
107: this .local = asList(nLocal, local);
108: this .stack = asList(nStack, stack);
109: break;
110: case Opcodes.F_APPEND:
111: this .local = asList(nLocal, local);
112: break;
113: case Opcodes.F_CHOP:
114: this .local = asList(nLocal, new Object[nLocal]);
115: break;
116: case Opcodes.F_SAME:
117: break;
118: case Opcodes.F_SAME1:
119: this .stack = asList(1, stack);
120: break;
121: }
122: }
123:
124: public int getType() {
125: return FRAME;
126: }
127:
128: /**
129: * Makes the given visitor visit this stack map frame.
130: *
131: * @param mv a method visitor.
132: */
133: public void accept(final MethodVisitor mv) {
134: switch (type) {
135: case Opcodes.F_NEW:
136: case Opcodes.F_FULL:
137: mv.visitFrame(type, local.size(), asArray(local), stack
138: .size(), asArray(stack));
139: break;
140: case Opcodes.F_APPEND:
141: mv.visitFrame(type, local.size(), asArray(local), 0, null);
142: break;
143: case Opcodes.F_CHOP:
144: mv.visitFrame(type, local.size(), null, 0, null);
145: break;
146: case Opcodes.F_SAME:
147: mv.visitFrame(type, 0, null, 0, null);
148: break;
149: case Opcodes.F_SAME1:
150: mv.visitFrame(type, 0, null, 1, asArray(stack));
151: break;
152: }
153: }
154:
155: public AbstractInsnNode clone(final Map labels) {
156: FrameNode clone = new FrameNode();
157: clone.type = type;
158: if (local != null) {
159: clone.local = new ArrayList();
160: for (int i = 0; i < local.size(); ++i) {
161: Object l = local.get(i);
162: if (l instanceof LabelNode) {
163: l = labels.get(l);
164: }
165: clone.local.add(l);
166: }
167: }
168: if (stack != null) {
169: clone.stack = new ArrayList();
170: for (int i = 0; i < stack.size(); ++i) {
171: Object s = stack.get(i);
172: if (s instanceof LabelNode) {
173: s = labels.get(s);
174: }
175: clone.stack.add(s);
176: }
177: }
178: return clone;
179: }
180:
181: // ------------------------------------------------------------------------
182:
183: private static List asList(final int n, final Object[] o) {
184: List l = new ArrayList(n);
185: for (int i = 0; i < n; ++i) {
186: l.add(o[i]);
187: }
188: return l;
189: }
190:
191: private static Object[] asArray(final List l) {
192: Object[] objs = new Object[l.size()];
193: for (int i = 0; i < objs.length; ++i) {
194: Object o = l.get(i);
195: if (o instanceof LabelNode) {
196: o = ((LabelNode) o).getLabel();
197: }
198: objs[i] = o;
199: }
200: return objs;
201: }
202: }
|