summaryrefslogtreecommitdiff
path: root/tools/external/asm/org/objectweb/asm/attrs/StackMapAttribute.java
diff options
context:
space:
mode:
Diffstat (limited to 'tools/external/asm/org/objectweb/asm/attrs/StackMapAttribute.java')
-rw-r--r--tools/external/asm/org/objectweb/asm/attrs/StackMapAttribute.java378
1 files changed, 378 insertions, 0 deletions
diff --git a/tools/external/asm/org/objectweb/asm/attrs/StackMapAttribute.java b/tools/external/asm/org/objectweb/asm/attrs/StackMapAttribute.java
new file mode 100644
index 000000000..4df2f7dde
--- /dev/null
+++ b/tools/external/asm/org/objectweb/asm/attrs/StackMapAttribute.java
@@ -0,0 +1,378 @@
+/**
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.attrs;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.ByteVector;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+
+/**
+ * StackMapAttribute is used by CDLC preverifier. Definition is given in
+ * appendix "CLDC Byte Code Typechecker Specification" from CDLC 1.1
+ * specification. <p> <i>Note that this implementation does not calculate
+ * StackMapFrame structures from the method bytecode. If method code is changed
+ * or generated from scratch, then developer is responsible to prepare a correct
+ * StackMapFrame structures.</i> <p> The format of the stack map in the class
+ * file is given below. In the following, <ul> <li>if the length of the
+ * method's byte code1 is 65535 or less, then <tt>uoffset</tt> represents the
+ * type u2; otherwise <tt>uoffset</tt> represents the type u4.</li> <li>If
+ * the maximum number of local variables for the method is 65535 or less, then
+ * <tt>ulocalvar</tt> represents the type u2; otherwise <tt>ulocalvar</tt>
+ * represents the type u4.</li> <li>If the maximum size of the operand stack
+ * is 65535 or less, then <tt>ustack</tt> represents the type u2; otherwise
+ * ustack represents the type u4.</li> </ul>
+ *
+ * <pre>
+ * stack_map { // attribute StackMap
+ * u2 attribute_name_index;
+ * u4 attribute_length
+ * uoffset number_of_entries;
+ * stack_map_frame entries[number_of_entries];
+ * }
+ * </pre>
+ *
+ * Each stack map frame has the following format:
+ *
+ * <pre>
+ * stack_map_frame {
+ * uoffset offset;
+ * ulocalvar number_of_locals;
+ * verification_type_info locals[number_of_locals];
+ * ustack number_of_stack_items;
+ * verification_type_info stack[number_of_stack_items];
+ * }
+ * </pre>
+ *
+ * The <tt>verification_type_info</tt> structure consists of a one-byte tag
+ * followed by zero or more bytes, giving more information about the tag. Each
+ * <tt>verification_type_info</tt> structure specifies the verification type
+ * of one or two locations.
+ *
+ * <pre>
+ * union verification_type_info {
+ * Top_variable_info;
+ * Integer_variable_info;
+ * Float_variable_info;
+ * Long_variable_info;
+ * Double_variable_info;
+ * Null_variable_info;
+ * UninitializedThis_variable_info;
+ * Object_variable_info;
+ * Uninitialized_variable_info;
+ * }
+ *
+ * Top_variable_info {
+ * u1 tag = ITEM_Top; // 0
+ * }
+ *
+ * Integer_variable_info {
+ * u1 tag = ITEM_Integer; // 1
+ * }
+ *
+ * Float_variable_info {
+ * u1 tag = ITEM_Float; // 2
+ * }
+ *
+ * Long_variable_info {
+ * u1 tag = ITEM_Long; // 4
+ * }
+ *
+ * Double_variable_info {
+ * u1 tag = ITEM_Double; // 3
+ * }
+ *
+ * Null_variable_info {
+ * u1 tag = ITEM_Null; // 5
+ * }
+ *
+ * UninitializedThis_variable_info {
+ * u1 tag = ITEM_UninitializedThis; // 6
+ * }
+ *
+ * Object_variable_info {
+ * u1 tag = ITEM_Object; // 7
+ * u2 cpool_index;
+ * }
+ *
+ * Uninitialized_variable_info {
+ * u1 tag = ITEM_Uninitialized // 8
+ * uoffset offset;
+ * }
+ * </pre>
+ *
+ * @see <a href="http://www.jcp.org/en/jsr/detail?id=139">JSR 139 : Connected
+ * Limited Device Configuration 1.1</a>
+ *
+ * @author Eugene Kuleshov
+ */
+public class StackMapAttribute extends Attribute {
+
+ static final int MAX_SIZE = 65535;
+
+ /**
+ * A List of <code>StackMapFrame</code> instances.
+ */
+ public List frames = new ArrayList();
+
+ public StackMapAttribute() {
+ super("StackMap");
+ }
+
+ public StackMapAttribute(List frames) {
+ this();
+ this.frames = frames;
+ }
+
+ public List getFrames() {
+ return frames;
+ }
+
+ public StackMapFrame getFrame(Label label) {
+ for (int i = 0; i < frames.size(); i++) {
+ StackMapFrame frame = (StackMapFrame) frames.get(i);
+ if (frame.label == label) {
+ return frame;
+ }
+ }
+ return null;
+ }
+
+ public boolean isUnknown() {
+ return false;
+ }
+
+ public boolean isCodeAttribute() {
+ return true;
+ }
+
+ protected Attribute read(
+ ClassReader cr,
+ int off,
+ int len,
+ char[] buf,
+ int codeOff,
+ Label[] labels)
+ {
+ StackMapAttribute attr = new StackMapAttribute();
+ // note that this is not the size of Code attribute
+ boolean isExtCodeSize = cr.readInt(codeOff + 4) > MAX_SIZE;
+ boolean isExtLocals = cr.readUnsignedShort(codeOff + 2) > MAX_SIZE;
+ boolean isExtStack = cr.readUnsignedShort(codeOff) > MAX_SIZE;
+
+ int size = 0;
+ if (isExtCodeSize) {
+ size = cr.readInt(off);
+ off += 4;
+ } else {
+ size = cr.readUnsignedShort(off);
+ off += 2;
+ }
+ for (int i = 0; i < size; i++) {
+ int offset;
+ if (isExtCodeSize) {
+ offset = cr.readInt(off);
+ off += 4;
+ } else {
+ offset = cr.readUnsignedShort(off);
+ off += 2;
+ }
+
+ Label label = getLabel(offset, labels);
+ List locals = new ArrayList();
+ List stack = new ArrayList();
+
+ off = readTypeInfo(cr,
+ off,
+ locals,
+ labels,
+ buf,
+ isExtLocals,
+ isExtCodeSize);
+ off = readTypeInfo(cr,
+ off,
+ stack,
+ labels,
+ buf,
+ isExtStack,
+ isExtCodeSize);
+
+ attr.frames.add(new StackMapFrame(label, locals, stack));
+ }
+ return attr;
+ }
+
+ private int readTypeInfo(
+ ClassReader cr,
+ int off,
+ List info,
+ Label[] labels,
+ char[] buf,
+ boolean isExt,
+ boolean isExtCode)
+ {
+ int n = 0;
+ if (isExt) {
+ n = cr.readInt(off);
+ off += 4;
+ } else {
+ n = cr.readUnsignedShort(off);
+ off += 2;
+ }
+ for (int j = 0; j < n; j++) {
+ int itemType = cr.readByte(off++);
+ StackMapType typeInfo = StackMapType.getTypeInfo(itemType);
+ info.add(typeInfo);
+ switch (itemType) {
+ case StackMapType.ITEM_Object: //
+ typeInfo.setObject(cr.readClass(off, buf));
+ off += 2;
+ break;
+ case StackMapType.ITEM_Uninitialized: //
+ int offset;
+ if (isExtCode) {
+ offset = cr.readInt(off);
+ off += 4;
+ } else {
+ offset = cr.readUnsignedShort(off);
+ off += 2;
+ }
+ typeInfo.setLabel(getLabel(offset, labels));
+ break;
+ }
+ }
+ return off;
+ }
+
+ private void writeTypeInfo(ByteVector bv, ClassWriter cw, List info, int max)
+ {
+ if (max > StackMapAttribute.MAX_SIZE) {
+ bv.putInt(info.size());
+ } else {
+ bv.putShort(info.size());
+ }
+ for (int j = 0; j < info.size(); j++) {
+ StackMapType typeInfo = (StackMapType) info.get(j);
+ bv.putByte(typeInfo.getType());
+ switch (typeInfo.getType()) {
+ case StackMapType.ITEM_Object: //
+ bv.putShort(cw.newClass(typeInfo.getObject()));
+ break;
+
+ case StackMapType.ITEM_Uninitialized: //
+ bv.putShort(typeInfo.getLabel().getOffset());
+ break;
+
+ }
+ }
+ }
+
+ private Label getLabel(int offset, Label[] labels) {
+ Label l = labels[offset];
+ if (l != null) {
+ return l;
+ }
+ return labels[offset] = new Label();
+ }
+
+ protected ByteVector write(
+ ClassWriter cw,
+ byte[] code,
+ int len,
+ int maxStack,
+ int maxLocals)
+ {
+ ByteVector bv = new ByteVector();
+ if (code != null && code.length > MAX_SIZE) { // TODO verify value
+ bv.putInt(frames.size());
+ } else {
+ bv.putShort(frames.size());
+ }
+ for (int i = 0; i < frames.size(); i++) {
+ writeFrame((StackMapFrame) frames.get(i),
+ cw,
+ maxStack,
+ maxLocals,
+ bv);
+ }
+ return bv;
+ }
+
+ protected Label[] getLabels() {
+ HashSet labels = new HashSet();
+ for (int i = 0; i < frames.size(); i++) {
+ getFrameLabels((StackMapFrame) frames.get(i), labels);
+ }
+ return (Label[]) labels.toArray(new Label[labels.size()]);
+ }
+
+ private void writeFrame(
+ StackMapFrame frame,
+ ClassWriter cw,
+ int maxStack,
+ int maxLocals,
+ ByteVector bv)
+ {
+ bv.putShort(frame.label.getOffset());
+ writeTypeInfo(bv, cw, frame.locals, maxLocals);
+ writeTypeInfo(bv, cw, frame.stack, maxStack);
+ }
+
+ private void getFrameLabels(StackMapFrame frame, Set labels) {
+ labels.add(frame.label);
+ getTypeInfoLabels(labels, frame.locals);
+ getTypeInfoLabels(labels, frame.stack);
+ }
+
+ private void getTypeInfoLabels(Set labels, List info) {
+ for (Iterator it = info.iterator(); it.hasNext();) {
+ StackMapType typeInfo = (StackMapType) it.next();
+ if (typeInfo.getType() == StackMapType.ITEM_Uninitialized) {
+ labels.add(typeInfo.getLabel());
+ }
+ }
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer("StackMap[");
+ for (int i = 0; i < frames.size(); i++) {
+ sb.append('\n').append('[').append(frames.get(i)).append(']');
+ }
+ sb.append("\n]");
+ return sb.toString();
+ }
+}