[clojure] 03/05: Removed third-party files
Daigo Moriwaki
daigo at moszumanska.debian.org
Sat Jun 14 06:09:07 UTC 2014
This is an automated email from the git hooks/post-receive script.
daigo pushed a commit to branch master
in repository clojure.
commit 0c1dab2298b6ee0931ab851d1210607fb633e496
Author: Daigo Moriwaki <daigo at debian.org>
Date: Sat Jun 14 10:13:16 2014 +0900
Removed third-party files
---
src/jvm/clojure/asm/AnnotationVisitor.java | 169 --
src/jvm/clojure/asm/AnnotationWriter.java | 318 ---
src/jvm/clojure/asm/Attribute.java | 255 --
src/jvm/clojure/asm/ByteVector.java | 306 ---
src/jvm/clojure/asm/ClassReader.java | 2202 ----------------
src/jvm/clojure/asm/ClassVisitor.java | 286 ---
src/jvm/clojure/asm/ClassWriter.java | 1693 ------------
src/jvm/clojure/asm/Context.java | 110 -
src/jvm/clojure/asm/Edge.java | 75 -
src/jvm/clojure/asm/FieldVisitor.java | 121 -
src/jvm/clojure/asm/FieldWriter.java | 273 --
src/jvm/clojure/asm/Frame.java | 1453 -----------
src/jvm/clojure/asm/Handle.java | 167 --
src/jvm/clojure/asm/Handler.java | 121 -
src/jvm/clojure/asm/Item.java | 311 ---
src/jvm/clojure/asm/Label.java | 560 ----
src/jvm/clojure/asm/MethodVisitor.java | 662 -----
src/jvm/clojure/asm/MethodWriter.java | 2685 --------------------
src/jvm/clojure/asm/Opcodes.java | 358 ---
src/jvm/clojure/asm/Type.java | 895 -------
src/jvm/clojure/asm/commons/AdviceAdapter.java | 625 -----
src/jvm/clojure/asm/commons/AnalyzerAdapter.java | 920 -------
src/jvm/clojure/asm/commons/CodeSizeEvaluator.java | 217 --
src/jvm/clojure/asm/commons/GeneratorAdapter.java | 1623 ------------
.../clojure/asm/commons/InstructionAdapter.java | 1090 --------
.../clojure/asm/commons/LocalVariablesSorter.java | 360 ---
src/jvm/clojure/asm/commons/Method.java | 282 --
.../clojure/asm/commons/SerialVersionUIDAdder.java | 533 ----
src/jvm/clojure/asm/commons/StaticInitMerger.java | 96 -
.../clojure/asm/commons/TableSwitchGenerator.java | 57 -
src/jvm/clojure/asm/commons/package.html | 48 -
src/jvm/clojure/asm/package.html | 87 -
32 files changed, 18958 deletions(-)
diff --git a/src/jvm/clojure/asm/AnnotationVisitor.java b/src/jvm/clojure/asm/AnnotationVisitor.java
deleted file mode 100644
index eb01145..0000000
--- a/src/jvm/clojure/asm/AnnotationVisitor.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-/**
- * A visitor to visit a Java annotation. The methods of this class must be
- * called in the following order: ( <tt>visit</tt> | <tt>visitEnum</tt> |
- * <tt>visitAnnotation</tt> | <tt>visitArray</tt> )* <tt>visitEnd</tt>.
- *
- * @author Eric Bruneton
- * @author Eugene Kuleshov
- */
-public abstract class AnnotationVisitor {
-
- /**
- * The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4}.
- */
- protected final int api;
-
- /**
- * The annotation visitor to which this visitor must delegate method calls.
- * May be null.
- */
- protected AnnotationVisitor av;
-
- /**
- * Constructs a new {@link AnnotationVisitor}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- */
- public AnnotationVisitor(final int api) {
- this(api, null);
- }
-
- /**
- * Constructs a new {@link AnnotationVisitor}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param av
- * the annotation visitor to which this visitor must delegate
- * method calls. May be null.
- */
- public AnnotationVisitor(final int api, final AnnotationVisitor av) {
- if (api != Opcodes.ASM4) {
- throw new IllegalArgumentException();
- }
- this.api = api;
- this.av = av;
- }
-
- /**
- * Visits a primitive value of the annotation.
- *
- * @param name
- * the value name.
- * @param value
- * the actual value, whose type must be {@link Byte},
- * {@link Boolean}, {@link Character}, {@link Short},
- * {@link Integer} , {@link Long}, {@link Float}, {@link Double},
- * {@link String} or {@link Type} or OBJECT or ARRAY sort. This
- * value can also be an array of byte, boolean, short, char, int,
- * long, float or double values (this is equivalent to using
- * {@link #visitArray visitArray} and visiting each array element
- * in turn, but is more convenient).
- */
- public void visit(String name, Object value) {
- if (av != null) {
- av.visit(name, value);
- }
- }
-
- /**
- * Visits an enumeration value of the annotation.
- *
- * @param name
- * the value name.
- * @param desc
- * the class descriptor of the enumeration class.
- * @param value
- * the actual enumeration value.
- */
- public void visitEnum(String name, String desc, String value) {
- if (av != null) {
- av.visitEnum(name, desc, value);
- }
- }
-
- /**
- * Visits a nested annotation value of the annotation.
- *
- * @param name
- * the value name.
- * @param desc
- * the class descriptor of the nested annotation class.
- * @return a visitor to visit the actual nested annotation value, or
- * <tt>null</tt> if this visitor is not interested in visiting this
- * nested annotation. <i>The nested annotation value must be fully
- * visited before calling other methods on this annotation
- * visitor</i>.
- */
- public AnnotationVisitor visitAnnotation(String name, String desc) {
- if (av != null) {
- return av.visitAnnotation(name, desc);
- }
- return null;
- }
-
- /**
- * Visits an array value of the annotation. Note that arrays of primitive
- * types (such as byte, boolean, short, char, int, long, float or double)
- * can be passed as value to {@link #visit visit}. This is what
- * {@link ClassReader} does.
- *
- * @param name
- * the value name.
- * @return a visitor to visit the actual array value elements, or
- * <tt>null</tt> if this visitor is not interested in visiting these
- * values. The 'name' parameters passed to the methods of this
- * visitor are ignored. <i>All the array values must be visited
- * before calling other methods on this annotation visitor</i>.
- */
- public AnnotationVisitor visitArray(String name) {
- if (av != null) {
- return av.visitArray(name);
- }
- return null;
- }
-
- /**
- * Visits the end of the annotation.
- */
- public void visitEnd() {
- if (av != null) {
- av.visitEnd();
- }
- }
-}
diff --git a/src/jvm/clojure/asm/AnnotationWriter.java b/src/jvm/clojure/asm/AnnotationWriter.java
deleted file mode 100644
index 9a40bf8..0000000
--- a/src/jvm/clojure/asm/AnnotationWriter.java
+++ /dev/null
@@ -1,318 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-/**
- * An {@link AnnotationVisitor} that generates annotations in bytecode form.
- *
- * @author Eric Bruneton
- * @author Eugene Kuleshov
- */
-final class AnnotationWriter extends AnnotationVisitor {
-
- /**
- * The class writer to which this annotation must be added.
- */
- private final ClassWriter cw;
-
- /**
- * The number of values in this annotation.
- */
- private int size;
-
- /**
- * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation
- * writers used for annotation default and annotation arrays use unnamed
- * values.
- */
- private final boolean named;
-
- /**
- * The annotation values in bytecode form. This byte vector only contains
- * the values themselves, i.e. the number of values must be stored as a
- * unsigned short just before these bytes.
- */
- private final ByteVector bv;
-
- /**
- * The byte vector to be used to store the number of values of this
- * annotation. See {@link #bv}.
- */
- private final ByteVector parent;
-
- /**
- * Where the number of values of this annotation must be stored in
- * {@link #parent}.
- */
- private final int offset;
-
- /**
- * Next annotation writer. This field is used to store annotation lists.
- */
- AnnotationWriter next;
-
- /**
- * Previous annotation writer. This field is used to store annotation lists.
- */
- AnnotationWriter prev;
-
- // ------------------------------------------------------------------------
- // Constructor
- // ------------------------------------------------------------------------
-
- /**
- * Constructs a new {@link AnnotationWriter}.
- *
- * @param cw
- * the class writer to which this annotation must be added.
- * @param named
- * <tt>true<tt> if values are named, <tt>false</tt> otherwise.
- * @param bv
- * where the annotation values must be stored.
- * @param parent
- * where the number of annotation values must be stored.
- * @param offset
- * where in <tt>parent</tt> the number of annotation values must
- * be stored.
- */
- AnnotationWriter(final ClassWriter cw, final boolean named,
- final ByteVector bv, final ByteVector parent, final int offset) {
- super(Opcodes.ASM4);
- this.cw = cw;
- this.named = named;
- this.bv = bv;
- this.parent = parent;
- this.offset = offset;
- }
-
- // ------------------------------------------------------------------------
- // Implementation of the AnnotationVisitor abstract class
- // ------------------------------------------------------------------------
-
- @Override
- public void visit(final String name, final Object value) {
- ++size;
- if (named) {
- bv.putShort(cw.newUTF8(name));
- }
- if (value instanceof String) {
- bv.put12('s', cw.newUTF8((String) value));
- } else if (value instanceof Byte) {
- bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index);
- } else if (value instanceof Boolean) {
- int v = ((Boolean) value).booleanValue() ? 1 : 0;
- bv.put12('Z', cw.newInteger(v).index);
- } else if (value instanceof Character) {
- bv.put12('C', cw.newInteger(((Character) value).charValue()).index);
- } else if (value instanceof Short) {
- bv.put12('S', cw.newInteger(((Short) value).shortValue()).index);
- } else if (value instanceof Type) {
- bv.put12('c', cw.newUTF8(((Type) value).getDescriptor()));
- } else if (value instanceof byte[]) {
- byte[] v = (byte[]) value;
- bv.put12('[', v.length);
- for (int i = 0; i < v.length; i++) {
- bv.put12('B', cw.newInteger(v[i]).index);
- }
- } else if (value instanceof boolean[]) {
- boolean[] v = (boolean[]) value;
- bv.put12('[', v.length);
- for (int i = 0; i < v.length; i++) {
- bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index);
- }
- } else if (value instanceof short[]) {
- short[] v = (short[]) value;
- bv.put12('[', v.length);
- for (int i = 0; i < v.length; i++) {
- bv.put12('S', cw.newInteger(v[i]).index);
- }
- } else if (value instanceof char[]) {
- char[] v = (char[]) value;
- bv.put12('[', v.length);
- for (int i = 0; i < v.length; i++) {
- bv.put12('C', cw.newInteger(v[i]).index);
- }
- } else if (value instanceof int[]) {
- int[] v = (int[]) value;
- bv.put12('[', v.length);
- for (int i = 0; i < v.length; i++) {
- bv.put12('I', cw.newInteger(v[i]).index);
- }
- } else if (value instanceof long[]) {
- long[] v = (long[]) value;
- bv.put12('[', v.length);
- for (int i = 0; i < v.length; i++) {
- bv.put12('J', cw.newLong(v[i]).index);
- }
- } else if (value instanceof float[]) {
- float[] v = (float[]) value;
- bv.put12('[', v.length);
- for (int i = 0; i < v.length; i++) {
- bv.put12('F', cw.newFloat(v[i]).index);
- }
- } else if (value instanceof double[]) {
- double[] v = (double[]) value;
- bv.put12('[', v.length);
- for (int i = 0; i < v.length; i++) {
- bv.put12('D', cw.newDouble(v[i]).index);
- }
- } else {
- Item i = cw.newConstItem(value);
- bv.put12(".s.IFJDCS".charAt(i.type), i.index);
- }
- }
-
- @Override
- public void visitEnum(final String name, final String desc,
- final String value) {
- ++size;
- if (named) {
- bv.putShort(cw.newUTF8(name));
- }
- bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value));
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(final String name,
- final String desc) {
- ++size;
- if (named) {
- bv.putShort(cw.newUTF8(name));
- }
- // write tag and type, and reserve space for values count
- bv.put12('@', cw.newUTF8(desc)).putShort(0);
- return new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
- }
-
- @Override
- public AnnotationVisitor visitArray(final String name) {
- ++size;
- if (named) {
- bv.putShort(cw.newUTF8(name));
- }
- // write tag, and reserve space for array size
- bv.put12('[', 0);
- return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);
- }
-
- @Override
- public void visitEnd() {
- if (parent != null) {
- byte[] data = parent.data;
- data[offset] = (byte) (size >>> 8);
- data[offset + 1] = (byte) size;
- }
- }
-
- // ------------------------------------------------------------------------
- // Utility methods
- // ------------------------------------------------------------------------
-
- /**
- * Returns the size of this annotation writer list.
- *
- * @return the size of this annotation writer list.
- */
- int getSize() {
- int size = 0;
- AnnotationWriter aw = this;
- while (aw != null) {
- size += aw.bv.length;
- aw = aw.next;
- }
- return size;
- }
-
- /**
- * Puts the annotations of this annotation writer list into the given byte
- * vector.
- *
- * @param out
- * where the annotations must be put.
- */
- void put(final ByteVector out) {
- int n = 0;
- int size = 2;
- AnnotationWriter aw = this;
- AnnotationWriter last = null;
- while (aw != null) {
- ++n;
- size += aw.bv.length;
- aw.visitEnd(); // in case user forgot to call visitEnd
- aw.prev = last;
- last = aw;
- aw = aw.next;
- }
- out.putInt(size);
- out.putShort(n);
- aw = last;
- while (aw != null) {
- out.putByteArray(aw.bv.data, 0, aw.bv.length);
- aw = aw.prev;
- }
- }
-
- /**
- * Puts the given annotation lists into the given byte vector.
- *
- * @param panns
- * an array of annotation writer lists.
- * @param off
- * index of the first annotation to be written.
- * @param out
- * where the annotations must be put.
- */
- static void put(final AnnotationWriter[] panns, final int off,
- final ByteVector out) {
- int size = 1 + 2 * (panns.length - off);
- for (int i = off; i < panns.length; ++i) {
- size += panns[i] == null ? 0 : panns[i].getSize();
- }
- out.putInt(size).putByte(panns.length - off);
- for (int i = off; i < panns.length; ++i) {
- AnnotationWriter aw = panns[i];
- AnnotationWriter last = null;
- int n = 0;
- while (aw != null) {
- ++n;
- aw.visitEnd(); // in case user forgot to call visitEnd
- aw.prev = last;
- last = aw;
- aw = aw.next;
- }
- out.putShort(n);
- aw = last;
- while (aw != null) {
- out.putByteArray(aw.bv.data, 0, aw.bv.length);
- aw = aw.prev;
- }
- }
- }
-}
diff --git a/src/jvm/clojure/asm/Attribute.java b/src/jvm/clojure/asm/Attribute.java
deleted file mode 100644
index 1259c3c..0000000
--- a/src/jvm/clojure/asm/Attribute.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-/**
- * A non standard class, field, method or code attribute.
- *
- * @author Eric Bruneton
- * @author Eugene Kuleshov
- */
-public class Attribute {
-
- /**
- * The type of this attribute.
- */
- public final String type;
-
- /**
- * The raw value of this attribute, used only for unknown attributes.
- */
- byte[] value;
-
- /**
- * The next attribute in this attribute list. May be <tt>null</tt>.
- */
- Attribute next;
-
- /**
- * Constructs a new empty attribute.
- *
- * @param type
- * the type of the attribute.
- */
- protected Attribute(final String type) {
- this.type = type;
- }
-
- /**
- * Returns <tt>true</tt> if this type of attribute is unknown. The default
- * implementation of this method always returns <tt>true</tt>.
- *
- * @return <tt>true</tt> if this type of attribute is unknown.
- */
- public boolean isUnknown() {
- return true;
- }
-
- /**
- * Returns <tt>true</tt> if this type of attribute is a code attribute.
- *
- * @return <tt>true</tt> if this type of attribute is a code attribute.
- */
- public boolean isCodeAttribute() {
- return false;
- }
-
- /**
- * Returns the labels corresponding to this attribute.
- *
- * @return the labels corresponding to this attribute, or <tt>null</tt> if
- * this attribute is not a code attribute that contains labels.
- */
- protected Label[] getLabels() {
- return null;
- }
-
- /**
- * Reads a {@link #type type} attribute. This method must return a
- * <i>new</i> {@link Attribute} object, of type {@link #type type},
- * corresponding to the <tt>len</tt> bytes starting at the given offset, in
- * the given class reader.
- *
- * @param cr
- * the class that contains the attribute to be read.
- * @param off
- * index of the first byte of the attribute's content in
- * {@link ClassReader#b cr.b}. The 6 attribute header bytes,
- * containing the type and the length of the attribute, are not
- * taken into account here.
- * @param len
- * the length of the attribute's content.
- * @param buf
- * buffer to be used to call {@link ClassReader#readUTF8
- * readUTF8}, {@link ClassReader#readClass(int,char[]) readClass}
- * or {@link ClassReader#readConst readConst}.
- * @param codeOff
- * index of the first byte of code's attribute content in
- * {@link ClassReader#b cr.b}, or -1 if the attribute to be read
- * is not a code attribute. The 6 attribute header bytes,
- * containing the type and the length of the attribute, are not
- * taken into account here.
- * @param labels
- * the labels of the method's code, or <tt>null</tt> if the
- * attribute to be read is not a code attribute.
- * @return a <i>new</i> {@link Attribute} object corresponding to the given
- * bytes.
- */
- protected Attribute read(final ClassReader cr, final int off,
- final int len, final char[] buf, final int codeOff,
- final Label[] labels) {
- Attribute attr = new Attribute(type);
- attr.value = new byte[len];
- System.arraycopy(cr.b, off, attr.value, 0, len);
- return attr;
- }
-
- /**
- * Returns the byte array form of this attribute.
- *
- * @param cw
- * the class to which this attribute must be added. This
- * parameter can be used to add to the constant pool of this
- * class the items that corresponds to this attribute.
- * @param code
- * the bytecode of the method corresponding to this code
- * attribute, or <tt>null</tt> if this attribute is not a code
- * attributes.
- * @param len
- * the length of the bytecode of the method corresponding to this
- * code attribute, or <tt>null</tt> if this attribute is not a
- * code attribute.
- * @param maxStack
- * the maximum stack size of the method corresponding to this
- * code attribute, or -1 if this attribute is not a code
- * attribute.
- * @param maxLocals
- * the maximum number of local variables of the method
- * corresponding to this code attribute, or -1 if this attribute
- * is not a code attribute.
- * @return the byte array form of this attribute.
- */
- protected ByteVector write(final ClassWriter cw, final byte[] code,
- final int len, final int maxStack, final int maxLocals) {
- ByteVector v = new ByteVector();
- v.data = value;
- v.length = value.length;
- return v;
- }
-
- /**
- * Returns the length of the attribute list that begins with this attribute.
- *
- * @return the length of the attribute list that begins with this attribute.
- */
- final int getCount() {
- int count = 0;
- Attribute attr = this;
- while (attr != null) {
- count += 1;
- attr = attr.next;
- }
- return count;
- }
-
- /**
- * Returns the size of all the attributes in this attribute list.
- *
- * @param cw
- * the class writer to be used to convert the attributes into
- * byte arrays, with the {@link #write write} method.
- * @param code
- * the bytecode of the method corresponding to these code
- * attributes, or <tt>null</tt> if these attributes are not code
- * attributes.
- * @param len
- * the length of the bytecode of the method corresponding to
- * these code attributes, or <tt>null</tt> if these attributes
- * are not code attributes.
- * @param maxStack
- * the maximum stack size of the method corresponding to these
- * code attributes, or -1 if these attributes are not code
- * attributes.
- * @param maxLocals
- * the maximum number of local variables of the method
- * corresponding to these code attributes, or -1 if these
- * attributes are not code attributes.
- * @return the size of all the attributes in this attribute list. This size
- * includes the size of the attribute headers.
- */
- final int getSize(final ClassWriter cw, final byte[] code, final int len,
- final int maxStack, final int maxLocals) {
- Attribute attr = this;
- int size = 0;
- while (attr != null) {
- cw.newUTF8(attr.type);
- size += attr.write(cw, code, len, maxStack, maxLocals).length + 6;
- attr = attr.next;
- }
- return size;
- }
-
- /**
- * Writes all the attributes of this attribute list in the given byte
- * vector.
- *
- * @param cw
- * the class writer to be used to convert the attributes into
- * byte arrays, with the {@link #write write} method.
- * @param code
- * the bytecode of the method corresponding to these code
- * attributes, or <tt>null</tt> if these attributes are not code
- * attributes.
- * @param len
- * the length of the bytecode of the method corresponding to
- * these code attributes, or <tt>null</tt> if these attributes
- * are not code attributes.
- * @param maxStack
- * the maximum stack size of the method corresponding to these
- * code attributes, or -1 if these attributes are not code
- * attributes.
- * @param maxLocals
- * the maximum number of local variables of the method
- * corresponding to these code attributes, or -1 if these
- * attributes are not code attributes.
- * @param out
- * where the attributes must be written.
- */
- final void put(final ClassWriter cw, final byte[] code, final int len,
- final int maxStack, final int maxLocals, final ByteVector out) {
- Attribute attr = this;
- while (attr != null) {
- ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
- out.putShort(cw.newUTF8(attr.type)).putInt(b.length);
- out.putByteArray(b.data, 0, b.length);
- attr = attr.next;
- }
- }
-}
diff --git a/src/jvm/clojure/asm/ByteVector.java b/src/jvm/clojure/asm/ByteVector.java
deleted file mode 100644
index 0e4f861..0000000
--- a/src/jvm/clojure/asm/ByteVector.java
+++ /dev/null
@@ -1,306 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-/**
- * A dynamically extensible vector of bytes. This class is roughly equivalent to
- * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
- *
- * @author Eric Bruneton
- */
-public class ByteVector {
-
- /**
- * The content of this vector.
- */
- byte[] data;
-
- /**
- * Actual number of bytes in this vector.
- */
- int length;
-
- /**
- * Constructs a new {@link ByteVector ByteVector} with a default initial
- * size.
- */
- public ByteVector() {
- data = new byte[64];
- }
-
- /**
- * Constructs a new {@link ByteVector ByteVector} with the given initial
- * size.
- *
- * @param initialSize
- * the initial size of the byte vector to be constructed.
- */
- public ByteVector(final int initialSize) {
- data = new byte[initialSize];
- }
-
- /**
- * Puts a byte into this byte vector. The byte vector is automatically
- * enlarged if necessary.
- *
- * @param b
- * a byte.
- * @return this byte vector.
- */
- public ByteVector putByte(final int b) {
- int length = this.length;
- if (length + 1 > data.length) {
- enlarge(1);
- }
- data[length++] = (byte) b;
- this.length = length;
- return this;
- }
-
- /**
- * Puts two bytes into this byte vector. The byte vector is automatically
- * enlarged if necessary.
- *
- * @param b1
- * a byte.
- * @param b2
- * another byte.
- * @return this byte vector.
- */
- ByteVector put11(final int b1, final int b2) {
- int length = this.length;
- if (length + 2 > data.length) {
- enlarge(2);
- }
- byte[] data = this.data;
- data[length++] = (byte) b1;
- data[length++] = (byte) b2;
- this.length = length;
- return this;
- }
-
- /**
- * Puts a short into this byte vector. The byte vector is automatically
- * enlarged if necessary.
- *
- * @param s
- * a short.
- * @return this byte vector.
- */
- public ByteVector putShort(final int s) {
- int length = this.length;
- if (length + 2 > data.length) {
- enlarge(2);
- }
- byte[] data = this.data;
- data[length++] = (byte) (s >>> 8);
- data[length++] = (byte) s;
- this.length = length;
- return this;
- }
-
- /**
- * Puts a byte and a short into this byte vector. The byte vector is
- * automatically enlarged if necessary.
- *
- * @param b
- * a byte.
- * @param s
- * a short.
- * @return this byte vector.
- */
- ByteVector put12(final int b, final int s) {
- int length = this.length;
- if (length + 3 > data.length) {
- enlarge(3);
- }
- byte[] data = this.data;
- data[length++] = (byte) b;
- data[length++] = (byte) (s >>> 8);
- data[length++] = (byte) s;
- this.length = length;
- return this;
- }
-
- /**
- * Puts an int into this byte vector. The byte vector is automatically
- * enlarged if necessary.
- *
- * @param i
- * an int.
- * @return this byte vector.
- */
- public ByteVector putInt(final int i) {
- int length = this.length;
- if (length + 4 > data.length) {
- enlarge(4);
- }
- byte[] data = this.data;
- data[length++] = (byte) (i >>> 24);
- data[length++] = (byte) (i >>> 16);
- data[length++] = (byte) (i >>> 8);
- data[length++] = (byte) i;
- this.length = length;
- return this;
- }
-
- /**
- * Puts a long into this byte vector. The byte vector is automatically
- * enlarged if necessary.
- *
- * @param l
- * a long.
- * @return this byte vector.
- */
- public ByteVector putLong(final long l) {
- int length = this.length;
- if (length + 8 > data.length) {
- enlarge(8);
- }
- byte[] data = this.data;
- int i = (int) (l >>> 32);
- data[length++] = (byte) (i >>> 24);
- data[length++] = (byte) (i >>> 16);
- data[length++] = (byte) (i >>> 8);
- data[length++] = (byte) i;
- i = (int) l;
- data[length++] = (byte) (i >>> 24);
- data[length++] = (byte) (i >>> 16);
- data[length++] = (byte) (i >>> 8);
- data[length++] = (byte) i;
- this.length = length;
- return this;
- }
-
- /**
- * Puts an UTF8 string into this byte vector. The byte vector is
- * automatically enlarged if necessary.
- *
- * @param s
- * a String.
- * @return this byte vector.
- */
- public ByteVector putUTF8(final String s) {
- int charLength = s.length();
- int len = length;
- if (len + 2 + charLength > data.length) {
- enlarge(2 + charLength);
- }
- byte[] data = this.data;
- // optimistic algorithm: instead of computing the byte length and then
- // serializing the string (which requires two loops), we assume the byte
- // length is equal to char length (which is the most frequent case), and
- // we start serializing the string right away. During the serialization,
- // if we find that this assumption is wrong, we continue with the
- // general method.
- data[len++] = (byte) (charLength >>> 8);
- data[len++] = (byte) charLength;
- for (int i = 0; i < charLength; ++i) {
- char c = s.charAt(i);
- if (c >= '\001' && c <= '\177') {
- data[len++] = (byte) c;
- } else {
- int byteLength = i;
- for (int j = i; j < charLength; ++j) {
- c = s.charAt(j);
- if (c >= '\001' && c <= '\177') {
- byteLength++;
- } else if (c > '\u07FF') {
- byteLength += 3;
- } else {
- byteLength += 2;
- }
- }
- data[length] = (byte) (byteLength >>> 8);
- data[length + 1] = (byte) byteLength;
- if (length + 2 + byteLength > data.length) {
- length = len;
- enlarge(2 + byteLength);
- data = this.data;
- }
- for (int j = i; j < charLength; ++j) {
- c = s.charAt(j);
- if (c >= '\001' && c <= '\177') {
- data[len++] = (byte) c;
- } else if (c > '\u07FF') {
- data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
- data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
- data[len++] = (byte) (0x80 | c & 0x3F);
- } else {
- data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
- data[len++] = (byte) (0x80 | c & 0x3F);
- }
- }
- break;
- }
- }
- length = len;
- return this;
- }
-
- /**
- * Puts an array of bytes into this byte vector. The byte vector is
- * automatically enlarged if necessary.
- *
- * @param b
- * an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
- * null bytes into this byte vector.
- * @param off
- * index of the fist byte of b that must be copied.
- * @param len
- * number of bytes of b that must be copied.
- * @return this byte vector.
- */
- public ByteVector putByteArray(final byte[] b, final int off, final int len) {
- if (length + len > data.length) {
- enlarge(len);
- }
- if (b != null) {
- System.arraycopy(b, off, data, length, len);
- }
- length += len;
- return this;
- }
-
- /**
- * Enlarge this byte vector so that it can receive n more bytes.
- *
- * @param size
- * number of additional bytes that this byte vector should be
- * able to receive.
- */
- private void enlarge(final int size) {
- int length1 = 2 * data.length;
- int length2 = length + size;
- byte[] newData = new byte[length1 > length2 ? length1 : length2];
- System.arraycopy(data, 0, newData, 0, length);
- data = newData;
- }
-}
diff --git a/src/jvm/clojure/asm/ClassReader.java b/src/jvm/clojure/asm/ClassReader.java
deleted file mode 100644
index 9265a37..0000000
--- a/src/jvm/clojure/asm/ClassReader.java
+++ /dev/null
@@ -1,2202 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * A Java class parser to make a {@link ClassVisitor} visit an existing class.
- * This class parses a byte array conforming to the Java class file format and
- * calls the appropriate visit methods of a given class visitor for each field,
- * method and bytecode instruction encountered.
- *
- * @author Eric Bruneton
- * @author Eugene Kuleshov
- */
-public class ClassReader {
-
- /**
- * True to enable signatures support.
- */
- static final boolean SIGNATURES = true;
-
- /**
- * True to enable annotations support.
- */
- static final boolean ANNOTATIONS = true;
-
- /**
- * True to enable stack map frames support.
- */
- static final boolean FRAMES = true;
-
- /**
- * True to enable bytecode writing support.
- */
- static final boolean WRITER = true;
-
- /**
- * True to enable JSR_W and GOTO_W support.
- */
- static final boolean RESIZE = true;
-
- /**
- * Flag to skip method code. If this class is set <code>CODE</code>
- * attribute won't be visited. This can be used, for example, to retrieve
- * annotations for methods and method parameters.
- */
- public static final int SKIP_CODE = 1;
-
- /**
- * Flag to skip the debug information in the class. If this flag is set the
- * debug information of the class is not visited, i.e. the
- * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
- * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be
- * called.
- */
- public static final int SKIP_DEBUG = 2;
-
- /**
- * Flag to skip the stack map frames in the class. If this flag is set the
- * stack map frames of the class is not visited, i.e. the
- * {@link MethodVisitor#visitFrame visitFrame} method will not be called.
- * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is
- * used: it avoids visiting frames that will be ignored and recomputed from
- * scratch in the class writer.
- */
- public static final int SKIP_FRAMES = 4;
-
- /**
- * Flag to expand the stack map frames. By default stack map frames are
- * visited in their original format (i.e. "expanded" for classes whose
- * version is less than V1_6, and "compressed" for the other classes). If
- * this flag is set, stack map frames are always visited in expanded format
- * (this option adds a decompression/recompression step in ClassReader and
- * ClassWriter which degrades performances quite a lot).
- */
- public static final int EXPAND_FRAMES = 8;
-
- /**
- * The class to be parsed. <i>The content of this array must not be
- * modified. This field is intended for {@link Attribute} sub classes, and
- * is normally not needed by class generators or adapters.</i>
- */
- public final byte[] b;
-
- /**
- * The start index of each constant pool item in {@link #b b}, plus one. The
- * one byte offset skips the constant pool item tag that indicates its type.
- */
- private final int[] items;
-
- /**
- * The String objects corresponding to the CONSTANT_Utf8 items. This cache
- * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
- * which GREATLY improves performances (by a factor 2 to 3). This caching
- * strategy could be extended to all constant pool items, but its benefit
- * would not be so great for these items (because they are much less
- * expensive to parse than CONSTANT_Utf8 items).
- */
- private final String[] strings;
-
- /**
- * Maximum length of the strings contained in the constant pool of the
- * class.
- */
- private final int maxStringLength;
-
- /**
- * Start index of the class header information (access, name...) in
- * {@link #b b}.
- */
- public final int header;
-
- // ------------------------------------------------------------------------
- // Constructors
- // ------------------------------------------------------------------------
-
- /**
- * Constructs a new {@link ClassReader} object.
- *
- * @param b
- * the bytecode of the class to be read.
- */
- public ClassReader(final byte[] b) {
- this(b, 0, b.length);
- }
-
- /**
- * Constructs a new {@link ClassReader} object.
- *
- * @param b
- * the bytecode of the class to be read.
- * @param off
- * the start offset of the class data.
- * @param len
- * the length of the class data.
- */
- public ClassReader(final byte[] b, final int off, final int len) {
- this.b = b;
- // checks the class version
- if (readShort(off + 6) > Opcodes.V1_7) {
- throw new IllegalArgumentException();
- }
- // parses the constant pool
- items = new int[readUnsignedShort(off + 8)];
- int n = items.length;
- strings = new String[n];
- int max = 0;
- int index = off + 10;
- for (int i = 1; i < n; ++i) {
- items[i] = index + 1;
- int size;
- switch (b[index]) {
- case ClassWriter.FIELD:
- case ClassWriter.METH:
- case ClassWriter.IMETH:
- case ClassWriter.INT:
- case ClassWriter.FLOAT:
- case ClassWriter.NAME_TYPE:
- case ClassWriter.INDY:
- size = 5;
- break;
- case ClassWriter.LONG:
- case ClassWriter.DOUBLE:
- size = 9;
- ++i;
- break;
- case ClassWriter.UTF8:
- size = 3 + readUnsignedShort(index + 1);
- if (size > max) {
- max = size;
- }
- break;
- case ClassWriter.HANDLE:
- size = 4;
- break;
- // case ClassWriter.CLASS:
- // case ClassWriter.STR:
- // case ClassWriter.MTYPE
- default:
- size = 3;
- break;
- }
- index += size;
- }
- maxStringLength = max;
- // the class header information starts just after the constant pool
- header = index;
- }
-
- /**
- * Returns the class's access flags (see {@link Opcodes}). This value may
- * not reflect Deprecated and Synthetic flags when bytecode is before 1.5
- * and those flags are represented by attributes.
- *
- * @return the class access flags
- *
- * @see ClassVisitor#visit(int, int, String, String, String, String[])
- */
- public int getAccess() {
- return readUnsignedShort(header);
- }
-
- /**
- * Returns the internal name of the class (see
- * {@link Type#getInternalName() getInternalName}).
- *
- * @return the internal class name
- *
- * @see ClassVisitor#visit(int, int, String, String, String, String[])
- */
- public String getClassName() {
- return readClass(header + 2, new char[maxStringLength]);
- }
-
- /**
- * Returns the internal of name of the super class (see
- * {@link Type#getInternalName() getInternalName}). For interfaces, the
- * super class is {@link Object}.
- *
- * @return the internal name of super class, or <tt>null</tt> for
- * {@link Object} class.
- *
- * @see ClassVisitor#visit(int, int, String, String, String, String[])
- */
- public String getSuperName() {
- return readClass(header + 4, new char[maxStringLength]);
- }
-
- /**
- * Returns the internal names of the class's interfaces (see
- * {@link Type#getInternalName() getInternalName}).
- *
- * @return the array of internal names for all implemented interfaces or
- * <tt>null</tt>.
- *
- * @see ClassVisitor#visit(int, int, String, String, String, String[])
- */
- public String[] getInterfaces() {
- int index = header + 6;
- int n = readUnsignedShort(index);
- String[] interfaces = new String[n];
- if (n > 0) {
- char[] buf = new char[maxStringLength];
- for (int i = 0; i < n; ++i) {
- index += 2;
- interfaces[i] = readClass(index, buf);
- }
- }
- return interfaces;
- }
-
- /**
- * Copies the constant pool data into the given {@link ClassWriter}. Should
- * be called before the {@link #accept(ClassVisitor,int)} method.
- *
- * @param classWriter
- * the {@link ClassWriter} to copy constant pool into.
- */
- void copyPool(final ClassWriter classWriter) {
- char[] buf = new char[maxStringLength];
- int ll = items.length;
- Item[] items2 = new Item[ll];
- for (int i = 1; i < ll; i++) {
- int index = items[i];
- int tag = b[index - 1];
- Item item = new Item(i);
- int nameType;
- switch (tag) {
- case ClassWriter.FIELD:
- case ClassWriter.METH:
- case ClassWriter.IMETH:
- nameType = items[readUnsignedShort(index + 2)];
- item.set(tag, readClass(index, buf), readUTF8(nameType, buf),
- readUTF8(nameType + 2, buf));
- break;
- case ClassWriter.INT:
- item.set(readInt(index));
- break;
- case ClassWriter.FLOAT:
- item.set(Float.intBitsToFloat(readInt(index)));
- break;
- case ClassWriter.NAME_TYPE:
- item.set(tag, readUTF8(index, buf), readUTF8(index + 2, buf),
- null);
- break;
- case ClassWriter.LONG:
- item.set(readLong(index));
- ++i;
- break;
- case ClassWriter.DOUBLE:
- item.set(Double.longBitsToDouble(readLong(index)));
- ++i;
- break;
- case ClassWriter.UTF8: {
- String s = strings[i];
- if (s == null) {
- index = items[i];
- s = strings[i] = readUTF(index + 2,
- readUnsignedShort(index), buf);
- }
- item.set(tag, s, null, null);
- break;
- }
- case ClassWriter.HANDLE: {
- int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
- nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
- item.set(ClassWriter.HANDLE_BASE + readByte(index),
- readClass(fieldOrMethodRef, buf),
- readUTF8(nameType, buf), readUTF8(nameType + 2, buf));
- break;
- }
- case ClassWriter.INDY:
- if (classWriter.bootstrapMethods == null) {
- copyBootstrapMethods(classWriter, items2, buf);
- }
- nameType = items[readUnsignedShort(index + 2)];
- item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf),
- readUnsignedShort(index));
- break;
- // case ClassWriter.STR:
- // case ClassWriter.CLASS:
- // case ClassWriter.MTYPE
- default:
- item.set(tag, readUTF8(index, buf), null, null);
- break;
- }
-
- int index2 = item.hashCode % items2.length;
- item.next = items2[index2];
- items2[index2] = item;
- }
-
- int off = items[1] - 1;
- classWriter.pool.putByteArray(b, off, header - off);
- classWriter.items = items2;
- classWriter.threshold = (int) (0.75d * ll);
- classWriter.index = ll;
- }
-
- /**
- * Copies the bootstrap method data into the given {@link ClassWriter}.
- * Should be called before the {@link #accept(ClassVisitor,int)} method.
- *
- * @param classWriter
- * the {@link ClassWriter} to copy bootstrap methods into.
- */
- private void copyBootstrapMethods(final ClassWriter classWriter,
- final Item[] items, final char[] c) {
- // finds the "BootstrapMethods" attribute
- int u = getAttributes();
- boolean found = false;
- for (int i = readUnsignedShort(u); i > 0; --i) {
- String attrName = readUTF8(u + 2, c);
- if ("BootstrapMethods".equals(attrName)) {
- found = true;
- break;
- }
- u += 6 + readInt(u + 4);
- }
- if (!found) {
- return;
- }
- // copies the bootstrap methods in the class writer
- int boostrapMethodCount = readUnsignedShort(u + 8);
- for (int j = 0, v = u + 10; j < boostrapMethodCount; j++) {
- int position = v - u - 10;
- int hashCode = readConst(readUnsignedShort(v), c).hashCode();
- for (int k = readUnsignedShort(v + 2); k > 0; --k) {
- hashCode ^= readConst(readUnsignedShort(v + 4), c).hashCode();
- v += 2;
- }
- v += 4;
- Item item = new Item(j);
- item.set(position, hashCode & 0x7FFFFFFF);
- int index = item.hashCode % items.length;
- item.next = items[index];
- items[index] = item;
- }
- int attrSize = readInt(u + 4);
- ByteVector bootstrapMethods = new ByteVector(attrSize + 62);
- bootstrapMethods.putByteArray(b, u + 10, attrSize - 2);
- classWriter.bootstrapMethodsCount = boostrapMethodCount;
- classWriter.bootstrapMethods = bootstrapMethods;
- }
-
- /**
- * Constructs a new {@link ClassReader} object.
- *
- * @param is
- * an input stream from which to read the class.
- * @throws IOException
- * if a problem occurs during reading.
- */
- public ClassReader(final InputStream is) throws IOException {
- this(readClass(is, false));
- }
-
- /**
- * Constructs a new {@link ClassReader} object.
- *
- * @param name
- * the binary qualified name of the class to be read.
- * @throws IOException
- * if an exception occurs during reading.
- */
- public ClassReader(final String name) throws IOException {
- this(readClass(
- ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
- + ".class"), true));
- }
-
- /**
- * Reads the bytecode of a class.
- *
- * @param is
- * an input stream from which to read the class.
- * @param close
- * true to close the input stream after reading.
- * @return the bytecode read from the given input stream.
- * @throws IOException
- * if a problem occurs during reading.
- */
- private static byte[] readClass(final InputStream is, boolean close)
- throws IOException {
- if (is == null) {
- throw new IOException("Class not found");
- }
- try {
- byte[] b = new byte[is.available()];
- int len = 0;
- while (true) {
- int n = is.read(b, len, b.length - len);
- if (n == -1) {
- if (len < b.length) {
- byte[] c = new byte[len];
- System.arraycopy(b, 0, c, 0, len);
- b = c;
- }
- return b;
- }
- len += n;
- if (len == b.length) {
- int last = is.read();
- if (last < 0) {
- return b;
- }
- byte[] c = new byte[b.length + 1000];
- System.arraycopy(b, 0, c, 0, len);
- c[len++] = (byte) last;
- b = c;
- }
- }
- } finally {
- if (close) {
- is.close();
- }
- }
- }
-
- // ------------------------------------------------------------------------
- // Public methods
- // ------------------------------------------------------------------------
-
- /**
- * Makes the given visitor visit the Java class of this {@link ClassReader}
- * . This class is the one specified in the constructor (see
- * {@link #ClassReader(byte[]) ClassReader}).
- *
- * @param classVisitor
- * the visitor that must visit this class.
- * @param flags
- * option flags that can be used to modify the default behavior
- * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}
- * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
- */
- public void accept(final ClassVisitor classVisitor, final int flags) {
- accept(classVisitor, new Attribute[0], flags);
- }
-
- /**
- * Makes the given visitor visit the Java class of this {@link ClassReader}.
- * This class is the one specified in the constructor (see
- * {@link #ClassReader(byte[]) ClassReader}).
- *
- * @param classVisitor
- * the visitor that must visit this class.
- * @param attrs
- * prototypes of the attributes that must be parsed during the
- * visit of the class. Any attribute whose type is not equal to
- * the type of one the prototypes will not be parsed: its byte
- * array value will be passed unchanged to the ClassWriter.
- * <i>This may corrupt it if this value contains references to
- * the constant pool, or has syntactic or semantic links with a
- * class element that has been transformed by a class adapter
- * between the reader and the writer</i>.
- * @param flags
- * option flags that can be used to modify the default behavior
- * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}
- * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
- */
- public void accept(final ClassVisitor classVisitor,
- final Attribute[] attrs, final int flags) {
- int u = header; // current offset in the class file
- char[] c = new char[maxStringLength]; // buffer used to read strings
-
- Context context = new Context();
- context.attrs = attrs;
- context.flags = flags;
- context.buffer = c;
-
- // reads the class declaration
- int access = readUnsignedShort(u);
- String name = readClass(u + 2, c);
- String superClass = readClass(u + 4, c);
- String[] interfaces = new String[readUnsignedShort(u + 6)];
- u += 8;
- for (int i = 0; i < interfaces.length; ++i) {
- interfaces[i] = readClass(u, c);
- u += 2;
- }
-
- // reads the class attributes
- String signature = null;
- String sourceFile = null;
- String sourceDebug = null;
- String enclosingOwner = null;
- String enclosingName = null;
- String enclosingDesc = null;
- int anns = 0;
- int ianns = 0;
- int innerClasses = 0;
- Attribute attributes = null;
-
- u = getAttributes();
- for (int i = readUnsignedShort(u); i > 0; --i) {
- String attrName = readUTF8(u + 2, c);
- // tests are sorted in decreasing frequency order
- // (based on frequencies observed on typical classes)
- if ("SourceFile".equals(attrName)) {
- sourceFile = readUTF8(u + 8, c);
- } else if ("InnerClasses".equals(attrName)) {
- innerClasses = u + 8;
- } else if ("EnclosingMethod".equals(attrName)) {
- enclosingOwner = readClass(u + 8, c);
- int item = readUnsignedShort(u + 10);
- if (item != 0) {
- enclosingName = readUTF8(items[item], c);
- enclosingDesc = readUTF8(items[item] + 2, c);
- }
- } else if (SIGNATURES && "Signature".equals(attrName)) {
- signature = readUTF8(u + 8, c);
- } else if (ANNOTATIONS
- && "RuntimeVisibleAnnotations".equals(attrName)) {
- anns = u + 8;
- } else if ("Deprecated".equals(attrName)) {
- access |= Opcodes.ACC_DEPRECATED;
- } else if ("Synthetic".equals(attrName)) {
- access |= Opcodes.ACC_SYNTHETIC
- | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
- } else if ("SourceDebugExtension".equals(attrName)) {
- int len = readInt(u + 4);
- sourceDebug = readUTF(u + 8, len, new char[len]);
- } else if (ANNOTATIONS
- && "RuntimeInvisibleAnnotations".equals(attrName)) {
- ianns = u + 8;
- } else if ("BootstrapMethods".equals(attrName)) {
- int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
- for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
- bootstrapMethods[j] = v;
- v += 2 + readUnsignedShort(v + 2) << 1;
- }
- context.bootstrapMethods = bootstrapMethods;
- } else {
- Attribute attr = readAttribute(attrs, attrName, u + 8,
- readInt(u + 4), c, -1, null);
- if (attr != null) {
- attr.next = attributes;
- attributes = attr;
- }
- }
- u += 6 + readInt(u + 4);
- }
-
- // visits the class declaration
- classVisitor.visit(readInt(items[1] - 7), access, name, signature,
- superClass, interfaces);
-
- // visits the source and debug info
- if ((flags & SKIP_DEBUG) == 0
- && (sourceFile != null || sourceDebug != null)) {
- classVisitor.visitSource(sourceFile, sourceDebug);
- }
-
- // visits the outer class
- if (enclosingOwner != null) {
- classVisitor.visitOuterClass(enclosingOwner, enclosingName,
- enclosingDesc);
- }
-
- // visits the class annotations
- if (ANNOTATIONS && anns != 0) {
- for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
- v = readAnnotationValues(v + 2, c, true,
- classVisitor.visitAnnotation(readUTF8(v, c), true));
- }
- }
- if (ANNOTATIONS && ianns != 0) {
- for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
- v = readAnnotationValues(v + 2, c, true,
- classVisitor.visitAnnotation(readUTF8(v, c), false));
- }
- }
-
- // visits the attributes
- while (attributes != null) {
- Attribute attr = attributes.next;
- attributes.next = null;
- classVisitor.visitAttribute(attributes);
- attributes = attr;
- }
-
- // visits the inner classes
- if (innerClasses != 0) {
- int v = innerClasses + 2;
- for (int i = readUnsignedShort(innerClasses); i > 0; --i) {
- classVisitor.visitInnerClass(readClass(v, c),
- readClass(v + 2, c), readUTF8(v + 4, c),
- readUnsignedShort(v + 6));
- v += 8;
- }
- }
-
- // visits the fields and methods
- u = header + 10 + 2 * interfaces.length;
- for (int i = readUnsignedShort(u - 2); i > 0; --i) {
- u = readField(classVisitor, context, u);
- }
- u += 2;
- for (int i = readUnsignedShort(u - 2); i > 0; --i) {
- u = readMethod(classVisitor, context, u);
- }
-
- // visits the end of the class
- classVisitor.visitEnd();
- }
-
- /**
- * Reads a field and makes the given visitor visit it.
- *
- * @param classVisitor
- * the visitor that must visit the field.
- * @param context
- * information about the class being parsed.
- * @param u
- * the start offset of the field in the class file.
- * @return the offset of the first byte following the field in the class.
- */
- private int readField(final ClassVisitor classVisitor,
- final Context context, int u) {
- // reads the field declaration
- char[] c = context.buffer;
- int access = readUnsignedShort(u);
- String name = readUTF8(u + 2, c);
- String desc = readUTF8(u + 4, c);
- u += 6;
-
- // reads the field attributes
- String signature = null;
- int anns = 0;
- int ianns = 0;
- Object value = null;
- Attribute attributes = null;
-
- for (int i = readUnsignedShort(u); i > 0; --i) {
- String attrName = readUTF8(u + 2, c);
- // tests are sorted in decreasing frequency order
- // (based on frequencies observed on typical classes)
- if ("ConstantValue".equals(attrName)) {
- int item = readUnsignedShort(u + 8);
- value = item == 0 ? null : readConst(item, c);
- } else if (SIGNATURES && "Signature".equals(attrName)) {
- signature = readUTF8(u + 8, c);
- } else if ("Deprecated".equals(attrName)) {
- access |= Opcodes.ACC_DEPRECATED;
- } else if ("Synthetic".equals(attrName)) {
- access |= Opcodes.ACC_SYNTHETIC
- | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
- } else if (ANNOTATIONS
- && "RuntimeVisibleAnnotations".equals(attrName)) {
- anns = u + 8;
- } else if (ANNOTATIONS
- && "RuntimeInvisibleAnnotations".equals(attrName)) {
- ianns = u + 8;
- } else {
- Attribute attr = readAttribute(context.attrs, attrName, u + 8,
- readInt(u + 4), c, -1, null);
- if (attr != null) {
- attr.next = attributes;
- attributes = attr;
- }
- }
- u += 6 + readInt(u + 4);
- }
- u += 2;
-
- // visits the field declaration
- FieldVisitor fv = classVisitor.visitField(access, name, desc,
- signature, value);
- if (fv == null) {
- return u;
- }
-
- // visits the field annotations
- if (ANNOTATIONS && anns != 0) {
- for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
- v = readAnnotationValues(v + 2, c, true,
- fv.visitAnnotation(readUTF8(v, c), true));
- }
- }
- if (ANNOTATIONS && ianns != 0) {
- for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
- v = readAnnotationValues(v + 2, c, true,
- fv.visitAnnotation(readUTF8(v, c), false));
- }
- }
-
- // visits the field attributes
- while (attributes != null) {
- Attribute attr = attributes.next;
- attributes.next = null;
- fv.visitAttribute(attributes);
- attributes = attr;
- }
-
- // visits the end of the field
- fv.visitEnd();
-
- return u;
- }
-
- /**
- * Reads a method and makes the given visitor visit it.
- *
- * @param classVisitor
- * the visitor that must visit the method.
- * @param context
- * information about the class being parsed.
- * @param u
- * the start offset of the method in the class file.
- * @return the offset of the first byte following the method in the class.
- */
- private int readMethod(final ClassVisitor classVisitor,
- final Context context, int u) {
- // reads the method declaration
- char[] c = context.buffer;
- int access = readUnsignedShort(u);
- String name = readUTF8(u + 2, c);
- String desc = readUTF8(u + 4, c);
- u += 6;
-
- // reads the method attributes
- int code = 0;
- int exception = 0;
- String[] exceptions = null;
- String signature = null;
- int anns = 0;
- int ianns = 0;
- int dann = 0;
- int mpanns = 0;
- int impanns = 0;
- int firstAttribute = u;
- Attribute attributes = null;
-
- for (int i = readUnsignedShort(u); i > 0; --i) {
- String attrName = readUTF8(u + 2, c);
- // tests are sorted in decreasing frequency order
- // (based on frequencies observed on typical classes)
- if ("Code".equals(attrName)) {
- if ((context.flags & SKIP_CODE) == 0) {
- code = u + 8;
- }
- } else if ("Exceptions".equals(attrName)) {
- exceptions = new String[readUnsignedShort(u + 8)];
- exception = u + 10;
- for (int j = 0; j < exceptions.length; ++j) {
- exceptions[j] = readClass(exception, c);
- exception += 2;
- }
- } else if (SIGNATURES && "Signature".equals(attrName)) {
- signature = readUTF8(u + 8, c);
- } else if ("Deprecated".equals(attrName)) {
- access |= Opcodes.ACC_DEPRECATED;
- } else if (ANNOTATIONS
- && "RuntimeVisibleAnnotations".equals(attrName)) {
- anns = u + 8;
- } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
- dann = u + 8;
- } else if ("Synthetic".equals(attrName)) {
- access |= Opcodes.ACC_SYNTHETIC
- | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
- } else if (ANNOTATIONS
- && "RuntimeInvisibleAnnotations".equals(attrName)) {
- ianns = u + 8;
- } else if (ANNOTATIONS
- && "RuntimeVisibleParameterAnnotations".equals(attrName)) {
- mpanns = u + 8;
- } else if (ANNOTATIONS
- && "RuntimeInvisibleParameterAnnotations".equals(attrName)) {
- impanns = u + 8;
- } else {
- Attribute attr = readAttribute(context.attrs, attrName, u + 8,
- readInt(u + 4), c, -1, null);
- if (attr != null) {
- attr.next = attributes;
- attributes = attr;
- }
- }
- u += 6 + readInt(u + 4);
- }
- u += 2;
-
- // visits the method declaration
- MethodVisitor mv = classVisitor.visitMethod(access, name, desc,
- signature, exceptions);
- if (mv == null) {
- return u;
- }
-
- /*
- * if the returned MethodVisitor is in fact a MethodWriter, it means
- * there is no method adapter between the reader and the writer. If, in
- * addition, the writer's constant pool was copied from this reader
- * (mw.cw.cr == this), and the signature and exceptions of the method
- * have not been changed, then it is possible to skip all visit events
- * and just copy the original code of the method to the writer (the
- * access, name and descriptor can have been changed, this is not
- * important since they are not copied as is from the reader).
- */
- if (WRITER && mv instanceof MethodWriter) {
- MethodWriter mw = (MethodWriter) mv;
- if (mw.cw.cr == this && signature == mw.signature) {
- boolean sameExceptions = false;
- if (exceptions == null) {
- sameExceptions = mw.exceptionCount == 0;
- } else if (exceptions.length == mw.exceptionCount) {
- sameExceptions = true;
- for (int j = exceptions.length - 1; j >= 0; --j) {
- exception -= 2;
- if (mw.exceptions[j] != readUnsignedShort(exception)) {
- sameExceptions = false;
- break;
- }
- }
- }
- if (sameExceptions) {
- /*
- * we do not copy directly the code into MethodWriter to
- * save a byte array copy operation. The real copy will be
- * done in ClassWriter.toByteArray().
- */
- mw.classReaderOffset = firstAttribute;
- mw.classReaderLength = u - firstAttribute;
- return u;
- }
- }
- }
-
- // visits the method annotations
- if (ANNOTATIONS && dann != 0) {
- AnnotationVisitor dv = mv.visitAnnotationDefault();
- readAnnotationValue(dann, c, null, dv);
- if (dv != null) {
- dv.visitEnd();
- }
- }
- if (ANNOTATIONS && anns != 0) {
- for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
- v = readAnnotationValues(v + 2, c, true,
- mv.visitAnnotation(readUTF8(v, c), true));
- }
- }
- if (ANNOTATIONS && ianns != 0) {
- for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
- v = readAnnotationValues(v + 2, c, true,
- mv.visitAnnotation(readUTF8(v, c), false));
- }
- }
- if (ANNOTATIONS && mpanns != 0) {
- readParameterAnnotations(mpanns, desc, c, true, mv);
- }
- if (ANNOTATIONS && impanns != 0) {
- readParameterAnnotations(impanns, desc, c, false, mv);
- }
-
- // visits the method attributes
- while (attributes != null) {
- Attribute attr = attributes.next;
- attributes.next = null;
- mv.visitAttribute(attributes);
- attributes = attr;
- }
-
- // visits the method code
- if (code != 0) {
- context.access = access;
- context.name = name;
- context.desc = desc;
- mv.visitCode();
- readCode(mv, context, code);
- }
-
- // visits the end of the method
- mv.visitEnd();
-
- return u;
- }
-
- /**
- * Reads the bytecode of a method and makes the given visitor visit it.
- *
- * @param mv
- * the visitor that must visit the method's code.
- * @param context
- * information about the class being parsed.
- * @param u
- * the start offset of the code attribute in the class file.
- */
- private void readCode(final MethodVisitor mv, final Context context, int u) {
- // reads the header
- byte[] b = this.b;
- char[] c = context.buffer;
- int maxStack = readUnsignedShort(u);
- int maxLocals = readUnsignedShort(u + 2);
- int codeLength = readInt(u + 4);
- u += 8;
-
- // reads the bytecode to find the labels
- int codeStart = u;
- int codeEnd = u + codeLength;
- Label[] labels = new Label[codeLength + 2];
- readLabel(codeLength + 1, labels);
- while (u < codeEnd) {
- int offset = u - codeStart;
- int opcode = b[u] & 0xFF;
- switch (ClassWriter.TYPE[opcode]) {
- case ClassWriter.NOARG_INSN:
- case ClassWriter.IMPLVAR_INSN:
- u += 1;
- break;
- case ClassWriter.LABEL_INSN:
- readLabel(offset + readShort(u + 1), labels);
- u += 3;
- break;
- case ClassWriter.LABELW_INSN:
- readLabel(offset + readInt(u + 1), labels);
- u += 5;
- break;
- case ClassWriter.WIDE_INSN:
- opcode = b[u + 1] & 0xFF;
- if (opcode == Opcodes.IINC) {
- u += 6;
- } else {
- u += 4;
- }
- break;
- case ClassWriter.TABL_INSN:
- // skips 0 to 3 padding bytes
- u = u + 4 - (offset & 3);
- // reads instruction
- readLabel(offset + readInt(u), labels);
- for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) {
- readLabel(offset + readInt(u + 12), labels);
- u += 4;
- }
- u += 12;
- break;
- case ClassWriter.LOOK_INSN:
- // skips 0 to 3 padding bytes
- u = u + 4 - (offset & 3);
- // reads instruction
- readLabel(offset + readInt(u), labels);
- for (int i = readInt(u + 4); i > 0; --i) {
- readLabel(offset + readInt(u + 12), labels);
- u += 8;
- }
- u += 8;
- break;
- case ClassWriter.VAR_INSN:
- case ClassWriter.SBYTE_INSN:
- case ClassWriter.LDC_INSN:
- u += 2;
- break;
- case ClassWriter.SHORT_INSN:
- case ClassWriter.LDCW_INSN:
- case ClassWriter.FIELDORMETH_INSN:
- case ClassWriter.TYPE_INSN:
- case ClassWriter.IINC_INSN:
- u += 3;
- break;
- case ClassWriter.ITFMETH_INSN:
- case ClassWriter.INDYMETH_INSN:
- u += 5;
- break;
- // case MANA_INSN:
- default:
- u += 4;
- break;
- }
- }
-
- // reads the try catch entries to find the labels, and also visits them
- for (int i = readUnsignedShort(u); i > 0; --i) {
- Label start = readLabel(readUnsignedShort(u + 2), labels);
- Label end = readLabel(readUnsignedShort(u + 4), labels);
- Label handler = readLabel(readUnsignedShort(u + 6), labels);
- String type = readUTF8(items[readUnsignedShort(u + 8)], c);
- mv.visitTryCatchBlock(start, end, handler, type);
- u += 8;
- }
- u += 2;
-
- // reads the code attributes
- int varTable = 0;
- int varTypeTable = 0;
- boolean zip = true;
- boolean unzip = (context.flags & EXPAND_FRAMES) != 0;
- int stackMap = 0;
- int stackMapSize = 0;
- int frameCount = 0;
- Context frame = null;
- Attribute attributes = null;
-
- for (int i = readUnsignedShort(u); i > 0; --i) {
- String attrName = readUTF8(u + 2, c);
- if ("LocalVariableTable".equals(attrName)) {
- if ((context.flags & SKIP_DEBUG) == 0) {
- varTable = u + 8;
- for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
- int label = readUnsignedShort(v + 10);
- if (labels[label] == null) {
- readLabel(label, labels).status |= Label.DEBUG;
- }
- label += readUnsignedShort(v + 12);
- if (labels[label] == null) {
- readLabel(label, labels).status |= Label.DEBUG;
- }
- v += 10;
- }
- }
- } else if ("LocalVariableTypeTable".equals(attrName)) {
- varTypeTable = u + 8;
- } else if ("LineNumberTable".equals(attrName)) {
- if ((context.flags & SKIP_DEBUG) == 0) {
- for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
- int label = readUnsignedShort(v + 10);
- if (labels[label] == null) {
- readLabel(label, labels).status |= Label.DEBUG;
- }
- labels[label].line = readUnsignedShort(v + 12);
- v += 4;
- }
- }
- } else if (FRAMES && "StackMapTable".equals(attrName)) {
- if ((context.flags & SKIP_FRAMES) == 0) {
- stackMap = u + 10;
- stackMapSize = readInt(u + 4);
- frameCount = readUnsignedShort(u + 8);
- }
- /*
- * here we do not extract the labels corresponding to the
- * attribute content. This would require a full parsing of the
- * attribute, which would need to be repeated in the second
- * phase (see below). Instead the content of the attribute is
- * read one frame at a time (i.e. after a frame has been
- * visited, the next frame is read), and the labels it contains
- * are also extracted one frame at a time. Thanks to the
- * ordering of frames, having only a "one frame lookahead" is
- * not a problem, i.e. it is not possible to see an offset
- * smaller than the offset of the current insn and for which no
- * Label exist.
- */
- /*
- * This is not true for UNINITIALIZED type offsets. We solve
- * this by parsing the stack map table without a full decoding
- * (see below).
- */
- } else if (FRAMES && "StackMap".equals(attrName)) {
- if ((context.flags & SKIP_FRAMES) == 0) {
- zip = false;
- stackMap = u + 10;
- stackMapSize = readInt(u + 4);
- frameCount = readUnsignedShort(u + 8);
- }
- /*
- * IMPORTANT! here we assume that the frames are ordered, as in
- * the StackMapTable attribute, although this is not guaranteed
- * by the attribute format.
- */
- } else {
- for (int j = 0; j < context.attrs.length; ++j) {
- if (context.attrs[j].type.equals(attrName)) {
- Attribute attr = context.attrs[j].read(this, u + 8,
- readInt(u + 4), c, codeStart - 8, labels);
- if (attr != null) {
- attr.next = attributes;
- attributes = attr;
- }
- }
- }
- }
- u += 6 + readInt(u + 4);
- }
- u += 2;
-
- // generates the first (implicit) stack map frame
- if (FRAMES && stackMap != 0) {
- /*
- * for the first explicit frame the offset is not offset_delta + 1
- * but only offset_delta; setting the implicit frame offset to -1
- * allow the use of the "offset_delta + 1" rule in all cases
- */
- frame = context;
- frame.offset = -1;
- frame.mode = 0;
- frame.localCount = 0;
- frame.localDiff = 0;
- frame.stackCount = 0;
- frame.local = new Object[maxLocals];
- frame.stack = new Object[maxStack];
- if (unzip) {
- getImplicitFrame(context);
- }
- /*
- * Finds labels for UNINITIALIZED frame types. Instead of decoding
- * each element of the stack map table, we look for 3 consecutive
- * bytes that "look like" an UNINITIALIZED type (tag 8, offset
- * within code bounds, NEW instruction at this offset). We may find
- * false positives (i.e. not real UNINITIALIZED types), but this
- * should be rare, and the only consequence will be the creation of
- * an unneeded label. This is better than creating a label for each
- * NEW instruction, and faster than fully decoding the whole stack
- * map table.
- */
- for (int i = stackMap; i < stackMap + stackMapSize - 2; ++i) {
- if (b[i] == 8) { // UNINITIALIZED FRAME TYPE
- int v = readUnsignedShort(i + 1);
- if (v >= 0 && v < codeLength) {
- if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) {
- readLabel(v, labels);
- }
- }
- }
- }
- }
-
- // visits the instructions
- u = codeStart;
- while (u < codeEnd) {
- int offset = u - codeStart;
-
- // visits the label and line number for this offset, if any
- Label l = labels[offset];
- if (l != null) {
- mv.visitLabel(l);
- if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) {
- mv.visitLineNumber(l.line, l);
- }
- }
-
- // visits the frame for this offset, if any
- while (FRAMES && frame != null
- && (frame.offset == offset || frame.offset == -1)) {
- // if there is a frame for this offset, makes the visitor visit
- // it, and reads the next frame if there is one.
- if (frame.offset != -1) {
- if (!zip || unzip) {
- mv.visitFrame(Opcodes.F_NEW, frame.localCount,
- frame.local, frame.stackCount, frame.stack);
- } else {
- mv.visitFrame(frame.mode, frame.localDiff, frame.local,
- frame.stackCount, frame.stack);
- }
- }
- if (frameCount > 0) {
- stackMap = readFrame(stackMap, zip, unzip, labels, frame);
- --frameCount;
- } else {
- frame = null;
- }
- }
-
- // visits the instruction at this offset
- int opcode = b[u] & 0xFF;
- switch (ClassWriter.TYPE[opcode]) {
- case ClassWriter.NOARG_INSN:
- mv.visitInsn(opcode);
- u += 1;
- break;
- case ClassWriter.IMPLVAR_INSN:
- if (opcode > Opcodes.ISTORE) {
- opcode -= 59; // ISTORE_0
- mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),
- opcode & 0x3);
- } else {
- opcode -= 26; // ILOAD_0
- mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), opcode & 0x3);
- }
- u += 1;
- break;
- case ClassWriter.LABEL_INSN:
- mv.visitJumpInsn(opcode, labels[offset + readShort(u + 1)]);
- u += 3;
- break;
- case ClassWriter.LABELW_INSN:
- mv.visitJumpInsn(opcode - 33, labels[offset + readInt(u + 1)]);
- u += 5;
- break;
- case ClassWriter.WIDE_INSN:
- opcode = b[u + 1] & 0xFF;
- if (opcode == Opcodes.IINC) {
- mv.visitIincInsn(readUnsignedShort(u + 2), readShort(u + 4));
- u += 6;
- } else {
- mv.visitVarInsn(opcode, readUnsignedShort(u + 2));
- u += 4;
- }
- break;
- case ClassWriter.TABL_INSN: {
- // skips 0 to 3 padding bytes
- u = u + 4 - (offset & 3);
- // reads instruction
- int label = offset + readInt(u);
- int min = readInt(u + 4);
- int max = readInt(u + 8);
- Label[] table = new Label[max - min + 1];
- u += 12;
- for (int i = 0; i < table.length; ++i) {
- table[i] = labels[offset + readInt(u)];
- u += 4;
- }
- mv.visitTableSwitchInsn(min, max, labels[label], table);
- break;
- }
- case ClassWriter.LOOK_INSN: {
- // skips 0 to 3 padding bytes
- u = u + 4 - (offset & 3);
- // reads instruction
- int label = offset + readInt(u);
- int len = readInt(u + 4);
- int[] keys = new int[len];
- Label[] values = new Label[len];
- u += 8;
- for (int i = 0; i < len; ++i) {
- keys[i] = readInt(u);
- values[i] = labels[offset + readInt(u + 4)];
- u += 8;
- }
- mv.visitLookupSwitchInsn(labels[label], keys, values);
- break;
- }
- case ClassWriter.VAR_INSN:
- mv.visitVarInsn(opcode, b[u + 1] & 0xFF);
- u += 2;
- break;
- case ClassWriter.SBYTE_INSN:
- mv.visitIntInsn(opcode, b[u + 1]);
- u += 2;
- break;
- case ClassWriter.SHORT_INSN:
- mv.visitIntInsn(opcode, readShort(u + 1));
- u += 3;
- break;
- case ClassWriter.LDC_INSN:
- mv.visitLdcInsn(readConst(b[u + 1] & 0xFF, c));
- u += 2;
- break;
- case ClassWriter.LDCW_INSN:
- mv.visitLdcInsn(readConst(readUnsignedShort(u + 1), c));
- u += 3;
- break;
- case ClassWriter.FIELDORMETH_INSN:
- case ClassWriter.ITFMETH_INSN: {
- int cpIndex = items[readUnsignedShort(u + 1)];
- String iowner = readClass(cpIndex, c);
- cpIndex = items[readUnsignedShort(cpIndex + 2)];
- String iname = readUTF8(cpIndex, c);
- String idesc = readUTF8(cpIndex + 2, c);
- if (opcode < Opcodes.INVOKEVIRTUAL) {
- mv.visitFieldInsn(opcode, iowner, iname, idesc);
- } else {
- mv.visitMethodInsn(opcode, iowner, iname, idesc);
- }
- if (opcode == Opcodes.INVOKEINTERFACE) {
- u += 5;
- } else {
- u += 3;
- }
- break;
- }
- case ClassWriter.INDYMETH_INSN: {
- int cpIndex = items[readUnsignedShort(u + 1)];
- int bsmIndex = context.bootstrapMethods[readUnsignedShort(cpIndex)];
- Handle bsm = (Handle) readConst(readUnsignedShort(bsmIndex), c);
- int bsmArgCount = readUnsignedShort(bsmIndex + 2);
- Object[] bsmArgs = new Object[bsmArgCount];
- bsmIndex += 4;
- for (int i = 0; i < bsmArgCount; i++) {
- bsmArgs[i] = readConst(readUnsignedShort(bsmIndex), c);
- bsmIndex += 2;
- }
- cpIndex = items[readUnsignedShort(cpIndex + 2)];
- String iname = readUTF8(cpIndex, c);
- String idesc = readUTF8(cpIndex + 2, c);
- mv.visitInvokeDynamicInsn(iname, idesc, bsm, bsmArgs);
- u += 5;
- break;
- }
- case ClassWriter.TYPE_INSN:
- mv.visitTypeInsn(opcode, readClass(u + 1, c));
- u += 3;
- break;
- case ClassWriter.IINC_INSN:
- mv.visitIincInsn(b[u + 1] & 0xFF, b[u + 2]);
- u += 3;
- break;
- // case MANA_INSN:
- default:
- mv.visitMultiANewArrayInsn(readClass(u + 1, c), b[u + 3] & 0xFF);
- u += 4;
- break;
- }
- }
- if (labels[codeLength] != null) {
- mv.visitLabel(labels[codeLength]);
- }
-
- // visits the local variable tables
- if ((context.flags & SKIP_DEBUG) == 0 && varTable != 0) {
- int[] typeTable = null;
- if (varTypeTable != 0) {
- u = varTypeTable + 2;
- typeTable = new int[readUnsignedShort(varTypeTable) * 3];
- for (int i = typeTable.length; i > 0;) {
- typeTable[--i] = u + 6; // signature
- typeTable[--i] = readUnsignedShort(u + 8); // index
- typeTable[--i] = readUnsignedShort(u); // start
- u += 10;
- }
- }
- u = varTable + 2;
- for (int i = readUnsignedShort(varTable); i > 0; --i) {
- int start = readUnsignedShort(u);
- int length = readUnsignedShort(u + 2);
- int index = readUnsignedShort(u + 8);
- String vsignature = null;
- if (typeTable != null) {
- for (int j = 0; j < typeTable.length; j += 3) {
- if (typeTable[j] == start && typeTable[j + 1] == index) {
- vsignature = readUTF8(typeTable[j + 2], c);
- break;
- }
- }
- }
- mv.visitLocalVariable(readUTF8(u + 4, c), readUTF8(u + 6, c),
- vsignature, labels[start], labels[start + length],
- index);
- u += 10;
- }
- }
-
- // visits the code attributes
- while (attributes != null) {
- Attribute attr = attributes.next;
- attributes.next = null;
- mv.visitAttribute(attributes);
- attributes = attr;
- }
-
- // visits the max stack and max locals values
- mv.visitMaxs(maxStack, maxLocals);
- }
-
- /**
- * Reads parameter annotations and makes the given visitor visit them.
- *
- * @param v
- * start offset in {@link #b b} of the annotations to be read.
- * @param desc
- * the method descriptor.
- * @param buf
- * buffer to be used to call {@link #readUTF8 readUTF8},
- * {@link #readClass(int,char[]) readClass} or {@link #readConst
- * readConst}.
- * @param visible
- * <tt>true</tt> if the annotations to be read are visible at
- * runtime.
- * @param mv
- * the visitor that must visit the annotations.
- */
- private void readParameterAnnotations(int v, final String desc,
- final char[] buf, final boolean visible, final MethodVisitor mv) {
- int i;
- int n = b[v++] & 0xFF;
- // workaround for a bug in javac (javac compiler generates a parameter
- // annotation array whose size is equal to the number of parameters in
- // the Java source file, while it should generate an array whose size is
- // equal to the number of parameters in the method descriptor - which
- // includes the synthetic parameters added by the compiler). This work-
- // around supposes that the synthetic parameters are the first ones.
- int synthetics = Type.getArgumentTypes(desc).length - n;
- AnnotationVisitor av;
- for (i = 0; i < synthetics; ++i) {
- // virtual annotation to detect synthetic parameters in MethodWriter
- av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false);
- if (av != null) {
- av.visitEnd();
- }
- }
- for (; i < n + synthetics; ++i) {
- int j = readUnsignedShort(v);
- v += 2;
- for (; j > 0; --j) {
- av = mv.visitParameterAnnotation(i, readUTF8(v, buf), visible);
- v = readAnnotationValues(v + 2, buf, true, av);
- }
- }
- }
-
- /**
- * Reads the values of an annotation and makes the given visitor visit them.
- *
- * @param v
- * the start offset in {@link #b b} of the values to be read
- * (including the unsigned short that gives the number of
- * values).
- * @param buf
- * buffer to be used to call {@link #readUTF8 readUTF8},
- * {@link #readClass(int,char[]) readClass} or {@link #readConst
- * readConst}.
- * @param named
- * if the annotation values are named or not.
- * @param av
- * the visitor that must visit the values.
- * @return the end offset of the annotation values.
- */
- private int readAnnotationValues(int v, final char[] buf,
- final boolean named, final AnnotationVisitor av) {
- int i = readUnsignedShort(v);
- v += 2;
- if (named) {
- for (; i > 0; --i) {
- v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av);
- }
- } else {
- for (; i > 0; --i) {
- v = readAnnotationValue(v, buf, null, av);
- }
- }
- if (av != null) {
- av.visitEnd();
- }
- return v;
- }
-
- /**
- * Reads a value of an annotation and makes the given visitor visit it.
- *
- * @param v
- * the start offset in {@link #b b} of the value to be read
- * (<i>not including the value name constant pool index</i>).
- * @param buf
- * buffer to be used to call {@link #readUTF8 readUTF8},
- * {@link #readClass(int,char[]) readClass} or {@link #readConst
- * readConst}.
- * @param name
- * the name of the value to be read.
- * @param av
- * the visitor that must visit the value.
- * @return the end offset of the annotation value.
- */
- private int readAnnotationValue(int v, final char[] buf, final String name,
- final AnnotationVisitor av) {
- int i;
- if (av == null) {
- switch (b[v] & 0xFF) {
- case 'e': // enum_const_value
- return v + 5;
- case '@': // annotation_value
- return readAnnotationValues(v + 3, buf, true, null);
- case '[': // array_value
- return readAnnotationValues(v + 1, buf, false, null);
- default:
- return v + 3;
- }
- }
- switch (b[v++] & 0xFF) {
- case 'I': // pointer to CONSTANT_Integer
- case 'J': // pointer to CONSTANT_Long
- case 'F': // pointer to CONSTANT_Float
- case 'D': // pointer to CONSTANT_Double
- av.visit(name, readConst(readUnsignedShort(v), buf));
- v += 2;
- break;
- case 'B': // pointer to CONSTANT_Byte
- av.visit(name,
- new Byte((byte) readInt(items[readUnsignedShort(v)])));
- v += 2;
- break;
- case 'Z': // pointer to CONSTANT_Boolean
- av.visit(name,
- readInt(items[readUnsignedShort(v)]) == 0 ? Boolean.FALSE
- : Boolean.TRUE);
- v += 2;
- break;
- case 'S': // pointer to CONSTANT_Short
- av.visit(name, new Short(
- (short) readInt(items[readUnsignedShort(v)])));
- v += 2;
- break;
- case 'C': // pointer to CONSTANT_Char
- av.visit(name, new Character(
- (char) readInt(items[readUnsignedShort(v)])));
- v += 2;
- break;
- case 's': // pointer to CONSTANT_Utf8
- av.visit(name, readUTF8(v, buf));
- v += 2;
- break;
- case 'e': // enum_const_value
- av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));
- v += 4;
- break;
- case 'c': // class_info
- av.visit(name, Type.getType(readUTF8(v, buf)));
- v += 2;
- break;
- case '@': // annotation_value
- v = readAnnotationValues(v + 2, buf, true,
- av.visitAnnotation(name, readUTF8(v, buf)));
- break;
- case '[': // array_value
- int size = readUnsignedShort(v);
- v += 2;
- if (size == 0) {
- return readAnnotationValues(v - 2, buf, false,
- av.visitArray(name));
- }
- switch (this.b[v++] & 0xFF) {
- case 'B':
- byte[] bv = new byte[size];
- for (i = 0; i < size; i++) {
- bv[i] = (byte) readInt(items[readUnsignedShort(v)]);
- v += 3;
- }
- av.visit(name, bv);
- --v;
- break;
- case 'Z':
- boolean[] zv = new boolean[size];
- for (i = 0; i < size; i++) {
- zv[i] = readInt(items[readUnsignedShort(v)]) != 0;
- v += 3;
- }
- av.visit(name, zv);
- --v;
- break;
- case 'S':
- short[] sv = new short[size];
- for (i = 0; i < size; i++) {
- sv[i] = (short) readInt(items[readUnsignedShort(v)]);
- v += 3;
- }
- av.visit(name, sv);
- --v;
- break;
- case 'C':
- char[] cv = new char[size];
- for (i = 0; i < size; i++) {
- cv[i] = (char) readInt(items[readUnsignedShort(v)]);
- v += 3;
- }
- av.visit(name, cv);
- --v;
- break;
- case 'I':
- int[] iv = new int[size];
- for (i = 0; i < size; i++) {
- iv[i] = readInt(items[readUnsignedShort(v)]);
- v += 3;
- }
- av.visit(name, iv);
- --v;
- break;
- case 'J':
- long[] lv = new long[size];
- for (i = 0; i < size; i++) {
- lv[i] = readLong(items[readUnsignedShort(v)]);
- v += 3;
- }
- av.visit(name, lv);
- --v;
- break;
- case 'F':
- float[] fv = new float[size];
- for (i = 0; i < size; i++) {
- fv[i] = Float
- .intBitsToFloat(readInt(items[readUnsignedShort(v)]));
- v += 3;
- }
- av.visit(name, fv);
- --v;
- break;
- case 'D':
- double[] dv = new double[size];
- for (i = 0; i < size; i++) {
- dv[i] = Double
- .longBitsToDouble(readLong(items[readUnsignedShort(v)]));
- v += 3;
- }
- av.visit(name, dv);
- --v;
- break;
- default:
- v = readAnnotationValues(v - 3, buf, false, av.visitArray(name));
- }
- }
- return v;
- }
-
- /**
- * Computes the implicit frame of the method currently being parsed (as
- * defined in the given {@link Context}) and stores it in the given context.
- *
- * @param frame
- * information about the class being parsed.
- */
- private void getImplicitFrame(final Context frame) {
- String desc = frame.desc;
- Object[] locals = frame.local;
- int local = 0;
- if ((frame.access & Opcodes.ACC_STATIC) == 0) {
- if ("<init>".equals(frame.name)) {
- locals[local++] = Opcodes.UNINITIALIZED_THIS;
- } else {
- locals[local++] = readClass(header + 2, frame.buffer);
- }
- }
- int i = 1;
- loop: while (true) {
- int j = i;
- switch (desc.charAt(i++)) {
- case 'Z':
- case 'C':
- case 'B':
- case 'S':
- case 'I':
- locals[local++] = Opcodes.INTEGER;
- break;
- case 'F':
- locals[local++] = Opcodes.FLOAT;
- break;
- case 'J':
- locals[local++] = Opcodes.LONG;
- break;
- case 'D':
- locals[local++] = Opcodes.DOUBLE;
- break;
- case '[':
- while (desc.charAt(i) == '[') {
- ++i;
- }
- if (desc.charAt(i) == 'L') {
- ++i;
- while (desc.charAt(i) != ';') {
- ++i;
- }
- }
- locals[local++] = desc.substring(j, ++i);
- break;
- case 'L':
- while (desc.charAt(i) != ';') {
- ++i;
- }
- locals[local++] = desc.substring(j + 1, i++);
- break;
- default:
- break loop;
- }
- }
- frame.localCount = local;
- }
-
- /**
- * Reads a stack map frame and stores the result in the given
- * {@link Context} object.
- *
- * @param stackMap
- * the start offset of a stack map frame in the class file.
- * @param zip
- * if the stack map frame at stackMap is compressed or not.
- * @param unzip
- * if the stack map frame must be uncompressed.
- * @param labels
- * the labels of the method currently being parsed, indexed by
- * their offset. A new label for the parsed stack map frame is
- * stored in this array if it does not already exist.
- * @param frame
- * where the parsed stack map frame must be stored.
- * @return the offset of the first byte following the parsed frame.
- */
- private int readFrame(int stackMap, boolean zip, boolean unzip,
- Label[] labels, Context frame) {
- char[] c = frame.buffer;
- int tag;
- int delta;
- if (zip) {
- tag = b[stackMap++] & 0xFF;
- } else {
- tag = MethodWriter.FULL_FRAME;
- frame.offset = -1;
- }
- frame.localDiff = 0;
- if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME) {
- delta = tag;
- frame.mode = Opcodes.F_SAME;
- frame.stackCount = 0;
- } else if (tag < MethodWriter.RESERVED) {
- delta = tag - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME;
- stackMap = readFrameType(frame.stack, 0, stackMap, c, labels);
- frame.mode = Opcodes.F_SAME1;
- frame.stackCount = 1;
- } else {
- delta = readUnsignedShort(stackMap);
- stackMap += 2;
- if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
- stackMap = readFrameType(frame.stack, 0, stackMap, c, labels);
- frame.mode = Opcodes.F_SAME1;
- frame.stackCount = 1;
- } else if (tag >= MethodWriter.CHOP_FRAME
- && tag < MethodWriter.SAME_FRAME_EXTENDED) {
- frame.mode = Opcodes.F_CHOP;
- frame.localDiff = MethodWriter.SAME_FRAME_EXTENDED - tag;
- frame.localCount -= frame.localDiff;
- frame.stackCount = 0;
- } else if (tag == MethodWriter.SAME_FRAME_EXTENDED) {
- frame.mode = Opcodes.F_SAME;
- frame.stackCount = 0;
- } else if (tag < MethodWriter.FULL_FRAME) {
- int local = unzip ? frame.localCount : 0;
- for (int i = tag - MethodWriter.SAME_FRAME_EXTENDED; i > 0; i--) {
- stackMap = readFrameType(frame.local, local++, stackMap, c,
- labels);
- }
- frame.mode = Opcodes.F_APPEND;
- frame.localDiff = tag - MethodWriter.SAME_FRAME_EXTENDED;
- frame.localCount += frame.localDiff;
- frame.stackCount = 0;
- } else { // if (tag == FULL_FRAME) {
- frame.mode = Opcodes.F_FULL;
- int n = readUnsignedShort(stackMap);
- stackMap += 2;
- frame.localDiff = n;
- frame.localCount = n;
- for (int local = 0; n > 0; n--) {
- stackMap = readFrameType(frame.local, local++, stackMap, c,
- labels);
- }
- n = readUnsignedShort(stackMap);
- stackMap += 2;
- frame.stackCount = n;
- for (int stack = 0; n > 0; n--) {
- stackMap = readFrameType(frame.stack, stack++, stackMap, c,
- labels);
- }
- }
- }
- frame.offset += delta + 1;
- readLabel(frame.offset, labels);
- return stackMap;
- }
-
- /**
- * Reads a stack map frame type and stores it at the given index in the
- * given array.
- *
- * @param frame
- * the array where the parsed type must be stored.
- * @param index
- * the index in 'frame' where the parsed type must be stored.
- * @param v
- * the start offset of the stack map frame type to read.
- * @param buf
- * a buffer to read strings.
- * @param labels
- * the labels of the method currently being parsed, indexed by
- * their offset. If the parsed type is an Uninitialized type, a
- * new label for the corresponding NEW instruction is stored in
- * this array if it does not already exist.
- * @return the offset of the first byte after the parsed type.
- */
- private int readFrameType(final Object[] frame, final int index, int v,
- final char[] buf, final Label[] labels) {
- int type = b[v++] & 0xFF;
- switch (type) {
- case 0:
- frame[index] = Opcodes.TOP;
- break;
- case 1:
- frame[index] = Opcodes.INTEGER;
- break;
- case 2:
- frame[index] = Opcodes.FLOAT;
- break;
- case 3:
- frame[index] = Opcodes.DOUBLE;
- break;
- case 4:
- frame[index] = Opcodes.LONG;
- break;
- case 5:
- frame[index] = Opcodes.NULL;
- break;
- case 6:
- frame[index] = Opcodes.UNINITIALIZED_THIS;
- break;
- case 7: // Object
- frame[index] = readClass(v, buf);
- v += 2;
- break;
- default: // Uninitialized
- frame[index] = readLabel(readUnsignedShort(v), labels);
- v += 2;
- }
- return v;
- }
-
- /**
- * Returns the label corresponding to the given offset. The default
- * implementation of this method creates a label for the given offset if it
- * has not been already created.
- *
- * @param offset
- * a bytecode offset in a method.
- * @param labels
- * the already created labels, indexed by their offset. If a
- * label already exists for offset this method must not create a
- * new one. Otherwise it must store the new label in this array.
- * @return a non null Label, which must be equal to labels[offset].
- */
- protected Label readLabel(int offset, Label[] labels) {
- if (labels[offset] == null) {
- labels[offset] = new Label();
- }
- return labels[offset];
- }
-
- /**
- * Returns the start index of the attribute_info structure of this class.
- *
- * @return the start index of the attribute_info structure of this class.
- */
- private int getAttributes() {
- // skips the header
- int u = header + 8 + readUnsignedShort(header + 6) * 2;
- // skips fields and methods
- for (int i = readUnsignedShort(u); i > 0; --i) {
- for (int j = readUnsignedShort(u + 8); j > 0; --j) {
- u += 6 + readInt(u + 12);
- }
- u += 8;
- }
- u += 2;
- for (int i = readUnsignedShort(u); i > 0; --i) {
- for (int j = readUnsignedShort(u + 8); j > 0; --j) {
- u += 6 + readInt(u + 12);
- }
- u += 8;
- }
- // the attribute_info structure starts just after the methods
- return u + 2;
- }
-
- /**
- * Reads an attribute in {@link #b b}.
- *
- * @param attrs
- * prototypes of the attributes that must be parsed during the
- * visit of the class. Any attribute whose type is not equal to
- * the type of one the prototypes is ignored (i.e. an empty
- * {@link Attribute} instance is returned).
- * @param type
- * the type of the attribute.
- * @param off
- * index of the first byte of the attribute's content in
- * {@link #b b}. The 6 attribute header bytes, containing the
- * type and the length of the attribute, are not taken into
- * account here (they have already been read).
- * @param len
- * the length of the attribute's content.
- * @param buf
- * buffer to be used to call {@link #readUTF8 readUTF8},
- * {@link #readClass(int,char[]) readClass} or {@link #readConst
- * readConst}.
- * @param codeOff
- * index of the first byte of code's attribute content in
- * {@link #b b}, or -1 if the attribute to be read is not a code
- * attribute. The 6 attribute header bytes, containing the type
- * and the length of the attribute, are not taken into account
- * here.
- * @param labels
- * the labels of the method's code, or <tt>null</tt> if the
- * attribute to be read is not a code attribute.
- * @return the attribute that has been read, or <tt>null</tt> to skip this
- * attribute.
- */
- private Attribute readAttribute(final Attribute[] attrs, final String type,
- final int off, final int len, final char[] buf, final int codeOff,
- final Label[] labels) {
- for (int i = 0; i < attrs.length; ++i) {
- if (attrs[i].type.equals(type)) {
- return attrs[i].read(this, off, len, buf, codeOff, labels);
- }
- }
- return new Attribute(type).read(this, off, len, null, -1, null);
- }
-
- // ------------------------------------------------------------------------
- // Utility methods: low level parsing
- // ------------------------------------------------------------------------
-
- /**
- * Returns the number of constant pool items in {@link #b b}.
- *
- * @return the number of constant pool items in {@link #b b}.
- */
- public int getItemCount() {
- return items.length;
- }
-
- /**
- * Returns the start index of the constant pool item in {@link #b b}, plus
- * one. <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param item
- * the index a constant pool item.
- * @return the start index of the constant pool item in {@link #b b}, plus
- * one.
- */
- public int getItem(final int item) {
- return items[item];
- }
-
- /**
- * Returns the maximum length of the strings contained in the constant pool
- * of the class.
- *
- * @return the maximum length of the strings contained in the constant pool
- * of the class.
- */
- public int getMaxStringLength() {
- return maxStringLength;
- }
-
- /**
- * Reads a byte value in {@link #b b}. <i>This method is intended for
- * {@link Attribute} sub classes, and is normally not needed by class
- * generators or adapters.</i>
- *
- * @param index
- * the start index of the value to be read in {@link #b b}.
- * @return the read value.
- */
- public int readByte(final int index) {
- return b[index] & 0xFF;
- }
-
- /**
- * Reads an unsigned short value in {@link #b b}. <i>This method is intended
- * for {@link Attribute} sub classes, and is normally not needed by class
- * generators or adapters.</i>
- *
- * @param index
- * the start index of the value to be read in {@link #b b}.
- * @return the read value.
- */
- public int readUnsignedShort(final int index) {
- byte[] b = this.b;
- return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
- }
-
- /**
- * Reads a signed short value in {@link #b b}. <i>This method is intended
- * for {@link Attribute} sub classes, and is normally not needed by class
- * generators or adapters.</i>
- *
- * @param index
- * the start index of the value to be read in {@link #b b}.
- * @return the read value.
- */
- public short readShort(final int index) {
- byte[] b = this.b;
- return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
- }
-
- /**
- * Reads a signed int value in {@link #b b}. <i>This method is intended for
- * {@link Attribute} sub classes, and is normally not needed by class
- * generators or adapters.</i>
- *
- * @param index
- * the start index of the value to be read in {@link #b b}.
- * @return the read value.
- */
- public int readInt(final int index) {
- byte[] b = this.b;
- return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)
- | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
- }
-
- /**
- * Reads a signed long value in {@link #b b}. <i>This method is intended for
- * {@link Attribute} sub classes, and is normally not needed by class
- * generators or adapters.</i>
- *
- * @param index
- * the start index of the value to be read in {@link #b b}.
- * @return the read value.
- */
- public long readLong(final int index) {
- long l1 = readInt(index);
- long l0 = readInt(index + 4) & 0xFFFFFFFFL;
- return (l1 << 32) | l0;
- }
-
- /**
- * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method
- * is intended for {@link Attribute} sub classes, and is normally not needed
- * by class generators or adapters.</i>
- *
- * @param index
- * the start index of an unsigned short value in {@link #b b},
- * whose value is the index of an UTF8 constant pool item.
- * @param buf
- * buffer to be used to read the item. This buffer must be
- * sufficiently large. It is not automatically resized.
- * @return the String corresponding to the specified UTF8 item.
- */
- public String readUTF8(int index, final char[] buf) {
- int item = readUnsignedShort(index);
- if (index == 0 || item == 0) {
- return null;
- }
- String s = strings[item];
- if (s != null) {
- return s;
- }
- index = items[item];
- return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf);
- }
-
- /**
- * Reads UTF8 string in {@link #b b}.
- *
- * @param index
- * start offset of the UTF8 string to be read.
- * @param utfLen
- * length of the UTF8 string to be read.
- * @param buf
- * buffer to be used to read the string. This buffer must be
- * sufficiently large. It is not automatically resized.
- * @return the String corresponding to the specified UTF8 string.
- */
- private String readUTF(int index, final int utfLen, final char[] buf) {
- int endIndex = index + utfLen;
- byte[] b = this.b;
- int strLen = 0;
- int c;
- int st = 0;
- char cc = 0;
- while (index < endIndex) {
- c = b[index++];
- switch (st) {
- case 0:
- c = c & 0xFF;
- if (c < 0x80) { // 0xxxxxxx
- buf[strLen++] = (char) c;
- } else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx
- cc = (char) (c & 0x1F);
- st = 1;
- } else { // 1110 xxxx 10xx xxxx 10xx xxxx
- cc = (char) (c & 0x0F);
- st = 2;
- }
- break;
-
- case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char
- buf[strLen++] = (char) ((cc << 6) | (c & 0x3F));
- st = 0;
- break;
-
- case 2: // byte 2 of 3-byte char
- cc = (char) ((cc << 6) | (c & 0x3F));
- st = 1;
- break;
- }
- }
- return new String(buf, 0, strLen);
- }
-
- /**
- * Reads a class constant pool item in {@link #b b}. <i>This method is
- * intended for {@link Attribute} sub classes, and is normally not needed by
- * class generators or adapters.</i>
- *
- * @param index
- * the start index of an unsigned short value in {@link #b b},
- * whose value is the index of a class constant pool item.
- * @param buf
- * buffer to be used to read the item. This buffer must be
- * sufficiently large. It is not automatically resized.
- * @return the String corresponding to the specified class item.
- */
- public String readClass(final int index, final char[] buf) {
- // computes the start index of the CONSTANT_Class item in b
- // and reads the CONSTANT_Utf8 item designated by
- // the first two bytes of this CONSTANT_Class item
- return readUTF8(items[readUnsignedShort(index)], buf);
- }
-
- /**
- * Reads a numeric or string constant pool item in {@link #b b}. <i>This
- * method is intended for {@link Attribute} sub classes, and is normally not
- * needed by class generators or adapters.</i>
- *
- * @param item
- * the index of a constant pool item.
- * @param buf
- * buffer to be used to read the item. This buffer must be
- * sufficiently large. It is not automatically resized.
- * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double},
- * {@link String}, {@link Type} or {@link Handle} corresponding to
- * the given constant pool item.
- */
- public Object readConst(final int item, final char[] buf) {
- int index = items[item];
- switch (b[index - 1]) {
- case ClassWriter.INT:
- return new Integer(readInt(index));
- case ClassWriter.FLOAT:
- return new Float(Float.intBitsToFloat(readInt(index)));
- case ClassWriter.LONG:
- return new Long(readLong(index));
- case ClassWriter.DOUBLE:
- return new Double(Double.longBitsToDouble(readLong(index)));
- case ClassWriter.CLASS:
- return Type.getObjectType(readUTF8(index, buf));
- case ClassWriter.STR:
- return readUTF8(index, buf);
- case ClassWriter.MTYPE:
- return Type.getMethodType(readUTF8(index, buf));
- default: // case ClassWriter.HANDLE_BASE + [1..9]:
- int tag = readByte(index);
- int[] items = this.items;
- int cpIndex = items[readUnsignedShort(index + 1)];
- String owner = readClass(cpIndex, buf);
- cpIndex = items[readUnsignedShort(cpIndex + 2)];
- String name = readUTF8(cpIndex, buf);
- String desc = readUTF8(cpIndex + 2, buf);
- return new Handle(tag, owner, name, desc);
- }
- }
-}
diff --git a/src/jvm/clojure/asm/ClassVisitor.java b/src/jvm/clojure/asm/ClassVisitor.java
deleted file mode 100644
index bc5919b..0000000
--- a/src/jvm/clojure/asm/ClassVisitor.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-/**
- * A visitor to visit a Java class. The methods of this class must be called in
- * the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
- * <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
- * <tt>visitAttribute</tt> )* ( <tt>visitInnerClass</tt> | <tt>visitField</tt> |
- * <tt>visitMethod</tt> )* <tt>visitEnd</tt>.
- *
- * @author Eric Bruneton
- */
-public abstract class ClassVisitor {
-
- /**
- * The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4}.
- */
- protected final int api;
-
- /**
- * The class visitor to which this visitor must delegate method calls. May
- * be null.
- */
- protected ClassVisitor cv;
-
- /**
- * Constructs a new {@link ClassVisitor}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- */
- public ClassVisitor(final int api) {
- this(api, null);
- }
-
- /**
- * Constructs a new {@link ClassVisitor}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param cv
- * the class visitor to which this visitor must delegate method
- * calls. May be null.
- */
- public ClassVisitor(final int api, final ClassVisitor cv) {
- if (api != Opcodes.ASM4) {
- throw new IllegalArgumentException();
- }
- this.api = api;
- this.cv = cv;
- }
-
- /**
- * Visits the header of the class.
- *
- * @param version
- * the class version.
- * @param access
- * the class's access flags (see {@link Opcodes}). This parameter
- * also indicates if the class is deprecated.
- * @param name
- * the internal name of the class (see
- * {@link Type#getInternalName() getInternalName}).
- * @param signature
- * the signature of this class. May be <tt>null</tt> if the class
- * is not a generic one, and does not extend or implement generic
- * classes or interfaces.
- * @param superName
- * the internal of name of the super class (see
- * {@link Type#getInternalName() getInternalName}). For
- * interfaces, the super class is {@link Object}. May be
- * <tt>null</tt>, but only for the {@link Object} class.
- * @param interfaces
- * the internal names of the class's interfaces (see
- * {@link Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
- */
- public void visit(int version, int access, String name, String signature,
- String superName, String[] interfaces) {
- if (cv != null) {
- cv.visit(version, access, name, signature, superName, interfaces);
- }
- }
-
- /**
- * Visits the source of the class.
- *
- * @param source
- * the name of the source file from which the class was compiled.
- * May be <tt>null</tt>.
- * @param debug
- * additional debug information to compute the correspondance
- * between source and compiled elements of the class. May be
- * <tt>null</tt>.
- */
- public void visitSource(String source, String debug) {
- if (cv != null) {
- cv.visitSource(source, debug);
- }
- }
-
- /**
- * Visits the enclosing class of the class. This method must be called only
- * if the class has an enclosing class.
- *
- * @param owner
- * internal name of the enclosing class of the class.
- * @param name
- * the name of the method that contains the class, or
- * <tt>null</tt> if the class is not enclosed in a method of its
- * enclosing class.
- * @param desc
- * the descriptor of the method that contains the class, or
- * <tt>null</tt> if the class is not enclosed in a method of its
- * enclosing class.
- */
- public void visitOuterClass(String owner, String name, String desc) {
- if (cv != null) {
- cv.visitOuterClass(owner, name, desc);
- }
- }
-
- /**
- * Visits an annotation of the class.
- *
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return a visitor to visit the annotation values, or <tt>null</tt> if
- * this visitor is not interested in visiting this annotation.
- */
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- if (cv != null) {
- return cv.visitAnnotation(desc, visible);
- }
- return null;
- }
-
- /**
- * Visits a non standard attribute of the class.
- *
- * @param attr
- * an attribute.
- */
- public void visitAttribute(Attribute attr) {
- if (cv != null) {
- cv.visitAttribute(attr);
- }
- }
-
- /**
- * Visits information about an inner class. This inner class is not
- * necessarily a member of the class being visited.
- *
- * @param name
- * the internal name of an inner class (see
- * {@link Type#getInternalName() getInternalName}).
- * @param outerName
- * the internal name of the class to which the inner class
- * belongs (see {@link Type#getInternalName() getInternalName}).
- * May be <tt>null</tt> for not member classes.
- * @param innerName
- * the (simple) name of the inner class inside its enclosing
- * class. May be <tt>null</tt> for anonymous inner classes.
- * @param access
- * the access flags of the inner class as originally declared in
- * the enclosing class.
- */
- public void visitInnerClass(String name, String outerName,
- String innerName, int access) {
- if (cv != null) {
- cv.visitInnerClass(name, outerName, innerName, access);
- }
- }
-
- /**
- * Visits a field of the class.
- *
- * @param access
- * the field's access flags (see {@link Opcodes}). This parameter
- * also indicates if the field is synthetic and/or deprecated.
- * @param name
- * the field's name.
- * @param desc
- * the field's descriptor (see {@link Type Type}).
- * @param signature
- * the field's signature. May be <tt>null</tt> if the field's
- * type does not use generic types.
- * @param value
- * the field's initial value. This parameter, which may be
- * <tt>null</tt> if the field does not have an initial value,
- * must be an {@link Integer}, a {@link Float}, a {@link Long}, a
- * {@link Double} or a {@link String} (for <tt>int</tt>,
- * <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields
- * respectively). <i>This parameter is only used for static
- * fields</i>. Its value is ignored for non static fields, which
- * must be initialized through bytecode instructions in
- * constructors or methods.
- * @return a visitor to visit field annotations and attributes, or
- * <tt>null</tt> if this class visitor is not interested in visiting
- * these annotations and attributes.
- */
- public FieldVisitor visitField(int access, String name, String desc,
- String signature, Object value) {
- if (cv != null) {
- return cv.visitField(access, name, desc, signature, value);
- }
- return null;
- }
-
- /**
- * Visits a method of the class. This method <i>must</i> return a new
- * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is called,
- * i.e., it should not return a previously returned visitor.
- *
- * @param access
- * the method's access flags (see {@link Opcodes}). This
- * parameter also indicates if the method is synthetic and/or
- * deprecated.
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- * @param signature
- * the method's signature. May be <tt>null</tt> if the method
- * parameters, return type and exceptions do not use generic
- * types.
- * @param exceptions
- * the internal names of the method's exception classes (see
- * {@link Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
- * @return an object to visit the byte code of the method, or <tt>null</tt>
- * if this class visitor is not interested in visiting the code of
- * this method.
- */
- public MethodVisitor visitMethod(int access, String name, String desc,
- String signature, String[] exceptions) {
- if (cv != null) {
- return cv.visitMethod(access, name, desc, signature, exceptions);
- }
- return null;
- }
-
- /**
- * Visits the end of the class. This method, which is the last one to be
- * called, is used to inform the visitor that all the fields and methods of
- * the class have been visited.
- */
- public void visitEnd() {
- if (cv != null) {
- cv.visitEnd();
- }
- }
-}
diff --git a/src/jvm/clojure/asm/ClassWriter.java b/src/jvm/clojure/asm/ClassWriter.java
deleted file mode 100644
index 3d78868..0000000
--- a/src/jvm/clojure/asm/ClassWriter.java
+++ /dev/null
@@ -1,1693 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-/**
- * A {@link ClassVisitor} that generates classes in bytecode form. More
- * precisely this visitor generates a byte array conforming to the Java class
- * file format. It can be used alone, to generate a Java class "from scratch",
- * or with one or more {@link ClassReader ClassReader} and adapter class visitor
- * to generate a modified class from one or more existing Java classes.
- *
- * @author Eric Bruneton
- */
-public class ClassWriter extends ClassVisitor {
-
- /**
- * Flag to automatically compute the maximum stack size and the maximum
- * number of local variables of methods. If this flag is set, then the
- * arguments of the {@link MethodVisitor#visitMaxs visitMaxs} method of the
- * {@link MethodVisitor} returned by the {@link #visitMethod visitMethod}
- * method will be ignored, and computed automatically from the signature and
- * the bytecode of each method.
- *
- * @see #ClassWriter(int)
- */
- public static final int COMPUTE_MAXS = 1;
-
- /**
- * Flag to automatically compute the stack map frames of methods from
- * scratch. If this flag is set, then the calls to the
- * {@link MethodVisitor#visitFrame} method are ignored, and the stack map
- * frames are recomputed from the methods bytecode. The arguments of the
- * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
- * recomputed from the bytecode. In other words, computeFrames implies
- * computeMaxs.
- *
- * @see #ClassWriter(int)
- */
- public static final int COMPUTE_FRAMES = 2;
-
- /**
- * Pseudo access flag to distinguish between the synthetic attribute and the
- * synthetic access flag.
- */
- static final int ACC_SYNTHETIC_ATTRIBUTE = 0x40000;
-
- /**
- * Factor to convert from ACC_SYNTHETIC_ATTRIBUTE to Opcode.ACC_SYNTHETIC.
- */
- static final int TO_ACC_SYNTHETIC = ACC_SYNTHETIC_ATTRIBUTE
- / Opcodes.ACC_SYNTHETIC;
-
- /**
- * The type of instructions without any argument.
- */
- static final int NOARG_INSN = 0;
-
- /**
- * The type of instructions with an signed byte argument.
- */
- static final int SBYTE_INSN = 1;
-
- /**
- * The type of instructions with an signed short argument.
- */
- static final int SHORT_INSN = 2;
-
- /**
- * The type of instructions with a local variable index argument.
- */
- static final int VAR_INSN = 3;
-
- /**
- * The type of instructions with an implicit local variable index argument.
- */
- static final int IMPLVAR_INSN = 4;
-
- /**
- * The type of instructions with a type descriptor argument.
- */
- static final int TYPE_INSN = 5;
-
- /**
- * The type of field and method invocations instructions.
- */
- static final int FIELDORMETH_INSN = 6;
-
- /**
- * The type of the INVOKEINTERFACE/INVOKEDYNAMIC instruction.
- */
- static final int ITFMETH_INSN = 7;
-
- /**
- * The type of the INVOKEDYNAMIC instruction.
- */
- static final int INDYMETH_INSN = 8;
-
- /**
- * The type of instructions with a 2 bytes bytecode offset label.
- */
- static final int LABEL_INSN = 9;
-
- /**
- * The type of instructions with a 4 bytes bytecode offset label.
- */
- static final int LABELW_INSN = 10;
-
- /**
- * The type of the LDC instruction.
- */
- static final int LDC_INSN = 11;
-
- /**
- * The type of the LDC_W and LDC2_W instructions.
- */
- static final int LDCW_INSN = 12;
-
- /**
- * The type of the IINC instruction.
- */
- static final int IINC_INSN = 13;
-
- /**
- * The type of the TABLESWITCH instruction.
- */
- static final int TABL_INSN = 14;
-
- /**
- * The type of the LOOKUPSWITCH instruction.
- */
- static final int LOOK_INSN = 15;
-
- /**
- * The type of the MULTIANEWARRAY instruction.
- */
- static final int MANA_INSN = 16;
-
- /**
- * The type of the WIDE instruction.
- */
- static final int WIDE_INSN = 17;
-
- /**
- * The instruction types of all JVM opcodes.
- */
- static final byte[] TYPE;
-
- /**
- * The type of CONSTANT_Class constant pool items.
- */
- static final int CLASS = 7;
-
- /**
- * The type of CONSTANT_Fieldref constant pool items.
- */
- static final int FIELD = 9;
-
- /**
- * The type of CONSTANT_Methodref constant pool items.
- */
- static final int METH = 10;
-
- /**
- * The type of CONSTANT_InterfaceMethodref constant pool items.
- */
- static final int IMETH = 11;
-
- /**
- * The type of CONSTANT_String constant pool items.
- */
- static final int STR = 8;
-
- /**
- * The type of CONSTANT_Integer constant pool items.
- */
- static final int INT = 3;
-
- /**
- * The type of CONSTANT_Float constant pool items.
- */
- static final int FLOAT = 4;
-
- /**
- * The type of CONSTANT_Long constant pool items.
- */
- static final int LONG = 5;
-
- /**
- * The type of CONSTANT_Double constant pool items.
- */
- static final int DOUBLE = 6;
-
- /**
- * The type of CONSTANT_NameAndType constant pool items.
- */
- static final int NAME_TYPE = 12;
-
- /**
- * The type of CONSTANT_Utf8 constant pool items.
- */
- static final int UTF8 = 1;
-
- /**
- * The type of CONSTANT_MethodType constant pool items.
- */
- static final int MTYPE = 16;
-
- /**
- * The type of CONSTANT_MethodHandle constant pool items.
- */
- static final int HANDLE = 15;
-
- /**
- * The type of CONSTANT_InvokeDynamic constant pool items.
- */
- static final int INDY = 18;
-
- /**
- * The base value for all CONSTANT_MethodHandle constant pool items.
- * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9
- * different items.
- */
- static final int HANDLE_BASE = 20;
-
- /**
- * Normal type Item stored in the ClassWriter {@link ClassWriter#typeTable},
- * instead of the constant pool, in order to avoid clashes with normal
- * constant pool items in the ClassWriter constant pool's hash table.
- */
- static final int TYPE_NORMAL = 30;
-
- /**
- * Uninitialized type Item stored in the ClassWriter
- * {@link ClassWriter#typeTable}, instead of the constant pool, in order to
- * avoid clashes with normal constant pool items in the ClassWriter constant
- * pool's hash table.
- */
- static final int TYPE_UNINIT = 31;
-
- /**
- * Merged type Item stored in the ClassWriter {@link ClassWriter#typeTable},
- * instead of the constant pool, in order to avoid clashes with normal
- * constant pool items in the ClassWriter constant pool's hash table.
- */
- static final int TYPE_MERGED = 32;
-
- /**
- * The type of BootstrapMethods items. These items are stored in a special
- * class attribute named BootstrapMethods and not in the constant pool.
- */
- static final int BSM = 33;
-
- /**
- * The class reader from which this class writer was constructed, if any.
- */
- ClassReader cr;
-
- /**
- * Minor and major version numbers of the class to be generated.
- */
- int version;
-
- /**
- * Index of the next item to be added in the constant pool.
- */
- int index;
-
- /**
- * The constant pool of this class.
- */
- final ByteVector pool;
-
- /**
- * The constant pool's hash table data.
- */
- Item[] items;
-
- /**
- * The threshold of the constant pool's hash table.
- */
- int threshold;
-
- /**
- * A reusable key used to look for items in the {@link #items} hash table.
- */
- final Item key;
-
- /**
- * A reusable key used to look for items in the {@link #items} hash table.
- */
- final Item key2;
-
- /**
- * A reusable key used to look for items in the {@link #items} hash table.
- */
- final Item key3;
-
- /**
- * A reusable key used to look for items in the {@link #items} hash table.
- */
- final Item key4;
-
- /**
- * A type table used to temporarily store internal names that will not
- * necessarily be stored in the constant pool. This type table is used by
- * the control flow and data flow analysis algorithm used to compute stack
- * map frames from scratch. This array associates to each index <tt>i</tt>
- * the Item whose index is <tt>i</tt>. All Item objects stored in this array
- * are also stored in the {@link #items} hash table. These two arrays allow
- * to retrieve an Item from its index or, conversely, to get the index of an
- * Item from its value. Each Item stores an internal name in its
- * {@link Item#strVal1} field.
- */
- Item[] typeTable;
-
- /**
- * Number of elements in the {@link #typeTable} array.
- */
- private short typeCount;
-
- /**
- * The access flags of this class.
- */
- private int access;
-
- /**
- * The constant pool item that contains the internal name of this class.
- */
- private int name;
-
- /**
- * The internal name of this class.
- */
- String thisName;
-
- /**
- * The constant pool item that contains the signature of this class.
- */
- private int signature;
-
- /**
- * The constant pool item that contains the internal name of the super class
- * of this class.
- */
- private int superName;
-
- /**
- * Number of interfaces implemented or extended by this class or interface.
- */
- private int interfaceCount;
-
- /**
- * The interfaces implemented or extended by this class or interface. More
- * precisely, this array contains the indexes of the constant pool items
- * that contain the internal names of these interfaces.
- */
- private int[] interfaces;
-
- /**
- * The index of the constant pool item that contains the name of the source
- * file from which this class was compiled.
- */
- private int sourceFile;
-
- /**
- * The SourceDebug attribute of this class.
- */
- private ByteVector sourceDebug;
-
- /**
- * The constant pool item that contains the name of the enclosing class of
- * this class.
- */
- private int enclosingMethodOwner;
-
- /**
- * The constant pool item that contains the name and descriptor of the
- * enclosing method of this class.
- */
- private int enclosingMethod;
-
- /**
- * The runtime visible annotations of this class.
- */
- private AnnotationWriter anns;
-
- /**
- * The runtime invisible annotations of this class.
- */
- private AnnotationWriter ianns;
-
- /**
- * The non standard attributes of this class.
- */
- private Attribute attrs;
-
- /**
- * The number of entries in the InnerClasses attribute.
- */
- private int innerClassesCount;
-
- /**
- * The InnerClasses attribute.
- */
- private ByteVector innerClasses;
-
- /**
- * The number of entries in the BootstrapMethods attribute.
- */
- int bootstrapMethodsCount;
-
- /**
- * The BootstrapMethods attribute.
- */
- ByteVector bootstrapMethods;
-
- /**
- * The fields of this class. These fields are stored in a linked list of
- * {@link FieldWriter} objects, linked to each other by their
- * {@link FieldWriter#fv} field. This field stores the first element of this
- * list.
- */
- FieldWriter firstField;
-
- /**
- * The fields of this class. These fields are stored in a linked list of
- * {@link FieldWriter} objects, linked to each other by their
- * {@link FieldWriter#fv} field. This field stores the last element of this
- * list.
- */
- FieldWriter lastField;
-
- /**
- * The methods of this class. These methods are stored in a linked list of
- * {@link MethodWriter} objects, linked to each other by their
- * {@link MethodWriter#mv} field. This field stores the first element of
- * this list.
- */
- MethodWriter firstMethod;
-
- /**
- * The methods of this class. These methods are stored in a linked list of
- * {@link MethodWriter} objects, linked to each other by their
- * {@link MethodWriter#mv} field. This field stores the last element of this
- * list.
- */
- MethodWriter lastMethod;
-
- /**
- * <tt>true</tt> if the maximum stack size and number of local variables
- * must be automatically computed.
- */
- private final boolean computeMaxs;
-
- /**
- * <tt>true</tt> if the stack map frames must be recomputed from scratch.
- */
- private final boolean computeFrames;
-
- /**
- * <tt>true</tt> if the stack map tables of this class are invalid. The
- * {@link MethodWriter#resizeInstructions} method cannot transform existing
- * stack map tables, and so produces potentially invalid classes when it is
- * executed. In this case the class is reread and rewritten with the
- * {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize
- * stack map tables when this option is used).
- */
- boolean invalidFrames;
-
- // ------------------------------------------------------------------------
- // Static initializer
- // ------------------------------------------------------------------------
-
- /**
- * Computes the instruction types of JVM opcodes.
- */
- static {
- int i;
- byte[] b = new byte[220];
- String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"
- + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
- + "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA"
- + "AAAAGGGGGGGHIFBFAAFFAARQJJKKJJJJJJJJJJJJJJJJJJ";
- for (i = 0; i < b.length; ++i) {
- b[i] = (byte) (s.charAt(i) - 'A');
- }
- TYPE = b;
-
- // code to generate the above string
- //
- // // SBYTE_INSN instructions
- // b[Constants.NEWARRAY] = SBYTE_INSN;
- // b[Constants.BIPUSH] = SBYTE_INSN;
- //
- // // SHORT_INSN instructions
- // b[Constants.SIPUSH] = SHORT_INSN;
- //
- // // (IMPL)VAR_INSN instructions
- // b[Constants.RET] = VAR_INSN;
- // for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) {
- // b[i] = VAR_INSN;
- // }
- // for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) {
- // b[i] = VAR_INSN;
- // }
- // for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3
- // b[i] = IMPLVAR_INSN;
- // }
- // for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3
- // b[i] = IMPLVAR_INSN;
- // }
- //
- // // TYPE_INSN instructions
- // b[Constants.NEW] = TYPE_INSN;
- // b[Constants.ANEWARRAY] = TYPE_INSN;
- // b[Constants.CHECKCAST] = TYPE_INSN;
- // b[Constants.INSTANCEOF] = TYPE_INSN;
- //
- // // (Set)FIELDORMETH_INSN instructions
- // for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) {
- // b[i] = FIELDORMETH_INSN;
- // }
- // b[Constants.INVOKEINTERFACE] = ITFMETH_INSN;
- // b[Constants.INVOKEDYNAMIC] = INDYMETH_INSN;
- //
- // // LABEL(W)_INSN instructions
- // for (i = Constants.IFEQ; i <= Constants.JSR; ++i) {
- // b[i] = LABEL_INSN;
- // }
- // b[Constants.IFNULL] = LABEL_INSN;
- // b[Constants.IFNONNULL] = LABEL_INSN;
- // b[200] = LABELW_INSN; // GOTO_W
- // b[201] = LABELW_INSN; // JSR_W
- // // temporary opcodes used internally by ASM - see Label and
- // MethodWriter
- // for (i = 202; i < 220; ++i) {
- // b[i] = LABEL_INSN;
- // }
- //
- // // LDC(_W) instructions
- // b[Constants.LDC] = LDC_INSN;
- // b[19] = LDCW_INSN; // LDC_W
- // b[20] = LDCW_INSN; // LDC2_W
- //
- // // special instructions
- // b[Constants.IINC] = IINC_INSN;
- // b[Constants.TABLESWITCH] = TABL_INSN;
- // b[Constants.LOOKUPSWITCH] = LOOK_INSN;
- // b[Constants.MULTIANEWARRAY] = MANA_INSN;
- // b[196] = WIDE_INSN; // WIDE
- //
- // for (i = 0; i < b.length; ++i) {
- // System.err.print((char)('A' + b[i]));
- // }
- // System.err.println();
- }
-
- // ------------------------------------------------------------------------
- // Constructor
- // ------------------------------------------------------------------------
-
- /**
- * Constructs a new {@link ClassWriter} object.
- *
- * @param flags
- * option flags that can be used to modify the default behavior
- * of this class. See {@link #COMPUTE_MAXS},
- * {@link #COMPUTE_FRAMES}.
- */
- public ClassWriter(final int flags) {
- super(Opcodes.ASM4);
- index = 1;
- pool = new ByteVector();
- items = new Item[256];
- threshold = (int) (0.75d * items.length);
- key = new Item();
- key2 = new Item();
- key3 = new Item();
- key4 = new Item();
- this.computeMaxs = (flags & COMPUTE_MAXS) != 0;
- this.computeFrames = (flags & COMPUTE_FRAMES) != 0;
- }
-
- /**
- * Constructs a new {@link ClassWriter} object and enables optimizations for
- * "mostly add" bytecode transformations. These optimizations are the
- * following:
- *
- * <ul>
- * <li>The constant pool from the original class is copied as is in the new
- * class, which saves time. New constant pool entries will be added at the
- * end if necessary, but unused constant pool entries <i>won't be
- * removed</i>.</li>
- * <li>Methods that are not transformed are copied as is in the new class,
- * directly from the original class bytecode (i.e. without emitting visit
- * events for all the method instructions), which saves a <i>lot</i> of
- * time. Untransformed methods are detected by the fact that the
- * {@link ClassReader} receives {@link MethodVisitor} objects that come from
- * a {@link ClassWriter} (and not from any other {@link ClassVisitor}
- * instance).</li>
- * </ul>
- *
- * @param classReader
- * the {@link ClassReader} used to read the original class. It
- * will be used to copy the entire constant pool from the
- * original class and also to copy other fragments of original
- * bytecode where applicable.
- * @param flags
- * option flags that can be used to modify the default behavior
- * of this class. <i>These option flags do not affect methods
- * that are copied as is in the new class. This means that the
- * maximum stack size nor the stack frames will be computed for
- * these methods</i>. See {@link #COMPUTE_MAXS},
- * {@link #COMPUTE_FRAMES}.
- */
- public ClassWriter(final ClassReader classReader, final int flags) {
- this(flags);
- classReader.copyPool(this);
- this.cr = classReader;
- }
-
- // ------------------------------------------------------------------------
- // Implementation of the ClassVisitor abstract class
- // ------------------------------------------------------------------------
-
- @Override
- public final void visit(final int version, final int access,
- final String name, final String signature, final String superName,
- final String[] interfaces) {
- this.version = version;
- this.access = access;
- this.name = newClass(name);
- thisName = name;
- if (ClassReader.SIGNATURES && signature != null) {
- this.signature = newUTF8(signature);
- }
- this.superName = superName == null ? 0 : newClass(superName);
- if (interfaces != null && interfaces.length > 0) {
- interfaceCount = interfaces.length;
- this.interfaces = new int[interfaceCount];
- for (int i = 0; i < interfaceCount; ++i) {
- this.interfaces[i] = newClass(interfaces[i]);
- }
- }
- }
-
- @Override
- public final void visitSource(final String file, final String debug) {
- if (file != null) {
- sourceFile = newUTF8(file);
- }
- if (debug != null) {
- sourceDebug = new ByteVector().putUTF8(debug);
- }
- }
-
- @Override
- public final void visitOuterClass(final String owner, final String name,
- final String desc) {
- enclosingMethodOwner = newClass(owner);
- if (name != null && desc != null) {
- enclosingMethod = newNameType(name, desc);
- }
- }
-
- @Override
- public final AnnotationVisitor visitAnnotation(final String desc,
- final boolean visible) {
- if (!ClassReader.ANNOTATIONS) {
- return null;
- }
- ByteVector bv = new ByteVector();
- // write type, and reserve space for values count
- bv.putShort(newUTF8(desc)).putShort(0);
- AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2);
- if (visible) {
- aw.next = anns;
- anns = aw;
- } else {
- aw.next = ianns;
- ianns = aw;
- }
- return aw;
- }
-
- @Override
- public final void visitAttribute(final Attribute attr) {
- attr.next = attrs;
- attrs = attr;
- }
-
- @Override
- public final void visitInnerClass(final String name,
- final String outerName, final String innerName, final int access) {
- if (innerClasses == null) {
- innerClasses = new ByteVector();
- }
- ++innerClassesCount;
- innerClasses.putShort(name == null ? 0 : newClass(name));
- innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
- innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
- innerClasses.putShort(access);
- }
-
- @Override
- public final FieldVisitor visitField(final int access, final String name,
- final String desc, final String signature, final Object value) {
- return new FieldWriter(this, access, name, desc, signature, value);
- }
-
- @Override
- public final MethodVisitor visitMethod(final int access, final String name,
- final String desc, final String signature, final String[] exceptions) {
- return new MethodWriter(this, access, name, desc, signature,
- exceptions, computeMaxs, computeFrames);
- }
-
- @Override
- public final void visitEnd() {
- }
-
- // ------------------------------------------------------------------------
- // Other public methods
- // ------------------------------------------------------------------------
-
- /**
- * Returns the bytecode of the class that was build with this class writer.
- *
- * @return the bytecode of the class that was build with this class writer.
- */
- public byte[] toByteArray() {
- if (index > 0xFFFF) {
- throw new RuntimeException("Class file too large!");
- }
- // computes the real size of the bytecode of this class
- int size = 24 + 2 * interfaceCount;
- int nbFields = 0;
- FieldWriter fb = firstField;
- while (fb != null) {
- ++nbFields;
- size += fb.getSize();
- fb = (FieldWriter) fb.fv;
- }
- int nbMethods = 0;
- MethodWriter mb = firstMethod;
- while (mb != null) {
- ++nbMethods;
- size += mb.getSize();
- mb = (MethodWriter) mb.mv;
- }
- int attributeCount = 0;
- if (bootstrapMethods != null) {
- // we put it as first attribute in order to improve a bit
- // ClassReader.copyBootstrapMethods
- ++attributeCount;
- size += 8 + bootstrapMethods.length;
- newUTF8("BootstrapMethods");
- }
- if (ClassReader.SIGNATURES && signature != 0) {
- ++attributeCount;
- size += 8;
- newUTF8("Signature");
- }
- if (sourceFile != 0) {
- ++attributeCount;
- size += 8;
- newUTF8("SourceFile");
- }
- if (sourceDebug != null) {
- ++attributeCount;
- size += sourceDebug.length + 4;
- newUTF8("SourceDebugExtension");
- }
- if (enclosingMethodOwner != 0) {
- ++attributeCount;
- size += 10;
- newUTF8("EnclosingMethod");
- }
- if ((access & Opcodes.ACC_DEPRECATED) != 0) {
- ++attributeCount;
- size += 6;
- newUTF8("Deprecated");
- }
- if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
- if ((version & 0xFFFF) < Opcodes.V1_5
- || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) {
- ++attributeCount;
- size += 6;
- newUTF8("Synthetic");
- }
- }
- if (innerClasses != null) {
- ++attributeCount;
- size += 8 + innerClasses.length;
- newUTF8("InnerClasses");
- }
- if (ClassReader.ANNOTATIONS && anns != null) {
- ++attributeCount;
- size += 8 + anns.getSize();
- newUTF8("RuntimeVisibleAnnotations");
- }
- if (ClassReader.ANNOTATIONS && ianns != null) {
- ++attributeCount;
- size += 8 + ianns.getSize();
- newUTF8("RuntimeInvisibleAnnotations");
- }
- if (attrs != null) {
- attributeCount += attrs.getCount();
- size += attrs.getSize(this, null, 0, -1, -1);
- }
- size += pool.length;
- // allocates a byte vector of this size, in order to avoid unnecessary
- // arraycopy operations in the ByteVector.enlarge() method
- ByteVector out = new ByteVector(size);
- out.putInt(0xCAFEBABE).putInt(version);
- out.putShort(index).putByteArray(pool.data, 0, pool.length);
- int mask = Opcodes.ACC_DEPRECATED | ACC_SYNTHETIC_ATTRIBUTE
- | ((access & ACC_SYNTHETIC_ATTRIBUTE) / TO_ACC_SYNTHETIC);
- out.putShort(access & ~mask).putShort(name).putShort(superName);
- out.putShort(interfaceCount);
- for (int i = 0; i < interfaceCount; ++i) {
- out.putShort(interfaces[i]);
- }
- out.putShort(nbFields);
- fb = firstField;
- while (fb != null) {
- fb.put(out);
- fb = (FieldWriter) fb.fv;
- }
- out.putShort(nbMethods);
- mb = firstMethod;
- while (mb != null) {
- mb.put(out);
- mb = (MethodWriter) mb.mv;
- }
- out.putShort(attributeCount);
- if (bootstrapMethods != null) {
- out.putShort(newUTF8("BootstrapMethods"));
- out.putInt(bootstrapMethods.length + 2).putShort(
- bootstrapMethodsCount);
- out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length);
- }
- if (ClassReader.SIGNATURES && signature != 0) {
- out.putShort(newUTF8("Signature")).putInt(2).putShort(signature);
- }
- if (sourceFile != 0) {
- out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);
- }
- if (sourceDebug != null) {
- int len = sourceDebug.length - 2;
- out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
- out.putByteArray(sourceDebug.data, 2, len);
- }
- if (enclosingMethodOwner != 0) {
- out.putShort(newUTF8("EnclosingMethod")).putInt(4);
- out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
- }
- if ((access & Opcodes.ACC_DEPRECATED) != 0) {
- out.putShort(newUTF8("Deprecated")).putInt(0);
- }
- if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
- if ((version & 0xFFFF) < Opcodes.V1_5
- || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) {
- out.putShort(newUTF8("Synthetic")).putInt(0);
- }
- }
- if (innerClasses != null) {
- out.putShort(newUTF8("InnerClasses"));
- out.putInt(innerClasses.length + 2).putShort(innerClassesCount);
- out.putByteArray(innerClasses.data, 0, innerClasses.length);
- }
- if (ClassReader.ANNOTATIONS && anns != null) {
- out.putShort(newUTF8("RuntimeVisibleAnnotations"));
- anns.put(out);
- }
- if (ClassReader.ANNOTATIONS && ianns != null) {
- out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
- ianns.put(out);
- }
- if (attrs != null) {
- attrs.put(this, null, 0, -1, -1, out);
- }
- if (invalidFrames) {
- ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
- new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES);
- return cw.toByteArray();
- }
- return out.data;
- }
-
- // ------------------------------------------------------------------------
- // Utility methods: constant pool management
- // ------------------------------------------------------------------------
-
- /**
- * Adds a number or string constant to the constant pool of the class being
- * build. Does nothing if the constant pool already contains a similar item.
- *
- * @param cst
- * the value of the constant to be added to the constant pool.
- * This parameter must be an {@link Integer}, a {@link Float}, a
- * {@link Long}, a {@link Double}, a {@link String} or a
- * {@link Type}.
- * @return a new or already existing constant item with the given value.
- */
- Item newConstItem(final Object cst) {
- if (cst instanceof Integer) {
- int val = ((Integer) cst).intValue();
- return newInteger(val);
- } else if (cst instanceof Byte) {
- int val = ((Byte) cst).intValue();
- return newInteger(val);
- } else if (cst instanceof Character) {
- int val = ((Character) cst).charValue();
- return newInteger(val);
- } else if (cst instanceof Short) {
- int val = ((Short) cst).intValue();
- return newInteger(val);
- } else if (cst instanceof Boolean) {
- int val = ((Boolean) cst).booleanValue() ? 1 : 0;
- return newInteger(val);
- } else if (cst instanceof Float) {
- float val = ((Float) cst).floatValue();
- return newFloat(val);
- } else if (cst instanceof Long) {
- long val = ((Long) cst).longValue();
- return newLong(val);
- } else if (cst instanceof Double) {
- double val = ((Double) cst).doubleValue();
- return newDouble(val);
- } else if (cst instanceof String) {
- return newString((String) cst);
- } else if (cst instanceof Type) {
- Type t = (Type) cst;
- int s = t.getSort();
- if (s == Type.OBJECT) {
- return newClassItem(t.getInternalName());
- } else if (s == Type.METHOD) {
- return newMethodTypeItem(t.getDescriptor());
- } else { // s == primitive type or array
- return newClassItem(t.getDescriptor());
- }
- } else if (cst instanceof Handle) {
- Handle h = (Handle) cst;
- return newHandleItem(h.tag, h.owner, h.name, h.desc);
- } else {
- throw new IllegalArgumentException("value " + cst);
- }
- }
-
- /**
- * Adds a number or string constant to the constant pool of the class being
- * build. Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param cst
- * the value of the constant to be added to the constant pool.
- * This parameter must be an {@link Integer}, a {@link Float}, a
- * {@link Long}, a {@link Double} or a {@link String}.
- * @return the index of a new or already existing constant item with the
- * given value.
- */
- public int newConst(final Object cst) {
- return newConstItem(cst).index;
- }
-
- /**
- * Adds an UTF8 string to the constant pool of the class being build. Does
- * nothing if the constant pool already contains a similar item. <i>This
- * method is intended for {@link Attribute} sub classes, and is normally not
- * needed by class generators or adapters.</i>
- *
- * @param value
- * the String value.
- * @return the index of a new or already existing UTF8 item.
- */
- public int newUTF8(final String value) {
- key.set(UTF8, value, null, null);
- Item result = get(key);
- if (result == null) {
- pool.putByte(UTF8).putUTF8(value);
- result = new Item(index++, key);
- put(result);
- }
- return result.index;
- }
-
- /**
- * Adds a class reference to the constant pool of the class being build.
- * Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param value
- * the internal name of the class.
- * @return a new or already existing class reference item.
- */
- Item newClassItem(final String value) {
- key2.set(CLASS, value, null, null);
- Item result = get(key2);
- if (result == null) {
- pool.put12(CLASS, newUTF8(value));
- result = new Item(index++, key2);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a class reference to the constant pool of the class being build.
- * Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param value
- * the internal name of the class.
- * @return the index of a new or already existing class reference item.
- */
- public int newClass(final String value) {
- return newClassItem(value).index;
- }
-
- /**
- * Adds a method type reference to the constant pool of the class being
- * build. Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param methodDesc
- * method descriptor of the method type.
- * @return a new or already existing method type reference item.
- */
- Item newMethodTypeItem(final String methodDesc) {
- key2.set(MTYPE, methodDesc, null, null);
- Item result = get(key2);
- if (result == null) {
- pool.put12(MTYPE, newUTF8(methodDesc));
- result = new Item(index++, key2);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a method type reference to the constant pool of the class being
- * build. Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param methodDesc
- * method descriptor of the method type.
- * @return the index of a new or already existing method type reference
- * item.
- */
- public int newMethodType(final String methodDesc) {
- return newMethodTypeItem(methodDesc).index;
- }
-
- /**
- * Adds a handle to the constant pool of the class being build. Does nothing
- * if the constant pool already contains a similar item. <i>This method is
- * intended for {@link Attribute} sub classes, and is normally not needed by
- * class generators or adapters.</i>
- *
- * @param tag
- * the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
- * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
- * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
- * {@link Opcodes#H_INVOKESTATIC},
- * {@link Opcodes#H_INVOKESPECIAL},
- * {@link Opcodes#H_NEWINVOKESPECIAL} or
- * {@link Opcodes#H_INVOKEINTERFACE}.
- * @param owner
- * the internal name of the field or method owner class.
- * @param name
- * the name of the field or method.
- * @param desc
- * the descriptor of the field or method.
- * @return a new or an already existing method type reference item.
- */
- Item newHandleItem(final int tag, final String owner, final String name,
- final String desc) {
- key4.set(HANDLE_BASE + tag, owner, name, desc);
- Item result = get(key4);
- if (result == null) {
- if (tag <= Opcodes.H_PUTSTATIC) {
- put112(HANDLE, tag, newField(owner, name, desc));
- } else {
- put112(HANDLE,
- tag,
- newMethod(owner, name, desc,
- tag == Opcodes.H_INVOKEINTERFACE));
- }
- result = new Item(index++, key4);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a handle to the constant pool of the class being build. Does nothing
- * if the constant pool already contains a similar item. <i>This method is
- * intended for {@link Attribute} sub classes, and is normally not needed by
- * class generators or adapters.</i>
- *
- * @param tag
- * the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
- * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
- * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
- * {@link Opcodes#H_INVOKESTATIC},
- * {@link Opcodes#H_INVOKESPECIAL},
- * {@link Opcodes#H_NEWINVOKESPECIAL} or
- * {@link Opcodes#H_INVOKEINTERFACE}.
- * @param owner
- * the internal name of the field or method owner class.
- * @param name
- * the name of the field or method.
- * @param desc
- * the descriptor of the field or method.
- * @return the index of a new or already existing method type reference
- * item.
- */
- public int newHandle(final int tag, final String owner, final String name,
- final String desc) {
- return newHandleItem(tag, owner, name, desc).index;
- }
-
- /**
- * Adds an invokedynamic reference to the constant pool of the class being
- * build. Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param name
- * name of the invoked method.
- * @param desc
- * descriptor of the invoke method.
- * @param bsm
- * the bootstrap method.
- * @param bsmArgs
- * the bootstrap method constant arguments.
- *
- * @return a new or an already existing invokedynamic type reference item.
- */
- Item newInvokeDynamicItem(final String name, final String desc,
- final Handle bsm, final Object... bsmArgs) {
- // cache for performance
- ByteVector bootstrapMethods = this.bootstrapMethods;
- if (bootstrapMethods == null) {
- bootstrapMethods = this.bootstrapMethods = new ByteVector();
- }
-
- int position = bootstrapMethods.length; // record current position
-
- int hashCode = bsm.hashCode();
- bootstrapMethods.putShort(newHandle(bsm.tag, bsm.owner, bsm.name,
- bsm.desc));
-
- int argsLength = bsmArgs.length;
- bootstrapMethods.putShort(argsLength);
-
- for (int i = 0; i < argsLength; i++) {
- Object bsmArg = bsmArgs[i];
- hashCode ^= bsmArg.hashCode();
- bootstrapMethods.putShort(newConst(bsmArg));
- }
-
- byte[] data = bootstrapMethods.data;
- int length = (1 + 1 + argsLength) << 1; // (bsm + argCount + arguments)
- hashCode &= 0x7FFFFFFF;
- Item result = items[hashCode % items.length];
- loop: while (result != null) {
- if (result.type != BSM || result.hashCode != hashCode) {
- result = result.next;
- continue;
- }
-
- // because the data encode the size of the argument
- // we don't need to test if these size are equals
- int resultPosition = result.intVal;
- for (int p = 0; p < length; p++) {
- if (data[position + p] != data[resultPosition + p]) {
- result = result.next;
- continue loop;
- }
- }
- break;
- }
-
- int bootstrapMethodIndex;
- if (result != null) {
- bootstrapMethodIndex = result.index;
- bootstrapMethods.length = position; // revert to old position
- } else {
- bootstrapMethodIndex = bootstrapMethodsCount++;
- result = new Item(bootstrapMethodIndex);
- result.set(position, hashCode);
- put(result);
- }
-
- // now, create the InvokeDynamic constant
- key3.set(name, desc, bootstrapMethodIndex);
- result = get(key3);
- if (result == null) {
- put122(INDY, bootstrapMethodIndex, newNameType(name, desc));
- result = new Item(index++, key3);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds an invokedynamic reference to the constant pool of the class being
- * build. Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param name
- * name of the invoked method.
- * @param desc
- * descriptor of the invoke method.
- * @param bsm
- * the bootstrap method.
- * @param bsmArgs
- * the bootstrap method constant arguments.
- *
- * @return the index of a new or already existing invokedynamic reference
- * item.
- */
- public int newInvokeDynamic(final String name, final String desc,
- final Handle bsm, final Object... bsmArgs) {
- return newInvokeDynamicItem(name, desc, bsm, bsmArgs).index;
- }
-
- /**
- * Adds a field reference to the constant pool of the class being build.
- * Does nothing if the constant pool already contains a similar item.
- *
- * @param owner
- * the internal name of the field's owner class.
- * @param name
- * the field's name.
- * @param desc
- * the field's descriptor.
- * @return a new or already existing field reference item.
- */
- Item newFieldItem(final String owner, final String name, final String desc) {
- key3.set(FIELD, owner, name, desc);
- Item result = get(key3);
- if (result == null) {
- put122(FIELD, newClass(owner), newNameType(name, desc));
- result = new Item(index++, key3);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a field reference to the constant pool of the class being build.
- * Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param owner
- * the internal name of the field's owner class.
- * @param name
- * the field's name.
- * @param desc
- * the field's descriptor.
- * @return the index of a new or already existing field reference item.
- */
- public int newField(final String owner, final String name, final String desc) {
- return newFieldItem(owner, name, desc).index;
- }
-
- /**
- * Adds a method reference to the constant pool of the class being build.
- * Does nothing if the constant pool already contains a similar item.
- *
- * @param owner
- * the internal name of the method's owner class.
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor.
- * @param itf
- * <tt>true</tt> if <tt>owner</tt> is an interface.
- * @return a new or already existing method reference item.
- */
- Item newMethodItem(final String owner, final String name,
- final String desc, final boolean itf) {
- int type = itf ? IMETH : METH;
- key3.set(type, owner, name, desc);
- Item result = get(key3);
- if (result == null) {
- put122(type, newClass(owner), newNameType(name, desc));
- result = new Item(index++, key3);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a method reference to the constant pool of the class being build.
- * Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param owner
- * the internal name of the method's owner class.
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor.
- * @param itf
- * <tt>true</tt> if <tt>owner</tt> is an interface.
- * @return the index of a new or already existing method reference item.
- */
- public int newMethod(final String owner, final String name,
- final String desc, final boolean itf) {
- return newMethodItem(owner, name, desc, itf).index;
- }
-
- /**
- * Adds an integer to the constant pool of the class being build. Does
- * nothing if the constant pool already contains a similar item.
- *
- * @param value
- * the int value.
- * @return a new or already existing int item.
- */
- Item newInteger(final int value) {
- key.set(value);
- Item result = get(key);
- if (result == null) {
- pool.putByte(INT).putInt(value);
- result = new Item(index++, key);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a float to the constant pool of the class being build. Does nothing
- * if the constant pool already contains a similar item.
- *
- * @param value
- * the float value.
- * @return a new or already existing float item.
- */
- Item newFloat(final float value) {
- key.set(value);
- Item result = get(key);
- if (result == null) {
- pool.putByte(FLOAT).putInt(key.intVal);
- result = new Item(index++, key);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a long to the constant pool of the class being build. Does nothing
- * if the constant pool already contains a similar item.
- *
- * @param value
- * the long value.
- * @return a new or already existing long item.
- */
- Item newLong(final long value) {
- key.set(value);
- Item result = get(key);
- if (result == null) {
- pool.putByte(LONG).putLong(value);
- result = new Item(index, key);
- index += 2;
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a double to the constant pool of the class being build. Does nothing
- * if the constant pool already contains a similar item.
- *
- * @param value
- * the double value.
- * @return a new or already existing double item.
- */
- Item newDouble(final double value) {
- key.set(value);
- Item result = get(key);
- if (result == null) {
- pool.putByte(DOUBLE).putLong(key.longVal);
- result = new Item(index, key);
- index += 2;
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a string to the constant pool of the class being build. Does nothing
- * if the constant pool already contains a similar item.
- *
- * @param value
- * the String value.
- * @return a new or already existing string item.
- */
- private Item newString(final String value) {
- key2.set(STR, value, null, null);
- Item result = get(key2);
- if (result == null) {
- pool.put12(STR, newUTF8(value));
- result = new Item(index++, key2);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a name and type to the constant pool of the class being build. Does
- * nothing if the constant pool already contains a similar item. <i>This
- * method is intended for {@link Attribute} sub classes, and is normally not
- * needed by class generators or adapters.</i>
- *
- * @param name
- * a name.
- * @param desc
- * a type descriptor.
- * @return the index of a new or already existing name and type item.
- */
- public int newNameType(final String name, final String desc) {
- return newNameTypeItem(name, desc).index;
- }
-
- /**
- * Adds a name and type to the constant pool of the class being build. Does
- * nothing if the constant pool already contains a similar item.
- *
- * @param name
- * a name.
- * @param desc
- * a type descriptor.
- * @return a new or already existing name and type item.
- */
- Item newNameTypeItem(final String name, final String desc) {
- key2.set(NAME_TYPE, name, desc, null);
- Item result = get(key2);
- if (result == null) {
- put122(NAME_TYPE, newUTF8(name), newUTF8(desc));
- result = new Item(index++, key2);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds the given internal name to {@link #typeTable} and returns its index.
- * Does nothing if the type table already contains this internal name.
- *
- * @param type
- * the internal name to be added to the type table.
- * @return the index of this internal name in the type table.
- */
- int addType(final String type) {
- key.set(TYPE_NORMAL, type, null, null);
- Item result = get(key);
- if (result == null) {
- result = addType(key);
- }
- return result.index;
- }
-
- /**
- * Adds the given "uninitialized" type to {@link #typeTable} and returns its
- * index. This method is used for UNINITIALIZED types, made of an internal
- * name and a bytecode offset.
- *
- * @param type
- * the internal name to be added to the type table.
- * @param offset
- * the bytecode offset of the NEW instruction that created this
- * UNINITIALIZED type value.
- * @return the index of this internal name in the type table.
- */
- int addUninitializedType(final String type, final int offset) {
- key.type = TYPE_UNINIT;
- key.intVal = offset;
- key.strVal1 = type;
- key.hashCode = 0x7FFFFFFF & (TYPE_UNINIT + type.hashCode() + offset);
- Item result = get(key);
- if (result == null) {
- result = addType(key);
- }
- return result.index;
- }
-
- /**
- * Adds the given Item to {@link #typeTable}.
- *
- * @param item
- * the value to be added to the type table.
- * @return the added Item, which a new Item instance with the same value as
- * the given Item.
- */
- private Item addType(final Item item) {
- ++typeCount;
- Item result = new Item(typeCount, key);
- put(result);
- if (typeTable == null) {
- typeTable = new Item[16];
- }
- if (typeCount == typeTable.length) {
- Item[] newTable = new Item[2 * typeTable.length];
- System.arraycopy(typeTable, 0, newTable, 0, typeTable.length);
- typeTable = newTable;
- }
- typeTable[typeCount] = result;
- return result;
- }
-
- /**
- * Returns the index of the common super type of the two given types. This
- * method calls {@link #getCommonSuperClass} and caches the result in the
- * {@link #items} hash table to speedup future calls with the same
- * parameters.
- *
- * @param type1
- * index of an internal name in {@link #typeTable}.
- * @param type2
- * index of an internal name in {@link #typeTable}.
- * @return the index of the common super type of the two given types.
- */
- int getMergedType(final int type1, final int type2) {
- key2.type = TYPE_MERGED;
- key2.longVal = type1 | (((long) type2) << 32);
- key2.hashCode = 0x7FFFFFFF & (TYPE_MERGED + type1 + type2);
- Item result = get(key2);
- if (result == null) {
- String t = typeTable[type1].strVal1;
- String u = typeTable[type2].strVal1;
- key2.intVal = addType(getCommonSuperClass(t, u));
- result = new Item((short) 0, key2);
- put(result);
- }
- return result.intVal;
- }
-
- /**
- * Returns the common super type of the two given types. The default
- * implementation of this method <i>loads<i> the two given classes and uses
- * the java.lang.Class methods to find the common super class. It can be
- * overridden to compute this common super type in other ways, in particular
- * without actually loading any class, or to take into account the class
- * that is currently being generated by this ClassWriter, which can of
- * course not be loaded since it is under construction.
- *
- * @param type1
- * the internal name of a class.
- * @param type2
- * the internal name of another class.
- * @return the internal name of the common super class of the two given
- * classes.
- */
- protected String getCommonSuperClass(final String type1, final String type2) {
- Class<?> c, d;
- ClassLoader classLoader = getClass().getClassLoader();
- try {
- c = Class.forName(type1.replace('/', '.'), false, classLoader);
- d = Class.forName(type2.replace('/', '.'), false, classLoader);
- } catch (Exception e) {
- throw new RuntimeException(e.toString());
- }
- if (c.isAssignableFrom(d)) {
- return type1;
- }
- if (d.isAssignableFrom(c)) {
- return type2;
- }
- if (c.isInterface() || d.isInterface()) {
- return "java/lang/Object";
- } else {
- do {
- c = c.getSuperclass();
- } while (!c.isAssignableFrom(d));
- return c.getName().replace('.', '/');
- }
- }
-
- /**
- * Returns the constant pool's hash table item which is equal to the given
- * item.
- *
- * @param key
- * a constant pool item.
- * @return the constant pool's hash table item which is equal to the given
- * item, or <tt>null</tt> if there is no such item.
- */
- private Item get(final Item key) {
- Item i = items[key.hashCode % items.length];
- while (i != null && (i.type != key.type || !key.isEqualTo(i))) {
- i = i.next;
- }
- return i;
- }
-
- /**
- * Puts the given item in the constant pool's hash table. The hash table
- * <i>must</i> not already contains this item.
- *
- * @param i
- * the item to be added to the constant pool's hash table.
- */
- private void put(final Item i) {
- if (index + typeCount > threshold) {
- int ll = items.length;
- int nl = ll * 2 + 1;
- Item[] newItems = new Item[nl];
- for (int l = ll - 1; l >= 0; --l) {
- Item j = items[l];
- while (j != null) {
- int index = j.hashCode % newItems.length;
- Item k = j.next;
- j.next = newItems[index];
- newItems[index] = j;
- j = k;
- }
- }
- items = newItems;
- threshold = (int) (nl * 0.75);
- }
- int index = i.hashCode % items.length;
- i.next = items[index];
- items[index] = i;
- }
-
- /**
- * Puts one byte and two shorts into the constant pool.
- *
- * @param b
- * a byte.
- * @param s1
- * a short.
- * @param s2
- * another short.
- */
- private void put122(final int b, final int s1, final int s2) {
- pool.put12(b, s1).putShort(s2);
- }
-
- /**
- * Puts two bytes and one short into the constant pool.
- *
- * @param b1
- * a byte.
- * @param b2
- * another byte.
- * @param s
- * a short.
- */
- private void put112(final int b1, final int b2, final int s) {
- pool.put11(b1, b2).putShort(s);
- }
-}
diff --git a/src/jvm/clojure/asm/Context.java b/src/jvm/clojure/asm/Context.java
deleted file mode 100644
index d113ed9..0000000
--- a/src/jvm/clojure/asm/Context.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-/**
- * Information about a class being parsed in a {@link ClassReader}.
- *
- * @author Eric Bruneton
- */
-class Context {
-
- /**
- * Prototypes of the attributes that must be parsed for this class.
- */
- Attribute[] attrs;
-
- /**
- * The {@link ClassReader} option flags for the parsing of this class.
- */
- int flags;
-
- /**
- * The buffer used to read strings.
- */
- char[] buffer;
-
- /**
- * The start index of each bootstrap method.
- */
- int[] bootstrapMethods;
-
- /**
- * The access flags of the method currently being parsed.
- */
- int access;
-
- /**
- * The name of the method currently being parsed.
- */
- String name;
-
- /**
- * The descriptor of the method currently being parsed.
- */
- String desc;
-
- /**
- * The offset of the latest stack map frame that has been parsed.
- */
- int offset;
-
- /**
- * The encoding of the latest stack map frame that has been parsed.
- */
- int mode;
-
- /**
- * The number of locals in the latest stack map frame that has been parsed.
- */
- int localCount;
-
- /**
- * The number locals in the latest stack map frame that has been parsed,
- * minus the number of locals in the previous frame.
- */
- int localDiff;
-
- /**
- * The local values of the latest stack map frame that has been parsed.
- */
- Object[] local;
-
- /**
- * The stack size of the latest stack map frame that has been parsed.
- */
- int stackCount;
-
- /**
- * The stack values of the latest stack map frame that has been parsed.
- */
- Object[] stack;
-}
\ No newline at end of file
diff --git a/src/jvm/clojure/asm/Edge.java b/src/jvm/clojure/asm/Edge.java
deleted file mode 100644
index 045cd46..0000000
--- a/src/jvm/clojure/asm/Edge.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-/**
- * An edge in the control flow graph of a method body. See {@link Label Label}.
- *
- * @author Eric Bruneton
- */
-class Edge {
-
- /**
- * Denotes a normal control flow graph edge.
- */
- static final int NORMAL = 0;
-
- /**
- * Denotes a control flow graph edge corresponding to an exception handler.
- * More precisely any {@link Edge} whose {@link #info} is strictly positive
- * corresponds to an exception handler. The actual value of {@link #info} is
- * the index, in the {@link ClassWriter} type table, of the exception that
- * is catched.
- */
- static final int EXCEPTION = 0x7FFFFFFF;
-
- /**
- * Information about this control flow graph edge. If
- * {@link ClassWriter#COMPUTE_MAXS} is used this field is the (relative)
- * stack size in the basic block from which this edge originates. This size
- * is equal to the stack size at the "jump" instruction to which this edge
- * corresponds, relatively to the stack size at the beginning of the
- * originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used,
- * this field is the kind of this control flow graph edge (i.e. NORMAL or
- * EXCEPTION).
- */
- int info;
-
- /**
- * The successor block of the basic block from which this edge originates.
- */
- Label successor;
-
- /**
- * The next edge in the list of successors of the originating basic block.
- * See {@link Label#successors successors}.
- */
- Edge next;
-}
diff --git a/src/jvm/clojure/asm/FieldVisitor.java b/src/jvm/clojure/asm/FieldVisitor.java
deleted file mode 100644
index b9df738..0000000
--- a/src/jvm/clojure/asm/FieldVisitor.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-/**
- * A visitor to visit a Java field. The methods of this class must be called in
- * the following order: ( <tt>visitAnnotation</tt> | <tt>visitAttribute</tt> )*
- * <tt>visitEnd</tt>.
- *
- * @author Eric Bruneton
- */
-public abstract class FieldVisitor {
-
- /**
- * The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4}.
- */
- protected final int api;
-
- /**
- * The field visitor to which this visitor must delegate method calls. May
- * be null.
- */
- protected FieldVisitor fv;
-
- /**
- * Constructs a new {@link FieldVisitor}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- */
- public FieldVisitor(final int api) {
- this(api, null);
- }
-
- /**
- * Constructs a new {@link FieldVisitor}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param fv
- * the field visitor to which this visitor must delegate method
- * calls. May be null.
- */
- public FieldVisitor(final int api, final FieldVisitor fv) {
- if (api != Opcodes.ASM4) {
- throw new IllegalArgumentException();
- }
- this.api = api;
- this.fv = fv;
- }
-
- /**
- * Visits an annotation of the field.
- *
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return a visitor to visit the annotation values, or <tt>null</tt> if
- * this visitor is not interested in visiting this annotation.
- */
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- if (fv != null) {
- return fv.visitAnnotation(desc, visible);
- }
- return null;
- }
-
- /**
- * Visits a non standard attribute of the field.
- *
- * @param attr
- * an attribute.
- */
- public void visitAttribute(Attribute attr) {
- if (fv != null) {
- fv.visitAttribute(attr);
- }
- }
-
- /**
- * Visits the end of the field. This method, which is the last one to be
- * called, is used to inform the visitor that all the annotations and
- * attributes of the field have been visited.
- */
- public void visitEnd() {
- if (fv != null) {
- fv.visitEnd();
- }
- }
-}
diff --git a/src/jvm/clojure/asm/FieldWriter.java b/src/jvm/clojure/asm/FieldWriter.java
deleted file mode 100644
index ccd32ec..0000000
--- a/src/jvm/clojure/asm/FieldWriter.java
+++ /dev/null
@@ -1,273 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-/**
- * An {@link FieldVisitor} that generates Java fields in bytecode form.
- *
- * @author Eric Bruneton
- */
-final class FieldWriter extends FieldVisitor {
-
- /**
- * The class writer to which this field must be added.
- */
- private final ClassWriter cw;
-
- /**
- * Access flags of this field.
- */
- private final int access;
-
- /**
- * The index of the constant pool item that contains the name of this
- * method.
- */
- private final int name;
-
- /**
- * The index of the constant pool item that contains the descriptor of this
- * field.
- */
- private final int desc;
-
- /**
- * The index of the constant pool item that contains the signature of this
- * field.
- */
- private int signature;
-
- /**
- * The index of the constant pool item that contains the constant value of
- * this field.
- */
- private int value;
-
- /**
- * The runtime visible annotations of this field. May be <tt>null</tt>.
- */
- private AnnotationWriter anns;
-
- /**
- * The runtime invisible annotations of this field. May be <tt>null</tt>.
- */
- private AnnotationWriter ianns;
-
- /**
- * The non standard attributes of this field. May be <tt>null</tt>.
- */
- private Attribute attrs;
-
- // ------------------------------------------------------------------------
- // Constructor
- // ------------------------------------------------------------------------
-
- /**
- * Constructs a new {@link FieldWriter}.
- *
- * @param cw
- * the class writer to which this field must be added.
- * @param access
- * the field's access flags (see {@link Opcodes}).
- * @param name
- * the field's name.
- * @param desc
- * the field's descriptor (see {@link Type}).
- * @param signature
- * the field's signature. May be <tt>null</tt>.
- * @param value
- * the field's constant value. May be <tt>null</tt>.
- */
- FieldWriter(final ClassWriter cw, final int access, final String name,
- final String desc, final String signature, final Object value) {
- super(Opcodes.ASM4);
- if (cw.firstField == null) {
- cw.firstField = this;
- } else {
- cw.lastField.fv = this;
- }
- cw.lastField = this;
- this.cw = cw;
- this.access = access;
- this.name = cw.newUTF8(name);
- this.desc = cw.newUTF8(desc);
- if (ClassReader.SIGNATURES && signature != null) {
- this.signature = cw.newUTF8(signature);
- }
- if (value != null) {
- this.value = cw.newConstItem(value).index;
- }
- }
-
- // ------------------------------------------------------------------------
- // Implementation of the FieldVisitor abstract class
- // ------------------------------------------------------------------------
-
- @Override
- public AnnotationVisitor visitAnnotation(final String desc,
- final boolean visible) {
- if (!ClassReader.ANNOTATIONS) {
- return null;
- }
- ByteVector bv = new ByteVector();
- // write type, and reserve space for values count
- bv.putShort(cw.newUTF8(desc)).putShort(0);
- AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
- if (visible) {
- aw.next = anns;
- anns = aw;
- } else {
- aw.next = ianns;
- ianns = aw;
- }
- return aw;
- }
-
- @Override
- public void visitAttribute(final Attribute attr) {
- attr.next = attrs;
- attrs = attr;
- }
-
- @Override
- public void visitEnd() {
- }
-
- // ------------------------------------------------------------------------
- // Utility methods
- // ------------------------------------------------------------------------
-
- /**
- * Returns the size of this field.
- *
- * @return the size of this field.
- */
- int getSize() {
- int size = 8;
- if (value != 0) {
- cw.newUTF8("ConstantValue");
- size += 8;
- }
- if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
- if ((cw.version & 0xFFFF) < Opcodes.V1_5
- || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
- cw.newUTF8("Synthetic");
- size += 6;
- }
- }
- if ((access & Opcodes.ACC_DEPRECATED) != 0) {
- cw.newUTF8("Deprecated");
- size += 6;
- }
- if (ClassReader.SIGNATURES && signature != 0) {
- cw.newUTF8("Signature");
- size += 8;
- }
- if (ClassReader.ANNOTATIONS && anns != null) {
- cw.newUTF8("RuntimeVisibleAnnotations");
- size += 8 + anns.getSize();
- }
- if (ClassReader.ANNOTATIONS && ianns != null) {
- cw.newUTF8("RuntimeInvisibleAnnotations");
- size += 8 + ianns.getSize();
- }
- if (attrs != null) {
- size += attrs.getSize(cw, null, 0, -1, -1);
- }
- return size;
- }
-
- /**
- * Puts the content of this field into the given byte vector.
- *
- * @param out
- * where the content of this field must be put.
- */
- void put(final ByteVector out) {
- final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
- int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
- | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
- out.putShort(access & ~mask).putShort(name).putShort(desc);
- int attributeCount = 0;
- if (value != 0) {
- ++attributeCount;
- }
- if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
- if ((cw.version & 0xFFFF) < Opcodes.V1_5
- || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
- ++attributeCount;
- }
- }
- if ((access & Opcodes.ACC_DEPRECATED) != 0) {
- ++attributeCount;
- }
- if (ClassReader.SIGNATURES && signature != 0) {
- ++attributeCount;
- }
- if (ClassReader.ANNOTATIONS && anns != null) {
- ++attributeCount;
- }
- if (ClassReader.ANNOTATIONS && ianns != null) {
- ++attributeCount;
- }
- if (attrs != null) {
- attributeCount += attrs.getCount();
- }
- out.putShort(attributeCount);
- if (value != 0) {
- out.putShort(cw.newUTF8("ConstantValue"));
- out.putInt(2).putShort(value);
- }
- if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
- if ((cw.version & 0xFFFF) < Opcodes.V1_5
- || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
- out.putShort(cw.newUTF8("Synthetic")).putInt(0);
- }
- }
- if ((access & Opcodes.ACC_DEPRECATED) != 0) {
- out.putShort(cw.newUTF8("Deprecated")).putInt(0);
- }
- if (ClassReader.SIGNATURES && signature != 0) {
- out.putShort(cw.newUTF8("Signature"));
- out.putInt(2).putShort(signature);
- }
- if (ClassReader.ANNOTATIONS && anns != null) {
- out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
- anns.put(out);
- }
- if (ClassReader.ANNOTATIONS && ianns != null) {
- out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
- ianns.put(out);
- }
- if (attrs != null) {
- attrs.put(cw, null, 0, -1, -1, out);
- }
- }
-}
diff --git a/src/jvm/clojure/asm/Frame.java b/src/jvm/clojure/asm/Frame.java
deleted file mode 100644
index 9c7e61d..0000000
--- a/src/jvm/clojure/asm/Frame.java
+++ /dev/null
@@ -1,1453 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-/**
- * Information about the input and output stack map frames of a basic block.
- *
- * @author Eric Bruneton
- */
-final class Frame {
-
- /*
- * Frames are computed in a two steps process: during the visit of each
- * instruction, the state of the frame at the end of current basic block is
- * updated by simulating the action of the instruction on the previous state
- * of this so called "output frame". In visitMaxs, a fix point algorithm is
- * used to compute the "input frame" of each basic block, i.e. the stack map
- * frame at the beginning of the basic block, starting from the input frame
- * of the first basic block (which is computed from the method descriptor),
- * and by using the previously computed output frames to compute the input
- * state of the other blocks.
- *
- * All output and input frames are stored as arrays of integers. Reference
- * and array types are represented by an index into a type table (which is
- * not the same as the constant pool of the class, in order to avoid adding
- * unnecessary constants in the pool - not all computed frames will end up
- * being stored in the stack map table). This allows very fast type
- * comparisons.
- *
- * Output stack map frames are computed relatively to the input frame of the
- * basic block, which is not yet known when output frames are computed. It
- * is therefore necessary to be able to represent abstract types such as
- * "the type at position x in the input frame locals" or "the type at
- * position x from the top of the input frame stack" or even "the type at
- * position x in the input frame, with y more (or less) array dimensions".
- * This explains the rather complicated type format used in output frames.
- *
- * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a
- * signed number of array dimensions (from -8 to 7). KIND is either BASE,
- * LOCAL or STACK. BASE is used for types that are not relative to the input
- * frame. LOCAL is used for types that are relative to the input local
- * variable types. STACK is used for types that are relative to the input
- * stack types. VALUE depends on KIND. For LOCAL types, it is an index in
- * the input local variable types. For STACK types, it is a position
- * relatively to the top of input frame stack. For BASE types, it is either
- * one of the constants defined in FrameVisitor, or for OBJECT and
- * UNINITIALIZED types, a tag and an index in the type table.
- *
- * Output frames can contain types of any kind and with a positive or
- * negative dimension (and even unassigned types, represented by 0 - which
- * does not correspond to any valid type value). Input frames can only
- * contain BASE types of positive or null dimension. In all cases the type
- * table contains only internal type names (array type descriptors are
- * forbidden - dimensions must be represented through the DIM field).
- *
- * The LONG and DOUBLE types are always represented by using two slots (LONG
- * + TOP or DOUBLE + TOP), for local variable types as well as in the
- * operand stack. This is necessary to be able to simulate DUPx_y
- * instructions, whose effect would be dependent on the actual type values
- * if types were always represented by a single slot in the stack (and this
- * is not possible, since actual type values are not always known - cf LOCAL
- * and STACK type kinds).
- */
-
- /**
- * Mask to get the dimension of a frame type. This dimension is a signed
- * integer between -8 and 7.
- */
- static final int DIM = 0xF0000000;
-
- /**
- * Constant to be added to a type to get a type with one more dimension.
- */
- static final int ARRAY_OF = 0x10000000;
-
- /**
- * Constant to be added to a type to get a type with one less dimension.
- */
- static final int ELEMENT_OF = 0xF0000000;
-
- /**
- * Mask to get the kind of a frame type.
- *
- * @see #BASE
- * @see #LOCAL
- * @see #STACK
- */
- static final int KIND = 0xF000000;
-
- /**
- * Flag used for LOCAL and STACK types. Indicates that if this type happens
- * to be a long or double type (during the computations of input frames),
- * then it must be set to TOP because the second word of this value has been
- * reused to store other data in the basic block. Hence the first word no
- * longer stores a valid long or double value.
- */
- static final int TOP_IF_LONG_OR_DOUBLE = 0x800000;
-
- /**
- * Mask to get the value of a frame type.
- */
- static final int VALUE = 0x7FFFFF;
-
- /**
- * Mask to get the kind of base types.
- */
- static final int BASE_KIND = 0xFF00000;
-
- /**
- * Mask to get the value of base types.
- */
- static final int BASE_VALUE = 0xFFFFF;
-
- /**
- * Kind of the types that are not relative to an input stack map frame.
- */
- static final int BASE = 0x1000000;
-
- /**
- * Base kind of the base reference types. The BASE_VALUE of such types is an
- * index into the type table.
- */
- static final int OBJECT = BASE | 0x700000;
-
- /**
- * Base kind of the uninitialized base types. The BASE_VALUE of such types
- * in an index into the type table (the Item at that index contains both an
- * instruction offset and an internal class name).
- */
- static final int UNINITIALIZED = BASE | 0x800000;
-
- /**
- * Kind of the types that are relative to the local variable types of an
- * input stack map frame. The value of such types is a local variable index.
- */
- private static final int LOCAL = 0x2000000;
-
- /**
- * Kind of the the types that are relative to the stack of an input stack
- * map frame. The value of such types is a position relatively to the top of
- * this stack.
- */
- private static final int STACK = 0x3000000;
-
- /**
- * The TOP type. This is a BASE type.
- */
- static final int TOP = BASE | 0;
-
- /**
- * The BOOLEAN type. This is a BASE type mainly used for array types.
- */
- static final int BOOLEAN = BASE | 9;
-
- /**
- * The BYTE type. This is a BASE type mainly used for array types.
- */
- static final int BYTE = BASE | 10;
-
- /**
- * The CHAR type. This is a BASE type mainly used for array types.
- */
- static final int CHAR = BASE | 11;
-
- /**
- * The SHORT type. This is a BASE type mainly used for array types.
- */
- static final int SHORT = BASE | 12;
-
- /**
- * The INTEGER type. This is a BASE type.
- */
- static final int INTEGER = BASE | 1;
-
- /**
- * The FLOAT type. This is a BASE type.
- */
- static final int FLOAT = BASE | 2;
-
- /**
- * The DOUBLE type. This is a BASE type.
- */
- static final int DOUBLE = BASE | 3;
-
- /**
- * The LONG type. This is a BASE type.
- */
- static final int LONG = BASE | 4;
-
- /**
- * The NULL type. This is a BASE type.
- */
- static final int NULL = BASE | 5;
-
- /**
- * The UNINITIALIZED_THIS type. This is a BASE type.
- */
- static final int UNINITIALIZED_THIS = BASE | 6;
-
- /**
- * The stack size variation corresponding to each JVM instruction. This
- * stack variation is equal to the size of the values produced by an
- * instruction, minus the size of the values consumed by this instruction.
- */
- static final int[] SIZE;
-
- /**
- * Computes the stack size variation corresponding to each JVM instruction.
- */
- static {
- int i;
- int[] b = new int[202];
- String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD"
- + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD"
- + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED"
- + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
- for (i = 0; i < b.length; ++i) {
- b[i] = s.charAt(i) - 'E';
- }
- SIZE = b;
-
- // code to generate the above string
- //
- // int NA = 0; // not applicable (unused opcode or variable size opcode)
- //
- // b = new int[] {
- // 0, //NOP, // visitInsn
- // 1, //ACONST_NULL, // -
- // 1, //ICONST_M1, // -
- // 1, //ICONST_0, // -
- // 1, //ICONST_1, // -
- // 1, //ICONST_2, // -
- // 1, //ICONST_3, // -
- // 1, //ICONST_4, // -
- // 1, //ICONST_5, // -
- // 2, //LCONST_0, // -
- // 2, //LCONST_1, // -
- // 1, //FCONST_0, // -
- // 1, //FCONST_1, // -
- // 1, //FCONST_2, // -
- // 2, //DCONST_0, // -
- // 2, //DCONST_1, // -
- // 1, //BIPUSH, // visitIntInsn
- // 1, //SIPUSH, // -
- // 1, //LDC, // visitLdcInsn
- // NA, //LDC_W, // -
- // NA, //LDC2_W, // -
- // 1, //ILOAD, // visitVarInsn
- // 2, //LLOAD, // -
- // 1, //FLOAD, // -
- // 2, //DLOAD, // -
- // 1, //ALOAD, // -
- // NA, //ILOAD_0, // -
- // NA, //ILOAD_1, // -
- // NA, //ILOAD_2, // -
- // NA, //ILOAD_3, // -
- // NA, //LLOAD_0, // -
- // NA, //LLOAD_1, // -
- // NA, //LLOAD_2, // -
- // NA, //LLOAD_3, // -
- // NA, //FLOAD_0, // -
- // NA, //FLOAD_1, // -
- // NA, //FLOAD_2, // -
- // NA, //FLOAD_3, // -
- // NA, //DLOAD_0, // -
- // NA, //DLOAD_1, // -
- // NA, //DLOAD_2, // -
- // NA, //DLOAD_3, // -
- // NA, //ALOAD_0, // -
- // NA, //ALOAD_1, // -
- // NA, //ALOAD_2, // -
- // NA, //ALOAD_3, // -
- // -1, //IALOAD, // visitInsn
- // 0, //LALOAD, // -
- // -1, //FALOAD, // -
- // 0, //DALOAD, // -
- // -1, //AALOAD, // -
- // -1, //BALOAD, // -
- // -1, //CALOAD, // -
- // -1, //SALOAD, // -
- // -1, //ISTORE, // visitVarInsn
- // -2, //LSTORE, // -
- // -1, //FSTORE, // -
- // -2, //DSTORE, // -
- // -1, //ASTORE, // -
- // NA, //ISTORE_0, // -
- // NA, //ISTORE_1, // -
- // NA, //ISTORE_2, // -
- // NA, //ISTORE_3, // -
- // NA, //LSTORE_0, // -
- // NA, //LSTORE_1, // -
- // NA, //LSTORE_2, // -
- // NA, //LSTORE_3, // -
- // NA, //FSTORE_0, // -
- // NA, //FSTORE_1, // -
- // NA, //FSTORE_2, // -
- // NA, //FSTORE_3, // -
- // NA, //DSTORE_0, // -
- // NA, //DSTORE_1, // -
- // NA, //DSTORE_2, // -
- // NA, //DSTORE_3, // -
- // NA, //ASTORE_0, // -
- // NA, //ASTORE_1, // -
- // NA, //ASTORE_2, // -
- // NA, //ASTORE_3, // -
- // -3, //IASTORE, // visitInsn
- // -4, //LASTORE, // -
- // -3, //FASTORE, // -
- // -4, //DASTORE, // -
- // -3, //AASTORE, // -
- // -3, //BASTORE, // -
- // -3, //CASTORE, // -
- // -3, //SASTORE, // -
- // -1, //POP, // -
- // -2, //POP2, // -
- // 1, //DUP, // -
- // 1, //DUP_X1, // -
- // 1, //DUP_X2, // -
- // 2, //DUP2, // -
- // 2, //DUP2_X1, // -
- // 2, //DUP2_X2, // -
- // 0, //SWAP, // -
- // -1, //IADD, // -
- // -2, //LADD, // -
- // -1, //FADD, // -
- // -2, //DADD, // -
- // -1, //ISUB, // -
- // -2, //LSUB, // -
- // -1, //FSUB, // -
- // -2, //DSUB, // -
- // -1, //IMUL, // -
- // -2, //LMUL, // -
- // -1, //FMUL, // -
- // -2, //DMUL, // -
- // -1, //IDIV, // -
- // -2, //LDIV, // -
- // -1, //FDIV, // -
- // -2, //DDIV, // -
- // -1, //IREM, // -
- // -2, //LREM, // -
- // -1, //FREM, // -
- // -2, //DREM, // -
- // 0, //INEG, // -
- // 0, //LNEG, // -
- // 0, //FNEG, // -
- // 0, //DNEG, // -
- // -1, //ISHL, // -
- // -1, //LSHL, // -
- // -1, //ISHR, // -
- // -1, //LSHR, // -
- // -1, //IUSHR, // -
- // -1, //LUSHR, // -
- // -1, //IAND, // -
- // -2, //LAND, // -
- // -1, //IOR, // -
- // -2, //LOR, // -
- // -1, //IXOR, // -
- // -2, //LXOR, // -
- // 0, //IINC, // visitIincInsn
- // 1, //I2L, // visitInsn
- // 0, //I2F, // -
- // 1, //I2D, // -
- // -1, //L2I, // -
- // -1, //L2F, // -
- // 0, //L2D, // -
- // 0, //F2I, // -
- // 1, //F2L, // -
- // 1, //F2D, // -
- // -1, //D2I, // -
- // 0, //D2L, // -
- // -1, //D2F, // -
- // 0, //I2B, // -
- // 0, //I2C, // -
- // 0, //I2S, // -
- // -3, //LCMP, // -
- // -1, //FCMPL, // -
- // -1, //FCMPG, // -
- // -3, //DCMPL, // -
- // -3, //DCMPG, // -
- // -1, //IFEQ, // visitJumpInsn
- // -1, //IFNE, // -
- // -1, //IFLT, // -
- // -1, //IFGE, // -
- // -1, //IFGT, // -
- // -1, //IFLE, // -
- // -2, //IF_ICMPEQ, // -
- // -2, //IF_ICMPNE, // -
- // -2, //IF_ICMPLT, // -
- // -2, //IF_ICMPGE, // -
- // -2, //IF_ICMPGT, // -
- // -2, //IF_ICMPLE, // -
- // -2, //IF_ACMPEQ, // -
- // -2, //IF_ACMPNE, // -
- // 0, //GOTO, // -
- // 1, //JSR, // -
- // 0, //RET, // visitVarInsn
- // -1, //TABLESWITCH, // visiTableSwitchInsn
- // -1, //LOOKUPSWITCH, // visitLookupSwitch
- // -1, //IRETURN, // visitInsn
- // -2, //LRETURN, // -
- // -1, //FRETURN, // -
- // -2, //DRETURN, // -
- // -1, //ARETURN, // -
- // 0, //RETURN, // -
- // NA, //GETSTATIC, // visitFieldInsn
- // NA, //PUTSTATIC, // -
- // NA, //GETFIELD, // -
- // NA, //PUTFIELD, // -
- // NA, //INVOKEVIRTUAL, // visitMethodInsn
- // NA, //INVOKESPECIAL, // -
- // NA, //INVOKESTATIC, // -
- // NA, //INVOKEINTERFACE, // -
- // NA, //INVOKEDYNAMIC, // visitInvokeDynamicInsn
- // 1, //NEW, // visitTypeInsn
- // 0, //NEWARRAY, // visitIntInsn
- // 0, //ANEWARRAY, // visitTypeInsn
- // 0, //ARRAYLENGTH, // visitInsn
- // NA, //ATHROW, // -
- // 0, //CHECKCAST, // visitTypeInsn
- // 0, //INSTANCEOF, // -
- // -1, //MONITORENTER, // visitInsn
- // -1, //MONITOREXIT, // -
- // NA, //WIDE, // NOT VISITED
- // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn
- // -1, //IFNULL, // visitJumpInsn
- // -1, //IFNONNULL, // -
- // NA, //GOTO_W, // -
- // NA, //JSR_W, // -
- // };
- // for (i = 0; i < b.length; ++i) {
- // System.err.print((char)('E' + b[i]));
- // }
- // System.err.println();
- }
-
- /**
- * The label (i.e. basic block) to which these input and output stack map
- * frames correspond.
- */
- Label owner;
-
- /**
- * The input stack map frame locals.
- */
- int[] inputLocals;
-
- /**
- * The input stack map frame stack.
- */
- int[] inputStack;
-
- /**
- * The output stack map frame locals.
- */
- private int[] outputLocals;
-
- /**
- * The output stack map frame stack.
- */
- private int[] outputStack;
-
- /**
- * Relative size of the output stack. The exact semantics of this field
- * depends on the algorithm that is used.
- *
- * When only the maximum stack size is computed, this field is the size of
- * the output stack relatively to the top of the input stack.
- *
- * When the stack map frames are completely computed, this field is the
- * actual number of types in {@link #outputStack}.
- */
- private int outputStackTop;
-
- /**
- * Number of types that are initialized in the basic block.
- *
- * @see #initializations
- */
- private int initializationCount;
-
- /**
- * The types that are initialized in the basic block. A constructor
- * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace
- * <i>every occurence</i> of this type in the local variables and in the
- * operand stack. This cannot be done during the first phase of the
- * algorithm since, during this phase, the local variables and the operand
- * stack are not completely computed. It is therefore necessary to store the
- * types on which constructors are invoked in the basic block, in order to
- * do this replacement during the second phase of the algorithm, where the
- * frames are fully computed. Note that this array can contain types that
- * are relative to input locals or to the input stack (see below for the
- * description of the algorithm).
- */
- private int[] initializations;
-
- /**
- * Returns the output frame local variable type at the given index.
- *
- * @param local
- * the index of the local that must be returned.
- * @return the output frame local variable type at the given index.
- */
- private int get(final int local) {
- if (outputLocals == null || local >= outputLocals.length) {
- // this local has never been assigned in this basic block,
- // so it is still equal to its value in the input frame
- return LOCAL | local;
- } else {
- int type = outputLocals[local];
- if (type == 0) {
- // this local has never been assigned in this basic block,
- // so it is still equal to its value in the input frame
- type = outputLocals[local] = LOCAL | local;
- }
- return type;
- }
- }
-
- /**
- * Sets the output frame local variable type at the given index.
- *
- * @param local
- * the index of the local that must be set.
- * @param type
- * the value of the local that must be set.
- */
- private void set(final int local, final int type) {
- // creates and/or resizes the output local variables array if necessary
- if (outputLocals == null) {
- outputLocals = new int[10];
- }
- int n = outputLocals.length;
- if (local >= n) {
- int[] t = new int[Math.max(local + 1, 2 * n)];
- System.arraycopy(outputLocals, 0, t, 0, n);
- outputLocals = t;
- }
- // sets the local variable
- outputLocals[local] = type;
- }
-
- /**
- * Pushes a new type onto the output frame stack.
- *
- * @param type
- * the type that must be pushed.
- */
- private void push(final int type) {
- // creates and/or resizes the output stack array if necessary
- if (outputStack == null) {
- outputStack = new int[10];
- }
- int n = outputStack.length;
- if (outputStackTop >= n) {
- int[] t = new int[Math.max(outputStackTop + 1, 2 * n)];
- System.arraycopy(outputStack, 0, t, 0, n);
- outputStack = t;
- }
- // pushes the type on the output stack
- outputStack[outputStackTop++] = type;
- // updates the maximun height reached by the output stack, if needed
- int top = owner.inputStackTop + outputStackTop;
- if (top > owner.outputStackMax) {
- owner.outputStackMax = top;
- }
- }
-
- /**
- * Pushes a new type onto the output frame stack.
- *
- * @param cw
- * the ClassWriter to which this label belongs.
- * @param desc
- * the descriptor of the type to be pushed. Can also be a method
- * descriptor (in this case this method pushes its return type
- * onto the output frame stack).
- */
- private void push(final ClassWriter cw, final String desc) {
- int type = type(cw, desc);
- if (type != 0) {
- push(type);
- if (type == LONG || type == DOUBLE) {
- push(TOP);
- }
- }
- }
-
- /**
- * Returns the int encoding of the given type.
- *
- * @param cw
- * the ClassWriter to which this label belongs.
- * @param desc
- * a type descriptor.
- * @return the int encoding of the given type.
- */
- private static int type(final ClassWriter cw, final String desc) {
- String t;
- int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
- switch (desc.charAt(index)) {
- case 'V':
- return 0;
- case 'Z':
- case 'C':
- case 'B':
- case 'S':
- case 'I':
- return INTEGER;
- case 'F':
- return FLOAT;
- case 'J':
- return LONG;
- case 'D':
- return DOUBLE;
- case 'L':
- // stores the internal name, not the descriptor!
- t = desc.substring(index + 1, desc.length() - 1);
- return OBJECT | cw.addType(t);
- // case '[':
- default:
- // extracts the dimensions and the element type
- int data;
- int dims = index + 1;
- while (desc.charAt(dims) == '[') {
- ++dims;
- }
- switch (desc.charAt(dims)) {
- case 'Z':
- data = BOOLEAN;
- break;
- case 'C':
- data = CHAR;
- break;
- case 'B':
- data = BYTE;
- break;
- case 'S':
- data = SHORT;
- break;
- case 'I':
- data = INTEGER;
- break;
- case 'F':
- data = FLOAT;
- break;
- case 'J':
- data = LONG;
- break;
- case 'D':
- data = DOUBLE;
- break;
- // case 'L':
- default:
- // stores the internal name, not the descriptor
- t = desc.substring(dims + 1, desc.length() - 1);
- data = OBJECT | cw.addType(t);
- }
- return (dims - index) << 28 | data;
- }
- }
-
- /**
- * Pops a type from the output frame stack and returns its value.
- *
- * @return the type that has been popped from the output frame stack.
- */
- private int pop() {
- if (outputStackTop > 0) {
- return outputStack[--outputStackTop];
- } else {
- // if the output frame stack is empty, pops from the input stack
- return STACK | -(--owner.inputStackTop);
- }
- }
-
- /**
- * Pops the given number of types from the output frame stack.
- *
- * @param elements
- * the number of types that must be popped.
- */
- private void pop(final int elements) {
- if (outputStackTop >= elements) {
- outputStackTop -= elements;
- } else {
- // if the number of elements to be popped is greater than the number
- // of elements in the output stack, clear it, and pops the remaining
- // elements from the input stack.
- owner.inputStackTop -= elements - outputStackTop;
- outputStackTop = 0;
- }
- }
-
- /**
- * Pops a type from the output frame stack.
- *
- * @param desc
- * the descriptor of the type to be popped. Can also be a method
- * descriptor (in this case this method pops the types
- * corresponding to the method arguments).
- */
- private void pop(final String desc) {
- char c = desc.charAt(0);
- if (c == '(') {
- pop((Type.getArgumentsAndReturnSizes(desc) >> 2) - 1);
- } else if (c == 'J' || c == 'D') {
- pop(2);
- } else {
- pop(1);
- }
- }
-
- /**
- * Adds a new type to the list of types on which a constructor is invoked in
- * the basic block.
- *
- * @param var
- * a type on a which a constructor is invoked.
- */
- private void init(final int var) {
- // creates and/or resizes the initializations array if necessary
- if (initializations == null) {
- initializations = new int[2];
- }
- int n = initializations.length;
- if (initializationCount >= n) {
- int[] t = new int[Math.max(initializationCount + 1, 2 * n)];
- System.arraycopy(initializations, 0, t, 0, n);
- initializations = t;
- }
- // stores the type to be initialized
- initializations[initializationCount++] = var;
- }
-
- /**
- * Replaces the given type with the appropriate type if it is one of the
- * types on which a constructor is invoked in the basic block.
- *
- * @param cw
- * the ClassWriter to which this label belongs.
- * @param t
- * a type
- * @return t or, if t is one of the types on which a constructor is invoked
- * in the basic block, the type corresponding to this constructor.
- */
- private int init(final ClassWriter cw, final int t) {
- int s;
- if (t == UNINITIALIZED_THIS) {
- s = OBJECT | cw.addType(cw.thisName);
- } else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) {
- String type = cw.typeTable[t & BASE_VALUE].strVal1;
- s = OBJECT | cw.addType(type);
- } else {
- return t;
- }
- for (int j = 0; j < initializationCount; ++j) {
- int u = initializations[j];
- int dim = u & DIM;
- int kind = u & KIND;
- if (kind == LOCAL) {
- u = dim + inputLocals[u & VALUE];
- } else if (kind == STACK) {
- u = dim + inputStack[inputStack.length - (u & VALUE)];
- }
- if (t == u) {
- return s;
- }
- }
- return t;
- }
-
- /**
- * Initializes the input frame of the first basic block from the method
- * descriptor.
- *
- * @param cw
- * the ClassWriter to which this label belongs.
- * @param access
- * the access flags of the method to which this label belongs.
- * @param args
- * the formal parameter types of this method.
- * @param maxLocals
- * the maximum number of local variables of this method.
- */
- void initInputFrame(final ClassWriter cw, final int access,
- final Type[] args, final int maxLocals) {
- inputLocals = new int[maxLocals];
- inputStack = new int[0];
- int i = 0;
- if ((access & Opcodes.ACC_STATIC) == 0) {
- if ((access & MethodWriter.ACC_CONSTRUCTOR) == 0) {
- inputLocals[i++] = OBJECT | cw.addType(cw.thisName);
- } else {
- inputLocals[i++] = UNINITIALIZED_THIS;
- }
- }
- for (int j = 0; j < args.length; ++j) {
- int t = type(cw, args[j].getDescriptor());
- inputLocals[i++] = t;
- if (t == LONG || t == DOUBLE) {
- inputLocals[i++] = TOP;
- }
- }
- while (i < maxLocals) {
- inputLocals[i++] = TOP;
- }
- }
-
- /**
- * Simulates the action of the given instruction on the output stack frame.
- *
- * @param opcode
- * the opcode of the instruction.
- * @param arg
- * the operand of the instruction, if any.
- * @param cw
- * the class writer to which this label belongs.
- * @param item
- * the operand of the instructions, if any.
- */
- void execute(final int opcode, final int arg, final ClassWriter cw,
- final Item item) {
- int t1, t2, t3, t4;
- switch (opcode) {
- case Opcodes.NOP:
- case Opcodes.INEG:
- case Opcodes.LNEG:
- case Opcodes.FNEG:
- case Opcodes.DNEG:
- case Opcodes.I2B:
- case Opcodes.I2C:
- case Opcodes.I2S:
- case Opcodes.GOTO:
- case Opcodes.RETURN:
- break;
- case Opcodes.ACONST_NULL:
- push(NULL);
- break;
- case Opcodes.ICONST_M1:
- case Opcodes.ICONST_0:
- case Opcodes.ICONST_1:
- case Opcodes.ICONST_2:
- case Opcodes.ICONST_3:
- case Opcodes.ICONST_4:
- case Opcodes.ICONST_5:
- case Opcodes.BIPUSH:
- case Opcodes.SIPUSH:
- case Opcodes.ILOAD:
- push(INTEGER);
- break;
- case Opcodes.LCONST_0:
- case Opcodes.LCONST_1:
- case Opcodes.LLOAD:
- push(LONG);
- push(TOP);
- break;
- case Opcodes.FCONST_0:
- case Opcodes.FCONST_1:
- case Opcodes.FCONST_2:
- case Opcodes.FLOAD:
- push(FLOAT);
- break;
- case Opcodes.DCONST_0:
- case Opcodes.DCONST_1:
- case Opcodes.DLOAD:
- push(DOUBLE);
- push(TOP);
- break;
- case Opcodes.LDC:
- switch (item.type) {
- case ClassWriter.INT:
- push(INTEGER);
- break;
- case ClassWriter.LONG:
- push(LONG);
- push(TOP);
- break;
- case ClassWriter.FLOAT:
- push(FLOAT);
- break;
- case ClassWriter.DOUBLE:
- push(DOUBLE);
- push(TOP);
- break;
- case ClassWriter.CLASS:
- push(OBJECT | cw.addType("java/lang/Class"));
- break;
- case ClassWriter.STR:
- push(OBJECT | cw.addType("java/lang/String"));
- break;
- case ClassWriter.MTYPE:
- push(OBJECT | cw.addType("java/lang/invoke/MethodType"));
- break;
- // case ClassWriter.HANDLE_BASE + [1..9]:
- default:
- push(OBJECT | cw.addType("java/lang/invoke/MethodHandle"));
- }
- break;
- case Opcodes.ALOAD:
- push(get(arg));
- break;
- case Opcodes.IALOAD:
- case Opcodes.BALOAD:
- case Opcodes.CALOAD:
- case Opcodes.SALOAD:
- pop(2);
- push(INTEGER);
- break;
- case Opcodes.LALOAD:
- case Opcodes.D2L:
- pop(2);
- push(LONG);
- push(TOP);
- break;
- case Opcodes.FALOAD:
- pop(2);
- push(FLOAT);
- break;
- case Opcodes.DALOAD:
- case Opcodes.L2D:
- pop(2);
- push(DOUBLE);
- push(TOP);
- break;
- case Opcodes.AALOAD:
- pop(1);
- t1 = pop();
- push(ELEMENT_OF + t1);
- break;
- case Opcodes.ISTORE:
- case Opcodes.FSTORE:
- case Opcodes.ASTORE:
- t1 = pop();
- set(arg, t1);
- if (arg > 0) {
- t2 = get(arg - 1);
- // if t2 is of kind STACK or LOCAL we cannot know its size!
- if (t2 == LONG || t2 == DOUBLE) {
- set(arg - 1, TOP);
- } else if ((t2 & KIND) != BASE) {
- set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
- }
- }
- break;
- case Opcodes.LSTORE:
- case Opcodes.DSTORE:
- pop(1);
- t1 = pop();
- set(arg, t1);
- set(arg + 1, TOP);
- if (arg > 0) {
- t2 = get(arg - 1);
- // if t2 is of kind STACK or LOCAL we cannot know its size!
- if (t2 == LONG || t2 == DOUBLE) {
- set(arg - 1, TOP);
- } else if ((t2 & KIND) != BASE) {
- set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
- }
- }
- break;
- case Opcodes.IASTORE:
- case Opcodes.BASTORE:
- case Opcodes.CASTORE:
- case Opcodes.SASTORE:
- case Opcodes.FASTORE:
- case Opcodes.AASTORE:
- pop(3);
- break;
- case Opcodes.LASTORE:
- case Opcodes.DASTORE:
- pop(4);
- break;
- case Opcodes.POP:
- case Opcodes.IFEQ:
- case Opcodes.IFNE:
- case Opcodes.IFLT:
- case Opcodes.IFGE:
- case Opcodes.IFGT:
- case Opcodes.IFLE:
- case Opcodes.IRETURN:
- case Opcodes.FRETURN:
- case Opcodes.ARETURN:
- case Opcodes.TABLESWITCH:
- case Opcodes.LOOKUPSWITCH:
- case Opcodes.ATHROW:
- case Opcodes.MONITORENTER:
- case Opcodes.MONITOREXIT:
- case Opcodes.IFNULL:
- case Opcodes.IFNONNULL:
- pop(1);
- break;
- case Opcodes.POP2:
- case Opcodes.IF_ICMPEQ:
- case Opcodes.IF_ICMPNE:
- case Opcodes.IF_ICMPLT:
- case Opcodes.IF_ICMPGE:
- case Opcodes.IF_ICMPGT:
- case Opcodes.IF_ICMPLE:
- case Opcodes.IF_ACMPEQ:
- case Opcodes.IF_ACMPNE:
- case Opcodes.LRETURN:
- case Opcodes.DRETURN:
- pop(2);
- break;
- case Opcodes.DUP:
- t1 = pop();
- push(t1);
- push(t1);
- break;
- case Opcodes.DUP_X1:
- t1 = pop();
- t2 = pop();
- push(t1);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP_X2:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- push(t1);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2:
- t1 = pop();
- t2 = pop();
- push(t2);
- push(t1);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2_X1:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- push(t2);
- push(t1);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2_X2:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- t4 = pop();
- push(t2);
- push(t1);
- push(t4);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.SWAP:
- t1 = pop();
- t2 = pop();
- push(t1);
- push(t2);
- break;
- case Opcodes.IADD:
- case Opcodes.ISUB:
- case Opcodes.IMUL:
- case Opcodes.IDIV:
- case Opcodes.IREM:
- case Opcodes.IAND:
- case Opcodes.IOR:
- case Opcodes.IXOR:
- case Opcodes.ISHL:
- case Opcodes.ISHR:
- case Opcodes.IUSHR:
- case Opcodes.L2I:
- case Opcodes.D2I:
- case Opcodes.FCMPL:
- case Opcodes.FCMPG:
- pop(2);
- push(INTEGER);
- break;
- case Opcodes.LADD:
- case Opcodes.LSUB:
- case Opcodes.LMUL:
- case Opcodes.LDIV:
- case Opcodes.LREM:
- case Opcodes.LAND:
- case Opcodes.LOR:
- case Opcodes.LXOR:
- pop(4);
- push(LONG);
- push(TOP);
- break;
- case Opcodes.FADD:
- case Opcodes.FSUB:
- case Opcodes.FMUL:
- case Opcodes.FDIV:
- case Opcodes.FREM:
- case Opcodes.L2F:
- case Opcodes.D2F:
- pop(2);
- push(FLOAT);
- break;
- case Opcodes.DADD:
- case Opcodes.DSUB:
- case Opcodes.DMUL:
- case Opcodes.DDIV:
- case Opcodes.DREM:
- pop(4);
- push(DOUBLE);
- push(TOP);
- break;
- case Opcodes.LSHL:
- case Opcodes.LSHR:
- case Opcodes.LUSHR:
- pop(3);
- push(LONG);
- push(TOP);
- break;
- case Opcodes.IINC:
- set(arg, INTEGER);
- break;
- case Opcodes.I2L:
- case Opcodes.F2L:
- pop(1);
- push(LONG);
- push(TOP);
- break;
- case Opcodes.I2F:
- pop(1);
- push(FLOAT);
- break;
- case Opcodes.I2D:
- case Opcodes.F2D:
- pop(1);
- push(DOUBLE);
- push(TOP);
- break;
- case Opcodes.F2I:
- case Opcodes.ARRAYLENGTH:
- case Opcodes.INSTANCEOF:
- pop(1);
- push(INTEGER);
- break;
- case Opcodes.LCMP:
- case Opcodes.DCMPL:
- case Opcodes.DCMPG:
- pop(4);
- push(INTEGER);
- break;
- case Opcodes.JSR:
- case Opcodes.RET:
- throw new RuntimeException(
- "JSR/RET are not supported with computeFrames option");
- case Opcodes.GETSTATIC:
- push(cw, item.strVal3);
- break;
- case Opcodes.PUTSTATIC:
- pop(item.strVal3);
- break;
- case Opcodes.GETFIELD:
- pop(1);
- push(cw, item.strVal3);
- break;
- case Opcodes.PUTFIELD:
- pop(item.strVal3);
- pop();
- break;
- case Opcodes.INVOKEVIRTUAL:
- case Opcodes.INVOKESPECIAL:
- case Opcodes.INVOKESTATIC:
- case Opcodes.INVOKEINTERFACE:
- pop(item.strVal3);
- if (opcode != Opcodes.INVOKESTATIC) {
- t1 = pop();
- if (opcode == Opcodes.INVOKESPECIAL
- && item.strVal2.charAt(0) == '<') {
- init(t1);
- }
- }
- push(cw, item.strVal3);
- break;
- case Opcodes.INVOKEDYNAMIC:
- pop(item.strVal2);
- push(cw, item.strVal2);
- break;
- case Opcodes.NEW:
- push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
- break;
- case Opcodes.NEWARRAY:
- pop();
- switch (arg) {
- case Opcodes.T_BOOLEAN:
- push(ARRAY_OF | BOOLEAN);
- break;
- case Opcodes.T_CHAR:
- push(ARRAY_OF | CHAR);
- break;
- case Opcodes.T_BYTE:
- push(ARRAY_OF | BYTE);
- break;
- case Opcodes.T_SHORT:
- push(ARRAY_OF | SHORT);
- break;
- case Opcodes.T_INT:
- push(ARRAY_OF | INTEGER);
- break;
- case Opcodes.T_FLOAT:
- push(ARRAY_OF | FLOAT);
- break;
- case Opcodes.T_DOUBLE:
- push(ARRAY_OF | DOUBLE);
- break;
- // case Opcodes.T_LONG:
- default:
- push(ARRAY_OF | LONG);
- break;
- }
- break;
- case Opcodes.ANEWARRAY:
- String s = item.strVal1;
- pop();
- if (s.charAt(0) == '[') {
- push(cw, '[' + s);
- } else {
- push(ARRAY_OF | OBJECT | cw.addType(s));
- }
- break;
- case Opcodes.CHECKCAST:
- s = item.strVal1;
- pop();
- if (s.charAt(0) == '[') {
- push(cw, s);
- } else {
- push(OBJECT | cw.addType(s));
- }
- break;
- // case Opcodes.MULTIANEWARRAY:
- default:
- pop(arg);
- push(cw, item.strVal1);
- break;
- }
- }
-
- /**
- * Merges the input frame of the given basic block with the input and output
- * frames of this basic block. Returns <tt>true</tt> if the input frame of
- * the given label has been changed by this operation.
- *
- * @param cw
- * the ClassWriter to which this label belongs.
- * @param frame
- * the basic block whose input frame must be updated.
- * @param edge
- * the kind of the {@link Edge} between this label and 'label'.
- * See {@link Edge#info}.
- * @return <tt>true</tt> if the input frame of the given label has been
- * changed by this operation.
- */
- boolean merge(final ClassWriter cw, final Frame frame, final int edge) {
- boolean changed = false;
- int i, s, dim, kind, t;
-
- int nLocal = inputLocals.length;
- int nStack = inputStack.length;
- if (frame.inputLocals == null) {
- frame.inputLocals = new int[nLocal];
- changed = true;
- }
-
- for (i = 0; i < nLocal; ++i) {
- if (outputLocals != null && i < outputLocals.length) {
- s = outputLocals[i];
- if (s == 0) {
- t = inputLocals[i];
- } else {
- dim = s & DIM;
- kind = s & KIND;
- if (kind == BASE) {
- t = s;
- } else {
- if (kind == LOCAL) {
- t = dim + inputLocals[s & VALUE];
- } else {
- t = dim + inputStack[nStack - (s & VALUE)];
- }
- if ((s & TOP_IF_LONG_OR_DOUBLE) != 0
- && (t == LONG || t == DOUBLE)) {
- t = TOP;
- }
- }
- }
- } else {
- t = inputLocals[i];
- }
- if (initializations != null) {
- t = init(cw, t);
- }
- changed |= merge(cw, t, frame.inputLocals, i);
- }
-
- if (edge > 0) {
- for (i = 0; i < nLocal; ++i) {
- t = inputLocals[i];
- changed |= merge(cw, t, frame.inputLocals, i);
- }
- if (frame.inputStack == null) {
- frame.inputStack = new int[1];
- changed = true;
- }
- changed |= merge(cw, edge, frame.inputStack, 0);
- return changed;
- }
-
- int nInputStack = inputStack.length + owner.inputStackTop;
- if (frame.inputStack == null) {
- frame.inputStack = new int[nInputStack + outputStackTop];
- changed = true;
- }
-
- for (i = 0; i < nInputStack; ++i) {
- t = inputStack[i];
- if (initializations != null) {
- t = init(cw, t);
- }
- changed |= merge(cw, t, frame.inputStack, i);
- }
- for (i = 0; i < outputStackTop; ++i) {
- s = outputStack[i];
- dim = s & DIM;
- kind = s & KIND;
- if (kind == BASE) {
- t = s;
- } else {
- if (kind == LOCAL) {
- t = dim + inputLocals[s & VALUE];
- } else {
- t = dim + inputStack[nStack - (s & VALUE)];
- }
- if ((s & TOP_IF_LONG_OR_DOUBLE) != 0
- && (t == LONG || t == DOUBLE)) {
- t = TOP;
- }
- }
- if (initializations != null) {
- t = init(cw, t);
- }
- changed |= merge(cw, t, frame.inputStack, nInputStack + i);
- }
- return changed;
- }
-
- /**
- * Merges the type at the given index in the given type array with the given
- * type. Returns <tt>true</tt> if the type array has been modified by this
- * operation.
- *
- * @param cw
- * the ClassWriter to which this label belongs.
- * @param t
- * the type with which the type array element must be merged.
- * @param types
- * an array of types.
- * @param index
- * the index of the type that must be merged in 'types'.
- * @return <tt>true</tt> if the type array has been modified by this
- * operation.
- */
- private static boolean merge(final ClassWriter cw, int t,
- final int[] types, final int index) {
- int u = types[index];
- if (u == t) {
- // if the types are equal, merge(u,t)=u, so there is no change
- return false;
- }
- if ((t & ~DIM) == NULL) {
- if (u == NULL) {
- return false;
- }
- t = NULL;
- }
- if (u == 0) {
- // if types[index] has never been assigned, merge(u,t)=t
- types[index] = t;
- return true;
- }
- int v;
- if ((u & BASE_KIND) == OBJECT || (u & DIM) != 0) {
- // if u is a reference type of any dimension
- if (t == NULL) {
- // if t is the NULL type, merge(u,t)=u, so there is no change
- return false;
- } else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) {
- if ((u & BASE_KIND) == OBJECT) {
- // if t is also a reference type, and if u and t have the
- // same dimension merge(u,t) = dim(t) | common parent of the
- // element types of u and t
- v = (t & DIM) | OBJECT
- | cw.getMergedType(t & BASE_VALUE, u & BASE_VALUE);
- } else {
- // if u and t are array types, but not with the same element
- // type, merge(u,t)=java/lang/Object
- v = OBJECT | cw.addType("java/lang/Object");
- }
- } else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) {
- // if t is any other reference or array type,
- // merge(u,t)=java/lang/Object
- v = OBJECT | cw.addType("java/lang/Object");
- } else {
- // if t is any other type, merge(u,t)=TOP
- v = TOP;
- }
- } else if (u == NULL) {
- // if u is the NULL type, merge(u,t)=t,
- // or TOP if t is not a reference type
- v = (t & BASE_KIND) == OBJECT || (t & DIM) != 0 ? t : TOP;
- } else {
- // if u is any other type, merge(u,t)=TOP whatever t
- v = TOP;
- }
- if (u != v) {
- types[index] = v;
- return true;
- }
- return false;
- }
-}
diff --git a/src/jvm/clojure/asm/Handle.java b/src/jvm/clojure/asm/Handle.java
deleted file mode 100644
index a147cf1..0000000
--- a/src/jvm/clojure/asm/Handle.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-/**
- * A reference to a field or a method.
- *
- * @author Remi Forax
- * @author Eric Bruneton
- */
-public final class Handle {
-
- /**
- * The kind of field or method designated by this Handle. Should be
- * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
- * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
- * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
- * {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or
- * {@link Opcodes#H_INVOKEINTERFACE}.
- */
- final int tag;
-
- /**
- * The internal name of the field or method designed by this handle.
- */
- final String owner;
-
- /**
- * The name of the field or method designated by this handle.
- */
- final String name;
-
- /**
- * The descriptor of the field or method designated by this handle.
- */
- final String desc;
-
- /**
- * Constructs a new field or method handle.
- *
- * @param tag
- * the kind of field or method designated by this Handle. Must be
- * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
- * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
- * {@link Opcodes#H_INVOKEVIRTUAL},
- * {@link Opcodes#H_INVOKESTATIC},
- * {@link Opcodes#H_INVOKESPECIAL},
- * {@link Opcodes#H_NEWINVOKESPECIAL} or
- * {@link Opcodes#H_INVOKEINTERFACE}.
- * @param owner
- * the internal name of the field or method designed by this
- * handle.
- * @param name
- * the name of the field or method designated by this handle.
- * @param desc
- * the descriptor of the field or method designated by this
- * handle.
- */
- public Handle(int tag, String owner, String name, String desc) {
- this.tag = tag;
- this.owner = owner;
- this.name = name;
- this.desc = desc;
- }
-
- /**
- * Returns the kind of field or method designated by this handle.
- *
- * @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
- * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
- * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
- * {@link Opcodes#H_INVOKESPECIAL},
- * {@link Opcodes#H_NEWINVOKESPECIAL} or
- * {@link Opcodes#H_INVOKEINTERFACE}.
- */
- public int getTag() {
- return tag;
- }
-
- /**
- * Returns the internal name of the field or method designed by this handle.
- *
- * @return the internal name of the field or method designed by this handle.
- */
- public String getOwner() {
- return owner;
- }
-
- /**
- * Returns the name of the field or method designated by this handle.
- *
- * @return the name of the field or method designated by this handle.
- */
- public String getName() {
- return name;
- }
-
- /**
- * Returns the descriptor of the field or method designated by this handle.
- *
- * @return the descriptor of the field or method designated by this handle.
- */
- public String getDesc() {
- return desc;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == this) {
- return true;
- }
- if (!(obj instanceof Handle)) {
- return false;
- }
- Handle h = (Handle) obj;
- return tag == h.tag && owner.equals(h.owner) && name.equals(h.name)
- && desc.equals(h.desc);
- }
-
- @Override
- public int hashCode() {
- return tag + owner.hashCode() * name.hashCode() * desc.hashCode();
- }
-
- /**
- * Returns the textual representation of this handle. The textual
- * representation is:
- *
- * <pre>
- * owner '.' name desc ' ' '(' tag ')'
- * </pre>
- *
- * . As this format is unambiguous, it can be parsed if necessary.
- */
- @Override
- public String toString() {
- return owner + '.' + name + desc + " (" + tag + ')';
- }
-}
diff --git a/src/jvm/clojure/asm/Handler.java b/src/jvm/clojure/asm/Handler.java
deleted file mode 100644
index bc0579e..0000000
--- a/src/jvm/clojure/asm/Handler.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-/**
- * Information about an exception handler block.
- *
- * @author Eric Bruneton
- */
-class Handler {
-
- /**
- * Beginning of the exception handler's scope (inclusive).
- */
- Label start;
-
- /**
- * End of the exception handler's scope (exclusive).
- */
- Label end;
-
- /**
- * Beginning of the exception handler's code.
- */
- Label handler;
-
- /**
- * Internal name of the type of exceptions handled by this handler, or
- * <tt>null</tt> to catch any exceptions.
- */
- String desc;
-
- /**
- * Constant pool index of the internal name of the type of exceptions
- * handled by this handler, or 0 to catch any exceptions.
- */
- int type;
-
- /**
- * Next exception handler block info.
- */
- Handler next;
-
- /**
- * Removes the range between start and end from the given exception
- * handlers.
- *
- * @param h
- * an exception handler list.
- * @param start
- * the start of the range to be removed.
- * @param end
- * the end of the range to be removed. Maybe null.
- * @return the exception handler list with the start-end range removed.
- */
- static Handler remove(Handler h, Label start, Label end) {
- if (h == null) {
- return null;
- } else {
- h.next = remove(h.next, start, end);
- }
- int hstart = h.start.position;
- int hend = h.end.position;
- int s = start.position;
- int e = end == null ? Integer.MAX_VALUE : end.position;
- // if [hstart,hend[ and [s,e[ intervals intersect...
- if (s < hend && e > hstart) {
- if (s <= hstart) {
- if (e >= hend) {
- // [hstart,hend[ fully included in [s,e[, h removed
- h = h.next;
- } else {
- // [hstart,hend[ minus [s,e[ = [e,hend[
- h.start = end;
- }
- } else if (e >= hend) {
- // [hstart,hend[ minus [s,e[ = [hstart,s[
- h.end = start;
- } else {
- // [hstart,hend[ minus [s,e[ = [hstart,s[ + [e,hend[
- Handler g = new Handler();
- g.start = end;
- g.end = h.end;
- g.handler = h.handler;
- g.desc = h.desc;
- g.type = h.type;
- g.next = h.next;
- h.end = start;
- h.next = g;
- }
- }
- return h;
- }
-}
diff --git a/src/jvm/clojure/asm/Item.java b/src/jvm/clojure/asm/Item.java
deleted file mode 100644
index 274a548..0000000
--- a/src/jvm/clojure/asm/Item.java
+++ /dev/null
@@ -1,311 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-/**
- * A constant pool item. Constant pool items can be created with the 'newXXX'
- * methods in the {@link ClassWriter} class.
- *
- * @author Eric Bruneton
- */
-final class Item {
-
- /**
- * Index of this item in the constant pool.
- */
- int index;
-
- /**
- * Type of this constant pool item. A single class is used to represent all
- * constant pool item types, in order to minimize the bytecode size of this
- * package. The value of this field is one of {@link ClassWriter#INT},
- * {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT},
- * {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8},
- * {@link ClassWriter#STR}, {@link ClassWriter#CLASS},
- * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
- * {@link ClassWriter#METH}, {@link ClassWriter#IMETH},
- * {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
- *
- * MethodHandle constant 9 variations are stored using a range of 9 values
- * from {@link ClassWriter#HANDLE_BASE} + 1 to
- * {@link ClassWriter#HANDLE_BASE} + 9.
- *
- * Special Item types are used for Items that are stored in the ClassWriter
- * {@link ClassWriter#typeTable}, instead of the constant pool, in order to
- * avoid clashes with normal constant pool items in the ClassWriter constant
- * pool's hash table. These special item types are
- * {@link ClassWriter#TYPE_NORMAL}, {@link ClassWriter#TYPE_UNINIT} and
- * {@link ClassWriter#TYPE_MERGED}.
- */
- int type;
-
- /**
- * Value of this item, for an integer item.
- */
- int intVal;
-
- /**
- * Value of this item, for a long item.
- */
- long longVal;
-
- /**
- * First part of the value of this item, for items that do not hold a
- * primitive value.
- */
- String strVal1;
-
- /**
- * Second part of the value of this item, for items that do not hold a
- * primitive value.
- */
- String strVal2;
-
- /**
- * Third part of the value of this item, for items that do not hold a
- * primitive value.
- */
- String strVal3;
-
- /**
- * The hash code value of this constant pool item.
- */
- int hashCode;
-
- /**
- * Link to another constant pool item, used for collision lists in the
- * constant pool's hash table.
- */
- Item next;
-
- /**
- * Constructs an uninitialized {@link Item}.
- */
- Item() {
- }
-
- /**
- * Constructs an uninitialized {@link Item} for constant pool element at
- * given position.
- *
- * @param index
- * index of the item to be constructed.
- */
- Item(final int index) {
- this.index = index;
- }
-
- /**
- * Constructs a copy of the given item.
- *
- * @param index
- * index of the item to be constructed.
- * @param i
- * the item that must be copied into the item to be constructed.
- */
- Item(final int index, final Item i) {
- this.index = index;
- type = i.type;
- intVal = i.intVal;
- longVal = i.longVal;
- strVal1 = i.strVal1;
- strVal2 = i.strVal2;
- strVal3 = i.strVal3;
- hashCode = i.hashCode;
- }
-
- /**
- * Sets this item to an integer item.
- *
- * @param intVal
- * the value of this item.
- */
- void set(final int intVal) {
- this.type = ClassWriter.INT;
- this.intVal = intVal;
- this.hashCode = 0x7FFFFFFF & (type + intVal);
- }
-
- /**
- * Sets this item to a long item.
- *
- * @param longVal
- * the value of this item.
- */
- void set(final long longVal) {
- this.type = ClassWriter.LONG;
- this.longVal = longVal;
- this.hashCode = 0x7FFFFFFF & (type + (int) longVal);
- }
-
- /**
- * Sets this item to a float item.
- *
- * @param floatVal
- * the value of this item.
- */
- void set(final float floatVal) {
- this.type = ClassWriter.FLOAT;
- this.intVal = Float.floatToRawIntBits(floatVal);
- this.hashCode = 0x7FFFFFFF & (type + (int) floatVal);
- }
-
- /**
- * Sets this item to a double item.
- *
- * @param doubleVal
- * the value of this item.
- */
- void set(final double doubleVal) {
- this.type = ClassWriter.DOUBLE;
- this.longVal = Double.doubleToRawLongBits(doubleVal);
- this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal);
- }
-
- /**
- * Sets this item to an item that do not hold a primitive value.
- *
- * @param type
- * the type of this item.
- * @param strVal1
- * first part of the value of this item.
- * @param strVal2
- * second part of the value of this item.
- * @param strVal3
- * third part of the value of this item.
- */
- void set(final int type, final String strVal1, final String strVal2,
- final String strVal3) {
- this.type = type;
- this.strVal1 = strVal1;
- this.strVal2 = strVal2;
- this.strVal3 = strVal3;
- switch (type) {
- case ClassWriter.UTF8:
- case ClassWriter.STR:
- case ClassWriter.CLASS:
- case ClassWriter.MTYPE:
- case ClassWriter.TYPE_NORMAL:
- hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
- return;
- case ClassWriter.NAME_TYPE: {
- hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
- * strVal2.hashCode());
- return;
- }
- // ClassWriter.FIELD:
- // ClassWriter.METH:
- // ClassWriter.IMETH:
- // ClassWriter.HANDLE_BASE + 1..9
- default:
- hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
- * strVal2.hashCode() * strVal3.hashCode());
- }
- }
-
- /**
- * Sets the item to an InvokeDynamic item.
- *
- * @param name
- * invokedynamic's name.
- * @param desc
- * invokedynamic's desc.
- * @param bsmIndex
- * zero based index into the class attribute BootrapMethods.
- */
- void set(String name, String desc, int bsmIndex) {
- this.type = ClassWriter.INDY;
- this.longVal = bsmIndex;
- this.strVal1 = name;
- this.strVal2 = desc;
- this.hashCode = 0x7FFFFFFF & (ClassWriter.INDY + bsmIndex
- * strVal1.hashCode() * strVal2.hashCode());
- }
-
- /**
- * Sets the item to a BootstrapMethod item.
- *
- * @param position
- * position in byte in the class attribute BootrapMethods.
- * @param hashCode
- * hashcode of the item. This hashcode is processed from the
- * hashcode of the bootstrap method and the hashcode of all
- * bootstrap arguments.
- */
- void set(int position, int hashCode) {
- this.type = ClassWriter.BSM;
- this.intVal = position;
- this.hashCode = hashCode;
- }
-
- /**
- * Indicates if the given item is equal to this one. <i>This method assumes
- * that the two items have the same {@link #type}</i>.
- *
- * @param i
- * the item to be compared to this one. Both items must have the
- * same {@link #type}.
- * @return <tt>true</tt> if the given item if equal to this one,
- * <tt>false</tt> otherwise.
- */
- boolean isEqualTo(final Item i) {
- switch (type) {
- case ClassWriter.UTF8:
- case ClassWriter.STR:
- case ClassWriter.CLASS:
- case ClassWriter.MTYPE:
- case ClassWriter.TYPE_NORMAL:
- return i.strVal1.equals(strVal1);
- case ClassWriter.TYPE_MERGED:
- case ClassWriter.LONG:
- case ClassWriter.DOUBLE:
- return i.longVal == longVal;
- case ClassWriter.INT:
- case ClassWriter.FLOAT:
- return i.intVal == intVal;
- case ClassWriter.TYPE_UNINIT:
- return i.intVal == intVal && i.strVal1.equals(strVal1);
- case ClassWriter.NAME_TYPE:
- return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
- case ClassWriter.INDY: {
- return i.longVal == longVal && i.strVal1.equals(strVal1)
- && i.strVal2.equals(strVal2);
- }
- // case ClassWriter.FIELD:
- // case ClassWriter.METH:
- // case ClassWriter.IMETH:
- // case ClassWriter.HANDLE_BASE + 1..9
- default:
- return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2)
- && i.strVal3.equals(strVal3);
- }
- }
-
-}
diff --git a/src/jvm/clojure/asm/Label.java b/src/jvm/clojure/asm/Label.java
deleted file mode 100644
index 735e1b9..0000000
--- a/src/jvm/clojure/asm/Label.java
+++ /dev/null
@@ -1,560 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-/**
- * A label represents a position in the bytecode of a method. Labels are used
- * for jump, goto, and switch instructions, and for try catch blocks. A label
- * designates the <i>instruction</i> that is just after. Note however that there
- * can be other elements between a label and the instruction it designates (such
- * as other labels, stack map frames, line numbers, etc.).
- *
- * @author Eric Bruneton
- */
-public class Label {
-
- /**
- * Indicates if this label is only used for debug attributes. Such a label
- * is not the start of a basic block, the target of a jump instruction, or
- * an exception handler. It can be safely ignored in control flow graph
- * analysis algorithms (for optimization purposes).
- */
- static final int DEBUG = 1;
-
- /**
- * Indicates if the position of this label is known.
- */
- static final int RESOLVED = 2;
-
- /**
- * Indicates if this label has been updated, after instruction resizing.
- */
- static final int RESIZED = 4;
-
- /**
- * Indicates if this basic block has been pushed in the basic block stack.
- * See {@link MethodWriter#visitMaxs visitMaxs}.
- */
- static final int PUSHED = 8;
-
- /**
- * Indicates if this label is the target of a jump instruction, or the start
- * of an exception handler.
- */
- static final int TARGET = 16;
-
- /**
- * Indicates if a stack map frame must be stored for this label.
- */
- static final int STORE = 32;
-
- /**
- * Indicates if this label corresponds to a reachable basic block.
- */
- static final int REACHABLE = 64;
-
- /**
- * Indicates if this basic block ends with a JSR instruction.
- */
- static final int JSR = 128;
-
- /**
- * Indicates if this basic block ends with a RET instruction.
- */
- static final int RET = 256;
-
- /**
- * Indicates if this basic block is the start of a subroutine.
- */
- static final int SUBROUTINE = 512;
-
- /**
- * Indicates if this subroutine basic block has been visited by a
- * visitSubroutine(null, ...) call.
- */
- static final int VISITED = 1024;
-
- /**
- * Indicates if this subroutine basic block has been visited by a
- * visitSubroutine(!null, ...) call.
- */
- static final int VISITED2 = 2048;
-
- /**
- * Field used to associate user information to a label. Warning: this field
- * is used by the ASM tree package. In order to use it with the ASM tree
- * package you must override the
- * {@link clojure.asm.tree.MethodNode#getLabelNode} method.
- */
- public Object info;
-
- /**
- * Flags that indicate the status of this label.
- *
- * @see #DEBUG
- * @see #RESOLVED
- * @see #RESIZED
- * @see #PUSHED
- * @see #TARGET
- * @see #STORE
- * @see #REACHABLE
- * @see #JSR
- * @see #RET
- */
- int status;
-
- /**
- * The line number corresponding to this label, if known.
- */
- int line;
-
- /**
- * The position of this label in the code, if known.
- */
- int position;
-
- /**
- * Number of forward references to this label, times two.
- */
- private int referenceCount;
-
- /**
- * Informations about forward references. Each forward reference is
- * described by two consecutive integers in this array: the first one is the
- * position of the first byte of the bytecode instruction that contains the
- * forward reference, while the second is the position of the first byte of
- * the forward reference itself. In fact the sign of the first integer
- * indicates if this reference uses 2 or 4 bytes, and its absolute value
- * gives the position of the bytecode instruction. This array is also used
- * as a bitset to store the subroutines to which a basic block belongs. This
- * information is needed in {@linked MethodWriter#visitMaxs}, after all
- * forward references have been resolved. Hence the same array can be used
- * for both purposes without problems.
- */
- private int[] srcAndRefPositions;
-
- // ------------------------------------------------------------------------
-
- /*
- * Fields for the control flow and data flow graph analysis algorithms (used
- * to compute the maximum stack size or the stack map frames). A control
- * flow graph contains one node per "basic block", and one edge per "jump"
- * from one basic block to another. Each node (i.e., each basic block) is
- * represented by the Label object that corresponds to the first instruction
- * of this basic block. Each node also stores the list of its successors in
- * the graph, as a linked list of Edge objects.
- *
- * The control flow analysis algorithms used to compute the maximum stack
- * size or the stack map frames are similar and use two steps. The first
- * step, during the visit of each instruction, builds information about the
- * state of the local variables and the operand stack at the end of each
- * basic block, called the "output frame", <i>relatively</i> to the frame
- * state at the beginning of the basic block, which is called the "input
- * frame", and which is <i>unknown</i> during this step. The second step, in
- * {@link MethodWriter#visitMaxs}, is a fix point algorithm that computes
- * information about the input frame of each basic block, from the input
- * state of the first basic block (known from the method signature), and by
- * the using the previously computed relative output frames.
- *
- * The algorithm used to compute the maximum stack size only computes the
- * relative output and absolute input stack heights, while the algorithm
- * used to compute stack map frames computes relative output frames and
- * absolute input frames.
- */
-
- /**
- * Start of the output stack relatively to the input stack. The exact
- * semantics of this field depends on the algorithm that is used.
- *
- * When only the maximum stack size is computed, this field is the number of
- * elements in the input stack.
- *
- * When the stack map frames are completely computed, this field is the
- * offset of the first output stack element relatively to the top of the
- * input stack. This offset is always negative or null. A null offset means
- * that the output stack must be appended to the input stack. A -n offset
- * means that the first n output stack elements must replace the top n input
- * stack elements, and that the other elements must be appended to the input
- * stack.
- */
- int inputStackTop;
-
- /**
- * Maximum height reached by the output stack, relatively to the top of the
- * input stack. This maximum is always positive or null.
- */
- int outputStackMax;
-
- /**
- * Information about the input and output stack map frames of this basic
- * block. This field is only used when {@link ClassWriter#COMPUTE_FRAMES}
- * option is used.
- */
- Frame frame;
-
- /**
- * The successor of this label, in the order they are visited. This linked
- * list does not include labels used for debug info only. If
- * {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it
- * does not contain successive labels that denote the same bytecode position
- * (in this case only the first label appears in this list).
- */
- Label successor;
-
- /**
- * The successors of this node in the control flow graph. These successors
- * are stored in a linked list of {@link Edge Edge} objects, linked to each
- * other by their {@link Edge#next} field.
- */
- Edge successors;
-
- /**
- * The next basic block in the basic block stack. This stack is used in the
- * main loop of the fix point algorithm used in the second step of the
- * control flow analysis algorithms. It is also used in
- * {@link #visitSubroutine} to avoid using a recursive method.
- *
- * @see MethodWriter#visitMaxs
- */
- Label next;
-
- // ------------------------------------------------------------------------
- // Constructor
- // ------------------------------------------------------------------------
-
- /**
- * Constructs a new label.
- */
- public Label() {
- }
-
- // ------------------------------------------------------------------------
- // Methods to compute offsets and to manage forward references
- // ------------------------------------------------------------------------
-
- /**
- * Returns the offset corresponding to this label. This offset is computed
- * from the start of the method's bytecode. <i>This method is intended for
- * {@link Attribute} sub classes, and is normally not needed by class
- * generators or adapters.</i>
- *
- * @return the offset corresponding to this label.
- * @throws IllegalStateException
- * if this label is not resolved yet.
- */
- public int getOffset() {
- if ((status & RESOLVED) == 0) {
- throw new IllegalStateException(
- "Label offset position has not been resolved yet");
- }
- return position;
- }
-
- /**
- * Puts a reference to this label in the bytecode of a method. If the
- * position of the label is known, the offset is computed and written
- * directly. Otherwise, a null offset is written and a new forward reference
- * is declared for this label.
- *
- * @param owner
- * the code writer that calls this method.
- * @param out
- * the bytecode of the method.
- * @param source
- * the position of first byte of the bytecode instruction that
- * contains this label.
- * @param wideOffset
- * <tt>true</tt> if the reference must be stored in 4 bytes, or
- * <tt>false</tt> if it must be stored with 2 bytes.
- * @throws IllegalArgumentException
- * if this label has not been created by the given code writer.
- */
- void put(final MethodWriter owner, final ByteVector out, final int source,
- final boolean wideOffset) {
- if ((status & RESOLVED) == 0) {
- if (wideOffset) {
- addReference(-1 - source, out.length);
- out.putInt(-1);
- } else {
- addReference(source, out.length);
- out.putShort(-1);
- }
- } else {
- if (wideOffset) {
- out.putInt(position - source);
- } else {
- out.putShort(position - source);
- }
- }
- }
-
- /**
- * Adds a forward reference to this label. This method must be called only
- * for a true forward reference, i.e. only if this label is not resolved
- * yet. For backward references, the offset of the reference can be, and
- * must be, computed and stored directly.
- *
- * @param sourcePosition
- * the position of the referencing instruction. This position
- * will be used to compute the offset of this forward reference.
- * @param referencePosition
- * the position where the offset for this forward reference must
- * be stored.
- */
- private void addReference(final int sourcePosition,
- final int referencePosition) {
- if (srcAndRefPositions == null) {
- srcAndRefPositions = new int[6];
- }
- if (referenceCount >= srcAndRefPositions.length) {
- int[] a = new int[srcAndRefPositions.length + 6];
- System.arraycopy(srcAndRefPositions, 0, a, 0,
- srcAndRefPositions.length);
- srcAndRefPositions = a;
- }
- srcAndRefPositions[referenceCount++] = sourcePosition;
- srcAndRefPositions[referenceCount++] = referencePosition;
- }
-
- /**
- * Resolves all forward references to this label. This method must be called
- * when this label is added to the bytecode of the method, i.e. when its
- * position becomes known. This method fills in the blanks that where left
- * in the bytecode by each forward reference previously added to this label.
- *
- * @param owner
- * the code writer that calls this method.
- * @param position
- * the position of this label in the bytecode.
- * @param data
- * the bytecode of the method.
- * @return <tt>true</tt> if a blank that was left for this label was to
- * small to store the offset. In such a case the corresponding jump
- * instruction is replaced with a pseudo instruction (using unused
- * opcodes) using an unsigned two bytes offset. These pseudo
- * instructions will need to be replaced with true instructions with
- * wider offsets (4 bytes instead of 2). This is done in
- * {@link MethodWriter#resizeInstructions}.
- * @throws IllegalArgumentException
- * if this label has already been resolved, or if it has not
- * been created by the given code writer.
- */
- boolean resolve(final MethodWriter owner, final int position,
- final byte[] data) {
- boolean needUpdate = false;
- this.status |= RESOLVED;
- this.position = position;
- int i = 0;
- while (i < referenceCount) {
- int source = srcAndRefPositions[i++];
- int reference = srcAndRefPositions[i++];
- int offset;
- if (source >= 0) {
- offset = position - source;
- if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
- /*
- * changes the opcode of the jump instruction, in order to
- * be able to find it later (see resizeInstructions in
- * MethodWriter). These temporary opcodes are similar to
- * jump instruction opcodes, except that the 2 bytes offset
- * is unsigned (and can therefore represent values from 0 to
- * 65535, which is sufficient since the size of a method is
- * limited to 65535 bytes).
- */
- int opcode = data[reference - 1] & 0xFF;
- if (opcode <= Opcodes.JSR) {
- // changes IFEQ ... JSR to opcodes 202 to 217
- data[reference - 1] = (byte) (opcode + 49);
- } else {
- // changes IFNULL and IFNONNULL to opcodes 218 and 219
- data[reference - 1] = (byte) (opcode + 20);
- }
- needUpdate = true;
- }
- data[reference++] = (byte) (offset >>> 8);
- data[reference] = (byte) offset;
- } else {
- offset = position + source + 1;
- data[reference++] = (byte) (offset >>> 24);
- data[reference++] = (byte) (offset >>> 16);
- data[reference++] = (byte) (offset >>> 8);
- data[reference] = (byte) offset;
- }
- }
- return needUpdate;
- }
-
- /**
- * Returns the first label of the series to which this label belongs. For an
- * isolated label or for the first label in a series of successive labels,
- * this method returns the label itself. For other labels it returns the
- * first label of the series.
- *
- * @return the first label of the series to which this label belongs.
- */
- Label getFirst() {
- return !ClassReader.FRAMES || frame == null ? this : frame.owner;
- }
-
- // ------------------------------------------------------------------------
- // Methods related to subroutines
- // ------------------------------------------------------------------------
-
- /**
- * Returns true is this basic block belongs to the given subroutine.
- *
- * @param id
- * a subroutine id.
- * @return true is this basic block belongs to the given subroutine.
- */
- boolean inSubroutine(final long id) {
- if ((status & Label.VISITED) != 0) {
- return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0;
- }
- return false;
- }
-
- /**
- * Returns true if this basic block and the given one belong to a common
- * subroutine.
- *
- * @param block
- * another basic block.
- * @return true if this basic block and the given one belong to a common
- * subroutine.
- */
- boolean inSameSubroutine(final Label block) {
- if ((status & VISITED) == 0 || (block.status & VISITED) == 0) {
- return false;
- }
- for (int i = 0; i < srcAndRefPositions.length; ++i) {
- if ((srcAndRefPositions[i] & block.srcAndRefPositions[i]) != 0) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Marks this basic block as belonging to the given subroutine.
- *
- * @param id
- * a subroutine id.
- * @param nbSubroutines
- * the total number of subroutines in the method.
- */
- void addToSubroutine(final long id, final int nbSubroutines) {
- if ((status & VISITED) == 0) {
- status |= VISITED;
- srcAndRefPositions = new int[(nbSubroutines - 1) / 32 + 1];
- }
- srcAndRefPositions[(int) (id >>> 32)] |= (int) id;
- }
-
- /**
- * Finds the basic blocks that belong to a given subroutine, and marks these
- * blocks as belonging to this subroutine. This method follows the control
- * flow graph to find all the blocks that are reachable from the current
- * block WITHOUT following any JSR target.
- *
- * @param JSR
- * a JSR block that jumps to this subroutine. If this JSR is not
- * null it is added to the successor of the RET blocks found in
- * the subroutine.
- * @param id
- * the id of this subroutine.
- * @param nbSubroutines
- * the total number of subroutines in the method.
- */
- void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) {
- // user managed stack of labels, to avoid using a recursive method
- // (recursivity can lead to stack overflow with very large methods)
- Label stack = this;
- while (stack != null) {
- // removes a label l from the stack
- Label l = stack;
- stack = l.next;
- l.next = null;
-
- if (JSR != null) {
- if ((l.status & VISITED2) != 0) {
- continue;
- }
- l.status |= VISITED2;
- // adds JSR to the successors of l, if it is a RET block
- if ((l.status & RET) != 0) {
- if (!l.inSameSubroutine(JSR)) {
- Edge e = new Edge();
- e.info = l.inputStackTop;
- e.successor = JSR.successors.successor;
- e.next = l.successors;
- l.successors = e;
- }
- }
- } else {
- // if the l block already belongs to subroutine 'id', continue
- if (l.inSubroutine(id)) {
- continue;
- }
- // marks the l block as belonging to subroutine 'id'
- l.addToSubroutine(id, nbSubroutines);
- }
- // pushes each successor of l on the stack, except JSR targets
- Edge e = l.successors;
- while (e != null) {
- // if the l block is a JSR block, then 'l.successors.next' leads
- // to the JSR target (see {@link #visitJumpInsn}) and must
- // therefore not be followed
- if ((l.status & Label.JSR) == 0 || e != l.successors.next) {
- // pushes e.successor on the stack if it not already added
- if (e.successor.next == null) {
- e.successor.next = stack;
- stack = e.successor;
- }
- }
- e = e.next;
- }
- }
- }
-
- // ------------------------------------------------------------------------
- // Overriden Object methods
- // ------------------------------------------------------------------------
-
- /**
- * Returns a string representation of this label.
- *
- * @return a string representation of this label.
- */
- @Override
- public String toString() {
- return "L" + System.identityHashCode(this);
- }
-}
diff --git a/src/jvm/clojure/asm/MethodVisitor.java b/src/jvm/clojure/asm/MethodVisitor.java
deleted file mode 100644
index 347455e..0000000
--- a/src/jvm/clojure/asm/MethodVisitor.java
+++ /dev/null
@@ -1,662 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-/**
- * A visitor to visit a Java method. The methods of this class must be called in
- * the following order: [ <tt>visitAnnotationDefault</tt> ] (
- * <tt>visitAnnotation</tt> | <tt>visitParameterAnnotation</tt> |
- * <tt>visitAttribute</tt> )* [ <tt>visitCode</tt> ( <tt>visitFrame</tt> |
- * <tt>visit</tt><i>X</i>Insn</tt> | <tt>visitLabel</tt> |
- * <tt>visitTryCatchBlock</tt> | <tt>visitLocalVariable</tt> |
- * <tt>visitLineNumber</tt> )* <tt>visitMaxs</tt> ] <tt>visitEnd</tt>. In
- * addition, the <tt>visit</tt><i>X</i>Insn</tt> and <tt>visitLabel</tt> methods
- * must be called in the sequential order of the bytecode instructions of the
- * visited code, <tt>visitTryCatchBlock</tt> must be called <i>before</i> the
- * labels passed as arguments have been visited, and the
- * <tt>visitLocalVariable</tt> and <tt>visitLineNumber</tt> methods must be
- * called <i>after</i> the labels passed as arguments have been visited.
- *
- * @author Eric Bruneton
- */
-public abstract class MethodVisitor {
-
- /**
- * The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4}.
- */
- protected final int api;
-
- /**
- * The method visitor to which this visitor must delegate method calls. May
- * be null.
- */
- protected MethodVisitor mv;
-
- /**
- * Constructs a new {@link MethodVisitor}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- */
- public MethodVisitor(final int api) {
- this(api, null);
- }
-
- /**
- * Constructs a new {@link MethodVisitor}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param mv
- * the method visitor to which this visitor must delegate method
- * calls. May be null.
- */
- public MethodVisitor(final int api, final MethodVisitor mv) {
- if (api != Opcodes.ASM4) {
- throw new IllegalArgumentException();
- }
- this.api = api;
- this.mv = mv;
- }
-
- // -------------------------------------------------------------------------
- // Annotations and non standard attributes
- // -------------------------------------------------------------------------
-
- /**
- * Visits the default value of this annotation interface method.
- *
- * @return a visitor to the visit the actual default value of this
- * annotation interface method, or <tt>null</tt> if this visitor is
- * not interested in visiting this default value. The 'name'
- * parameters passed to the methods of this annotation visitor are
- * ignored. Moreover, exacly one visit method must be called on this
- * annotation visitor, followed by visitEnd.
- */
- public AnnotationVisitor visitAnnotationDefault() {
- if (mv != null) {
- return mv.visitAnnotationDefault();
- }
- return null;
- }
-
- /**
- * Visits an annotation of this method.
- *
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return a visitor to visit the annotation values, or <tt>null</tt> if
- * this visitor is not interested in visiting this annotation.
- */
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- if (mv != null) {
- return mv.visitAnnotation(desc, visible);
- }
- return null;
- }
-
- /**
- * Visits an annotation of a parameter this method.
- *
- * @param parameter
- * the parameter index.
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return a visitor to visit the annotation values, or <tt>null</tt> if
- * this visitor is not interested in visiting this annotation.
- */
- public AnnotationVisitor visitParameterAnnotation(int parameter,
- String desc, boolean visible) {
- if (mv != null) {
- return mv.visitParameterAnnotation(parameter, desc, visible);
- }
- return null;
- }
-
- /**
- * Visits a non standard attribute of this method.
- *
- * @param attr
- * an attribute.
- */
- public void visitAttribute(Attribute attr) {
- if (mv != null) {
- mv.visitAttribute(attr);
- }
- }
-
- /**
- * Starts the visit of the method's code, if any (i.e. non abstract method).
- */
- public void visitCode() {
- if (mv != null) {
- mv.visitCode();
- }
- }
-
- /**
- * Visits the current state of the local variables and operand stack
- * elements. This method must(*) be called <i>just before</i> any
- * instruction <b>i</b> that follows an unconditional branch instruction
- * such as GOTO or THROW, that is the target of a jump instruction, or that
- * starts an exception handler block. The visited types must describe the
- * values of the local variables and of the operand stack elements <i>just
- * before</i> <b>i</b> is executed.<br>
- * <br>
- * (*) this is mandatory only for classes whose version is greater than or
- * equal to {@link Opcodes#V1_6 V1_6}. <br>
- * <br>
- * The frames of a method must be given either in expanded form, or in
- * compressed form (all frames must use the same format, i.e. you must not
- * mix expanded and compressed frames within a single method):
- * <ul>
- * <li>In expanded form, all frames must have the F_NEW type.</li>
- * <li>In compressed form, frames are basically "deltas" from the state of
- * the previous frame:
- * <ul>
- * <li>{@link Opcodes#F_SAME} representing frame with exactly the same
- * locals as the previous frame and with the empty stack.</li>
- * <li>{@link Opcodes#F_SAME1} representing frame with exactly the same
- * locals as the previous frame and with single value on the stack (
- * <code>nStack</code> is 1 and <code>stack[0]</code> contains value for the
- * type of the stack item).</li>
- * <li>{@link Opcodes#F_APPEND} representing frame with current locals are
- * the same as the locals in the previous frame, except that additional
- * locals are defined (<code>nLocal</code> is 1, 2 or 3 and
- * <code>local</code> elements contains values representing added types).</li>
- * <li>{@link Opcodes#F_CHOP} representing frame with current locals are the
- * same as the locals in the previous frame, except that the last 1-3 locals
- * are absent and with the empty stack (<code>nLocals</code> is 1, 2 or 3).</li>
- * <li>{@link Opcodes#F_FULL} representing complete frame data.</li></li>
- * </ul>
- * </ul> <br>
- * In both cases the first frame, corresponding to the method's parameters
- * and access flags, is implicit and must not be visited. Also, it is
- * illegal to visit two or more frames for the same code location (i.e., at
- * least one instruction must be visited between two calls to visitFrame).
- *
- * @param type
- * the type of this stack map frame. Must be
- * {@link Opcodes#F_NEW} for expanded frames, or
- * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
- * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
- * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for
- * compressed frames.
- * @param nLocal
- * the number of local variables in the visited frame.
- * @param local
- * the local variable types in this frame. This array must not be
- * modified. Primitive types are represented by
- * {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
- * {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
- * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
- * {@link Opcodes#UNINITIALIZED_THIS} (long and double are
- * represented by a single element). Reference types are
- * represented by String objects (representing internal names),
- * and uninitialized types by Label objects (this label
- * designates the NEW instruction that created this uninitialized
- * value).
- * @param nStack
- * the number of operand stack elements in the visited frame.
- * @param stack
- * the operand stack types in this frame. This array must not be
- * modified. Its content has the same format as the "local"
- * array.
- * @throws IllegalStateException
- * if a frame is visited just after another one, without any
- * instruction between the two (unless this frame is a
- * Opcodes#F_SAME frame, in which case it is silently ignored).
- */
- public void visitFrame(int type, int nLocal, Object[] local, int nStack,
- Object[] stack) {
- if (mv != null) {
- mv.visitFrame(type, nLocal, local, nStack, stack);
- }
- }
-
- // -------------------------------------------------------------------------
- // Normal instructions
- // -------------------------------------------------------------------------
-
- /**
- * Visits a zero operand instruction.
- *
- * @param opcode
- * the opcode of the instruction to be visited. This opcode is
- * either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1,
- * ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1,
- * FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD,
- * LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD,
- * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE,
- * SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1,
- * DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB,
- * IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM,
- * FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR,
- * IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D,
- * L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S,
- * LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN,
- * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER,
- * or MONITOREXIT.
- */
- public void visitInsn(int opcode) {
- if (mv != null) {
- mv.visitInsn(opcode);
- }
- }
-
- /**
- * Visits an instruction with a single int operand.
- *
- * @param opcode
- * the opcode of the instruction to be visited. This opcode is
- * either BIPUSH, SIPUSH or NEWARRAY.
- * @param operand
- * the operand of the instruction to be visited.<br>
- * When opcode is BIPUSH, operand value should be between
- * Byte.MIN_VALUE and Byte.MAX_VALUE.<br>
- * When opcode is SIPUSH, operand value should be between
- * Short.MIN_VALUE and Short.MAX_VALUE.<br>
- * When opcode is NEWARRAY, operand value should be one of
- * {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR},
- * {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE},
- * {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT},
- * {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.
- */
- public void visitIntInsn(int opcode, int operand) {
- if (mv != null) {
- mv.visitIntInsn(opcode, operand);
- }
- }
-
- /**
- * Visits a local variable instruction. A local variable instruction is an
- * instruction that loads or stores the value of a local variable.
- *
- * @param opcode
- * the opcode of the local variable instruction to be visited.
- * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD,
- * ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
- * @param var
- * the operand of the instruction to be visited. This operand is
- * the index of a local variable.
- */
- public void visitVarInsn(int opcode, int var) {
- if (mv != null) {
- mv.visitVarInsn(opcode, var);
- }
- }
-
- /**
- * Visits a type instruction. A type instruction is an instruction that
- * takes the internal name of a class as parameter.
- *
- * @param opcode
- * the opcode of the type instruction to be visited. This opcode
- * is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
- * @param type
- * the operand of the instruction to be visited. This operand
- * must be the internal name of an object or array class (see
- * {@link Type#getInternalName() getInternalName}).
- */
- public void visitTypeInsn(int opcode, String type) {
- if (mv != null) {
- mv.visitTypeInsn(opcode, type);
- }
- }
-
- /**
- * Visits a field instruction. A field instruction is an instruction that
- * loads or stores the value of a field of an object.
- *
- * @param opcode
- * the opcode of the type instruction to be visited. This opcode
- * is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
- * @param owner
- * the internal name of the field's owner class (see
- * {@link Type#getInternalName() getInternalName}).
- * @param name
- * the field's name.
- * @param desc
- * the field's descriptor (see {@link Type Type}).
- */
- public void visitFieldInsn(int opcode, String owner, String name,
- String desc) {
- if (mv != null) {
- mv.visitFieldInsn(opcode, owner, name, desc);
- }
- }
-
- /**
- * Visits a method instruction. A method instruction is an instruction that
- * invokes a method.
- *
- * @param opcode
- * the opcode of the type instruction to be visited. This opcode
- * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
- * INVOKEINTERFACE.
- * @param owner
- * the internal name of the method's owner class (see
- * {@link Type#getInternalName() getInternalName}).
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- */
- public void visitMethodInsn(int opcode, String owner, String name,
- String desc) {
- if (mv != null) {
- mv.visitMethodInsn(opcode, owner, name, desc);
- }
- }
-
- /**
- * Visits an invokedynamic instruction.
- *
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- * @param bsm
- * the bootstrap method.
- * @param bsmArgs
- * the bootstrap method constant arguments. Each argument must be
- * an {@link Integer}, {@link Float}, {@link Long},
- * {@link Double}, {@link String}, {@link Type} or {@link Handle}
- * value. This method is allowed to modify the content of the
- * array so a caller should expect that this array may change.
- */
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- if (mv != null) {
- mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
- }
- }
-
- /**
- * Visits a jump instruction. A jump instruction is an instruction that may
- * jump to another instruction.
- *
- * @param opcode
- * the opcode of the type instruction to be visited. This opcode
- * is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
- * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
- * IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
- * @param label
- * the operand of the instruction to be visited. This operand is
- * a label that designates the instruction to which the jump
- * instruction may jump.
- */
- public void visitJumpInsn(int opcode, Label label) {
- if (mv != null) {
- mv.visitJumpInsn(opcode, label);
- }
- }
-
- /**
- * Visits a label. A label designates the instruction that will be visited
- * just after it.
- *
- * @param label
- * a {@link Label Label} object.
- */
- public void visitLabel(Label label) {
- if (mv != null) {
- mv.visitLabel(label);
- }
- }
-
- // -------------------------------------------------------------------------
- // Special instructions
- // -------------------------------------------------------------------------
-
- /**
- * Visits a LDC instruction. Note that new constant types may be added in
- * future versions of the Java Virtual Machine. To easily detect new
- * constant types, implementations of this method should check for
- * unexpected constant types, like this:
- *
- * <pre>
- * if (cst instanceof Integer) {
- * // ...
- * } else if (cst instanceof Float) {
- * // ...
- * } else if (cst instanceof Long) {
- * // ...
- * } else if (cst instanceof Double) {
- * // ...
- * } else if (cst instanceof String) {
- * // ...
- * } else if (cst instanceof Type) {
- * int sort = ((Type) cst).getSort();
- * if (sort == Type.OBJECT) {
- * // ...
- * } else if (sort == Type.ARRAY) {
- * // ...
- * } else if (sort == Type.METHOD) {
- * // ...
- * } else {
- * // throw an exception
- * }
- * } else if (cst instanceof Handle) {
- * // ...
- * } else {
- * // throw an exception
- * }
- * </pre>
- *
- * @param cst
- * the constant to be loaded on the stack. This parameter must be
- * a non null {@link Integer}, a {@link Float}, a {@link Long}, a
- * {@link Double}, a {@link String}, a {@link Type} of OBJECT or
- * ARRAY sort for <tt>.class</tt> constants, for classes whose
- * version is 49.0, a {@link Type} of METHOD sort or a
- * {@link Handle} for MethodType and MethodHandle constants, for
- * classes whose version is 51.0.
- */
- public void visitLdcInsn(Object cst) {
- if (mv != null) {
- mv.visitLdcInsn(cst);
- }
- }
-
- /**
- * Visits an IINC instruction.
- *
- * @param var
- * index of the local variable to be incremented.
- * @param increment
- * amount to increment the local variable by.
- */
- public void visitIincInsn(int var, int increment) {
- if (mv != null) {
- mv.visitIincInsn(var, increment);
- }
- }
-
- /**
- * Visits a TABLESWITCH instruction.
- *
- * @param min
- * the minimum key value.
- * @param max
- * the maximum key value.
- * @param dflt
- * beginning of the default handler block.
- * @param labels
- * beginnings of the handler blocks. <tt>labels[i]</tt> is the
- * beginning of the handler block for the <tt>min + i</tt> key.
- */
- public void visitTableSwitchInsn(int min, int max, Label dflt,
- Label... labels) {
- if (mv != null) {
- mv.visitTableSwitchInsn(min, max, dflt, labels);
- }
- }
-
- /**
- * Visits a LOOKUPSWITCH instruction.
- *
- * @param dflt
- * beginning of the default handler block.
- * @param keys
- * the values of the keys.
- * @param labels
- * beginnings of the handler blocks. <tt>labels[i]</tt> is the
- * beginning of the handler block for the <tt>keys[i]</tt> key.
- */
- public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
- if (mv != null) {
- mv.visitLookupSwitchInsn(dflt, keys, labels);
- }
- }
-
- /**
- * Visits a MULTIANEWARRAY instruction.
- *
- * @param desc
- * an array type descriptor (see {@link Type Type}).
- * @param dims
- * number of dimensions of the array to allocate.
- */
- public void visitMultiANewArrayInsn(String desc, int dims) {
- if (mv != null) {
- mv.visitMultiANewArrayInsn(desc, dims);
- }
- }
-
- // -------------------------------------------------------------------------
- // Exceptions table entries, debug information, max stack and max locals
- // -------------------------------------------------------------------------
-
- /**
- * Visits a try catch block.
- *
- * @param start
- * beginning of the exception handler's scope (inclusive).
- * @param end
- * end of the exception handler's scope (exclusive).
- * @param handler
- * beginning of the exception handler's code.
- * @param type
- * internal name of the type of exceptions handled by the
- * handler, or <tt>null</tt> to catch any exceptions (for
- * "finally" blocks).
- * @throws IllegalArgumentException
- * if one of the labels has already been visited by this visitor
- * (by the {@link #visitLabel visitLabel} method).
- */
- public void visitTryCatchBlock(Label start, Label end, Label handler,
- String type) {
- if (mv != null) {
- mv.visitTryCatchBlock(start, end, handler, type);
- }
- }
-
- /**
- * Visits a local variable declaration.
- *
- * @param name
- * the name of a local variable.
- * @param desc
- * the type descriptor of this local variable.
- * @param signature
- * the type signature of this local variable. May be
- * <tt>null</tt> if the local variable type does not use generic
- * types.
- * @param start
- * the first instruction corresponding to the scope of this local
- * variable (inclusive).
- * @param end
- * the last instruction corresponding to the scope of this local
- * variable (exclusive).
- * @param index
- * the local variable's index.
- * @throws IllegalArgumentException
- * if one of the labels has not already been visited by this
- * visitor (by the {@link #visitLabel visitLabel} method).
- */
- public void visitLocalVariable(String name, String desc, String signature,
- Label start, Label end, int index) {
- if (mv != null) {
- mv.visitLocalVariable(name, desc, signature, start, end, index);
- }
- }
-
- /**
- * Visits a line number declaration.
- *
- * @param line
- * a line number. This number refers to the source file from
- * which the class was compiled.
- * @param start
- * the first instruction corresponding to this line number.
- * @throws IllegalArgumentException
- * if <tt>start</tt> has not already been visited by this
- * visitor (by the {@link #visitLabel visitLabel} method).
- */
- public void visitLineNumber(int line, Label start) {
- if (mv != null) {
- mv.visitLineNumber(line, start);
- }
- }
-
- /**
- * Visits the maximum stack size and the maximum number of local variables
- * of the method.
- *
- * @param maxStack
- * maximum stack size of the method.
- * @param maxLocals
- * maximum number of local variables for the method.
- */
- public void visitMaxs(int maxStack, int maxLocals) {
- if (mv != null) {
- mv.visitMaxs(maxStack, maxLocals);
- }
- }
-
- /**
- * Visits the end of the method. This method, which is the last one to be
- * called, is used to inform the visitor that all the annotations and
- * attributes of the method have been visited.
- */
- public void visitEnd() {
- if (mv != null) {
- mv.visitEnd();
- }
- }
-}
diff --git a/src/jvm/clojure/asm/MethodWriter.java b/src/jvm/clojure/asm/MethodWriter.java
deleted file mode 100644
index 9197318..0000000
--- a/src/jvm/clojure/asm/MethodWriter.java
+++ /dev/null
@@ -1,2685 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-/**
- * A {@link MethodVisitor} that generates methods in bytecode form. Each visit
- * method of this class appends the bytecode corresponding to the visited
- * instruction to a byte vector, in the order these methods are called.
- *
- * @author Eric Bruneton
- * @author Eugene Kuleshov
- */
-class MethodWriter extends MethodVisitor {
-
- /**
- * Pseudo access flag used to denote constructors.
- */
- static final int ACC_CONSTRUCTOR = 0x80000;
-
- /**
- * Frame has exactly the same locals as the previous stack map frame and
- * number of stack items is zero.
- */
- static final int SAME_FRAME = 0; // to 63 (0-3f)
-
- /**
- * Frame has exactly the same locals as the previous stack map frame and
- * number of stack items is 1
- */
- static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; // to 127 (40-7f)
-
- /**
- * Reserved for future use
- */
- static final int RESERVED = 128;
-
- /**
- * Frame has exactly the same locals as the previous stack map frame and
- * number of stack items is 1. Offset is bigger then 63;
- */
- static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247; // f7
-
- /**
- * Frame where current locals are the same as the locals in the previous
- * frame, except that the k last locals are absent. The value of k is given
- * by the formula 251-frame_type.
- */
- static final int CHOP_FRAME = 248; // to 250 (f8-fA)
-
- /**
- * Frame has exactly the same locals as the previous stack map frame and
- * number of stack items is zero. Offset is bigger then 63;
- */
- static final int SAME_FRAME_EXTENDED = 251; // fb
-
- /**
- * Frame where current locals are the same as the locals in the previous
- * frame, except that k additional locals are defined. The value of k is
- * given by the formula frame_type-251.
- */
- static final int APPEND_FRAME = 252; // to 254 // fc-fe
-
- /**
- * Full frame
- */
- static final int FULL_FRAME = 255; // ff
-
- /**
- * Indicates that the stack map frames must be recomputed from scratch. In
- * this case the maximum stack size and number of local variables is also
- * recomputed from scratch.
- *
- * @see #compute
- */
- private static final int FRAMES = 0;
-
- /**
- * Indicates that the maximum stack size and number of local variables must
- * be automatically computed.
- *
- * @see #compute
- */
- private static final int MAXS = 1;
-
- /**
- * Indicates that nothing must be automatically computed.
- *
- * @see #compute
- */
- private static final int NOTHING = 2;
-
- /**
- * The class writer to which this method must be added.
- */
- final ClassWriter cw;
-
- /**
- * Access flags of this method.
- */
- private int access;
-
- /**
- * The index of the constant pool item that contains the name of this
- * method.
- */
- private final int name;
-
- /**
- * The index of the constant pool item that contains the descriptor of this
- * method.
- */
- private final int desc;
-
- /**
- * The descriptor of this method.
- */
- private final String descriptor;
-
- /**
- * The signature of this method.
- */
- String signature;
-
- /**
- * If not zero, indicates that the code of this method must be copied from
- * the ClassReader associated to this writer in <code>cw.cr</code>. More
- * precisely, this field gives the index of the first byte to copied from
- * <code>cw.cr.b</code>.
- */
- int classReaderOffset;
-
- /**
- * If not zero, indicates that the code of this method must be copied from
- * the ClassReader associated to this writer in <code>cw.cr</code>. More
- * precisely, this field gives the number of bytes to copied from
- * <code>cw.cr.b</code>.
- */
- int classReaderLength;
-
- /**
- * Number of exceptions that can be thrown by this method.
- */
- int exceptionCount;
-
- /**
- * The exceptions that can be thrown by this method. More precisely, this
- * array contains the indexes of the constant pool items that contain the
- * internal names of these exception classes.
- */
- int[] exceptions;
-
- /**
- * The annotation default attribute of this method. May be <tt>null</tt>.
- */
- private ByteVector annd;
-
- /**
- * The runtime visible annotations of this method. May be <tt>null</tt>.
- */
- private AnnotationWriter anns;
-
- /**
- * The runtime invisible annotations of this method. May be <tt>null</tt>.
- */
- private AnnotationWriter ianns;
-
- /**
- * The runtime visible parameter annotations of this method. May be
- * <tt>null</tt>.
- */
- private AnnotationWriter[] panns;
-
- /**
- * The runtime invisible parameter annotations of this method. May be
- * <tt>null</tt>.
- */
- private AnnotationWriter[] ipanns;
-
- /**
- * The number of synthetic parameters of this method.
- */
- private int synthetics;
-
- /**
- * The non standard attributes of the method.
- */
- private Attribute attrs;
-
- /**
- * The bytecode of this method.
- */
- private ByteVector code = new ByteVector();
-
- /**
- * Maximum stack size of this method.
- */
- private int maxStack;
-
- /**
- * Maximum number of local variables for this method.
- */
- private int maxLocals;
-
- /**
- * Number of local variables in the current stack map frame.
- */
- private int currentLocals;
-
- /**
- * Number of stack map frames in the StackMapTable attribute.
- */
- private int frameCount;
-
- /**
- * The StackMapTable attribute.
- */
- private ByteVector stackMap;
-
- /**
- * The offset of the last frame that was written in the StackMapTable
- * attribute.
- */
- private int previousFrameOffset;
-
- /**
- * The last frame that was written in the StackMapTable attribute.
- *
- * @see #frame
- */
- private int[] previousFrame;
-
- /**
- * The current stack map frame. The first element contains the offset of the
- * instruction to which the frame corresponds, the second element is the
- * number of locals and the third one is the number of stack elements. The
- * local variables start at index 3 and are followed by the operand stack
- * values. In summary frame[0] = offset, frame[1] = nLocal, frame[2] =
- * nStack, frame[3] = nLocal. All types are encoded as integers, with the
- * same format as the one used in {@link Label}, but limited to BASE types.
- */
- private int[] frame;
-
- /**
- * Number of elements in the exception handler list.
- */
- private int handlerCount;
-
- /**
- * The first element in the exception handler list.
- */
- private Handler firstHandler;
-
- /**
- * The last element in the exception handler list.
- */
- private Handler lastHandler;
-
- /**
- * Number of entries in the LocalVariableTable attribute.
- */
- private int localVarCount;
-
- /**
- * The LocalVariableTable attribute.
- */
- private ByteVector localVar;
-
- /**
- * Number of entries in the LocalVariableTypeTable attribute.
- */
- private int localVarTypeCount;
-
- /**
- * The LocalVariableTypeTable attribute.
- */
- private ByteVector localVarType;
-
- /**
- * Number of entries in the LineNumberTable attribute.
- */
- private int lineNumberCount;
-
- /**
- * The LineNumberTable attribute.
- */
- private ByteVector lineNumber;
-
- /**
- * The non standard attributes of the method's code.
- */
- private Attribute cattrs;
-
- /**
- * Indicates if some jump instructions are too small and need to be resized.
- */
- private boolean resize;
-
- /**
- * The number of subroutines in this method.
- */
- private int subroutines;
-
- // ------------------------------------------------------------------------
-
- /*
- * Fields for the control flow graph analysis algorithm (used to compute the
- * maximum stack size). A control flow graph contains one node per "basic
- * block", and one edge per "jump" from one basic block to another. Each
- * node (i.e., each basic block) is represented by the Label object that
- * corresponds to the first instruction of this basic block. Each node also
- * stores the list of its successors in the graph, as a linked list of Edge
- * objects.
- */
-
- /**
- * Indicates what must be automatically computed.
- *
- * @see #FRAMES
- * @see #MAXS
- * @see #NOTHING
- */
- private final int compute;
-
- /**
- * A list of labels. This list is the list of basic blocks in the method,
- * i.e. a list of Label objects linked to each other by their
- * {@link Label#successor} field, in the order they are visited by
- * {@link MethodVisitor#visitLabel}, and starting with the first basic
- * block.
- */
- private Label labels;
-
- /**
- * The previous basic block.
- */
- private Label previousBlock;
-
- /**
- * The current basic block.
- */
- private Label currentBlock;
-
- /**
- * The (relative) stack size after the last visited instruction. This size
- * is relative to the beginning of the current basic block, i.e., the true
- * stack size after the last visited instruction is equal to the
- * {@link Label#inputStackTop beginStackSize} of the current basic block
- * plus <tt>stackSize</tt>.
- */
- private int stackSize;
-
- /**
- * The (relative) maximum stack size after the last visited instruction.
- * This size is relative to the beginning of the current basic block, i.e.,
- * the true maximum stack size after the last visited instruction is equal
- * to the {@link Label#inputStackTop beginStackSize} of the current basic
- * block plus <tt>stackSize</tt>.
- */
- private int maxStackSize;
-
- // ------------------------------------------------------------------------
- // Constructor
- // ------------------------------------------------------------------------
-
- /**
- * Constructs a new {@link MethodWriter}.
- *
- * @param cw
- * the class writer in which the method must be added.
- * @param access
- * the method's access flags (see {@link Opcodes}).
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type}).
- * @param signature
- * the method's signature. May be <tt>null</tt>.
- * @param exceptions
- * the internal names of the method's exceptions. May be
- * <tt>null</tt>.
- * @param computeMaxs
- * <tt>true</tt> if the maximum stack size and number of local
- * variables must be automatically computed.
- * @param computeFrames
- * <tt>true</tt> if the stack map tables must be recomputed from
- * scratch.
- */
- MethodWriter(final ClassWriter cw, final int access, final String name,
- final String desc, final String signature,
- final String[] exceptions, final boolean computeMaxs,
- final boolean computeFrames) {
- super(Opcodes.ASM4);
- if (cw.firstMethod == null) {
- cw.firstMethod = this;
- } else {
- cw.lastMethod.mv = this;
- }
- cw.lastMethod = this;
- this.cw = cw;
- this.access = access;
- if ("<init>".equals(name)) {
- this.access |= ACC_CONSTRUCTOR;
- }
- this.name = cw.newUTF8(name);
- this.desc = cw.newUTF8(desc);
- this.descriptor = desc;
- if (ClassReader.SIGNATURES) {
- this.signature = signature;
- }
- if (exceptions != null && exceptions.length > 0) {
- exceptionCount = exceptions.length;
- this.exceptions = new int[exceptionCount];
- for (int i = 0; i < exceptionCount; ++i) {
- this.exceptions[i] = cw.newClass(exceptions[i]);
- }
- }
- this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING);
- if (computeMaxs || computeFrames) {
- // updates maxLocals
- int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2;
- if ((access & Opcodes.ACC_STATIC) != 0) {
- --size;
- }
- maxLocals = size;
- currentLocals = size;
- // creates and visits the label for the first basic block
- labels = new Label();
- labels.status |= Label.PUSHED;
- visitLabel(labels);
- }
- }
-
- // ------------------------------------------------------------------------
- // Implementation of the MethodVisitor abstract class
- // ------------------------------------------------------------------------
-
- @Override
- public AnnotationVisitor visitAnnotationDefault() {
- if (!ClassReader.ANNOTATIONS) {
- return null;
- }
- annd = new ByteVector();
- return new AnnotationWriter(cw, false, annd, null, 0);
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(final String desc,
- final boolean visible) {
- if (!ClassReader.ANNOTATIONS) {
- return null;
- }
- ByteVector bv = new ByteVector();
- // write type, and reserve space for values count
- bv.putShort(cw.newUTF8(desc)).putShort(0);
- AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
- if (visible) {
- aw.next = anns;
- anns = aw;
- } else {
- aw.next = ianns;
- ianns = aw;
- }
- return aw;
- }
-
- @Override
- public AnnotationVisitor visitParameterAnnotation(final int parameter,
- final String desc, final boolean visible) {
- if (!ClassReader.ANNOTATIONS) {
- return null;
- }
- ByteVector bv = new ByteVector();
- if ("Ljava/lang/Synthetic;".equals(desc)) {
- // workaround for a bug in javac with synthetic parameters
- // see ClassReader.readParameterAnnotations
- synthetics = Math.max(synthetics, parameter + 1);
- return new AnnotationWriter(cw, false, bv, null, 0);
- }
- // write type, and reserve space for values count
- bv.putShort(cw.newUTF8(desc)).putShort(0);
- AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
- if (visible) {
- if (panns == null) {
- panns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length];
- }
- aw.next = panns[parameter];
- panns[parameter] = aw;
- } else {
- if (ipanns == null) {
- ipanns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length];
- }
- aw.next = ipanns[parameter];
- ipanns[parameter] = aw;
- }
- return aw;
- }
-
- @Override
- public void visitAttribute(final Attribute attr) {
- if (attr.isCodeAttribute()) {
- attr.next = cattrs;
- cattrs = attr;
- } else {
- attr.next = attrs;
- attrs = attr;
- }
- }
-
- @Override
- public void visitCode() {
- }
-
- @Override
- public void visitFrame(final int type, final int nLocal,
- final Object[] local, final int nStack, final Object[] stack) {
- if (!ClassReader.FRAMES || compute == FRAMES) {
- return;
- }
-
- if (type == Opcodes.F_NEW) {
- if (previousFrame == null) {
- visitImplicitFirstFrame();
- }
- currentLocals = nLocal;
- int frameIndex = startFrame(code.length, nLocal, nStack);
- for (int i = 0; i < nLocal; ++i) {
- if (local[i] instanceof String) {
- frame[frameIndex++] = Frame.OBJECT
- | cw.addType((String) local[i]);
- } else if (local[i] instanceof Integer) {
- frame[frameIndex++] = ((Integer) local[i]).intValue();
- } else {
- frame[frameIndex++] = Frame.UNINITIALIZED
- | cw.addUninitializedType("",
- ((Label) local[i]).position);
- }
- }
- for (int i = 0; i < nStack; ++i) {
- if (stack[i] instanceof String) {
- frame[frameIndex++] = Frame.OBJECT
- | cw.addType((String) stack[i]);
- } else if (stack[i] instanceof Integer) {
- frame[frameIndex++] = ((Integer) stack[i]).intValue();
- } else {
- frame[frameIndex++] = Frame.UNINITIALIZED
- | cw.addUninitializedType("",
- ((Label) stack[i]).position);
- }
- }
- endFrame();
- } else {
- int delta;
- if (stackMap == null) {
- stackMap = new ByteVector();
- delta = code.length;
- } else {
- delta = code.length - previousFrameOffset - 1;
- if (delta < 0) {
- if (type == Opcodes.F_SAME) {
- return;
- } else {
- throw new IllegalStateException();
- }
- }
- }
-
- switch (type) {
- case Opcodes.F_FULL:
- currentLocals = nLocal;
- stackMap.putByte(FULL_FRAME).putShort(delta).putShort(nLocal);
- for (int i = 0; i < nLocal; ++i) {
- writeFrameType(local[i]);
- }
- stackMap.putShort(nStack);
- for (int i = 0; i < nStack; ++i) {
- writeFrameType(stack[i]);
- }
- break;
- case Opcodes.F_APPEND:
- currentLocals += nLocal;
- stackMap.putByte(SAME_FRAME_EXTENDED + nLocal).putShort(delta);
- for (int i = 0; i < nLocal; ++i) {
- writeFrameType(local[i]);
- }
- break;
- case Opcodes.F_CHOP:
- currentLocals -= nLocal;
- stackMap.putByte(SAME_FRAME_EXTENDED - nLocal).putShort(delta);
- break;
- case Opcodes.F_SAME:
- if (delta < 64) {
- stackMap.putByte(delta);
- } else {
- stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
- }
- break;
- case Opcodes.F_SAME1:
- if (delta < 64) {
- stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
- } else {
- stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
- .putShort(delta);
- }
- writeFrameType(stack[0]);
- break;
- }
-
- previousFrameOffset = code.length;
- ++frameCount;
- }
-
- maxStack = Math.max(maxStack, nStack);
- maxLocals = Math.max(maxLocals, currentLocals);
- }
-
- @Override
- public void visitInsn(final int opcode) {
- // adds the instruction to the bytecode of the method
- code.putByte(opcode);
- // update currentBlock
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES) {
- currentBlock.frame.execute(opcode, 0, null, null);
- } else {
- // updates current and max stack sizes
- int size = stackSize + Frame.SIZE[opcode];
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- // if opcode == ATHROW or xRETURN, ends current block (no successor)
- if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
- || opcode == Opcodes.ATHROW) {
- noSuccessor();
- }
- }
- }
-
- @Override
- public void visitIntInsn(final int opcode, final int operand) {
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES) {
- currentBlock.frame.execute(opcode, operand, null, null);
- } else if (opcode != Opcodes.NEWARRAY) {
- // updates current and max stack sizes only for NEWARRAY
- // (stack size variation = 0 for BIPUSH or SIPUSH)
- int size = stackSize + 1;
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- }
- // adds the instruction to the bytecode of the method
- if (opcode == Opcodes.SIPUSH) {
- code.put12(opcode, operand);
- } else { // BIPUSH or NEWARRAY
- code.put11(opcode, operand);
- }
- }
-
- @Override
- public void visitVarInsn(final int opcode, final int var) {
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES) {
- currentBlock.frame.execute(opcode, var, null, null);
- } else {
- // updates current and max stack sizes
- if (opcode == Opcodes.RET) {
- // no stack change, but end of current block (no successor)
- currentBlock.status |= Label.RET;
- // save 'stackSize' here for future use
- // (see {@link #findSubroutineSuccessors})
- currentBlock.inputStackTop = stackSize;
- noSuccessor();
- } else { // xLOAD or xSTORE
- int size = stackSize + Frame.SIZE[opcode];
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- }
- }
- if (compute != NOTHING) {
- // updates max locals
- int n;
- if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD
- || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) {
- n = var + 2;
- } else {
- n = var + 1;
- }
- if (n > maxLocals) {
- maxLocals = n;
- }
- }
- // adds the instruction to the bytecode of the method
- if (var < 4 && opcode != Opcodes.RET) {
- int opt;
- if (opcode < Opcodes.ISTORE) {
- /* ILOAD_0 */
- opt = 26 + ((opcode - Opcodes.ILOAD) << 2) + var;
- } else {
- /* ISTORE_0 */
- opt = 59 + ((opcode - Opcodes.ISTORE) << 2) + var;
- }
- code.putByte(opt);
- } else if (var >= 256) {
- code.putByte(196 /* WIDE */).put12(opcode, var);
- } else {
- code.put11(opcode, var);
- }
- if (opcode >= Opcodes.ISTORE && compute == FRAMES && handlerCount > 0) {
- visitLabel(new Label());
- }
- }
-
- @Override
- public void visitTypeInsn(final int opcode, final String type) {
- Item i = cw.newClassItem(type);
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES) {
- currentBlock.frame.execute(opcode, code.length, cw, i);
- } else if (opcode == Opcodes.NEW) {
- // updates current and max stack sizes only if opcode == NEW
- // (no stack change for ANEWARRAY, CHECKCAST, INSTANCEOF)
- int size = stackSize + 1;
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- }
- // adds the instruction to the bytecode of the method
- code.put12(opcode, i.index);
- }
-
- @Override
- public void visitFieldInsn(final int opcode, final String owner,
- final String name, final String desc) {
- Item i = cw.newFieldItem(owner, name, desc);
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES) {
- currentBlock.frame.execute(opcode, 0, cw, i);
- } else {
- int size;
- // computes the stack size variation
- char c = desc.charAt(0);
- switch (opcode) {
- case Opcodes.GETSTATIC:
- size = stackSize + (c == 'D' || c == 'J' ? 2 : 1);
- break;
- case Opcodes.PUTSTATIC:
- size = stackSize + (c == 'D' || c == 'J' ? -2 : -1);
- break;
- case Opcodes.GETFIELD:
- size = stackSize + (c == 'D' || c == 'J' ? 1 : 0);
- break;
- // case Constants.PUTFIELD:
- default:
- size = stackSize + (c == 'D' || c == 'J' ? -3 : -2);
- break;
- }
- // updates current and max stack sizes
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- }
- // adds the instruction to the bytecode of the method
- code.put12(opcode, i.index);
- }
-
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc) {
- boolean itf = opcode == Opcodes.INVOKEINTERFACE;
- Item i = cw.newMethodItem(owner, name, desc, itf);
- int argSize = i.intVal;
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES) {
- currentBlock.frame.execute(opcode, 0, cw, i);
- } else {
- /*
- * computes the stack size variation. In order not to recompute
- * several times this variation for the same Item, we use the
- * intVal field of this item to store this variation, once it
- * has been computed. More precisely this intVal field stores
- * the sizes of the arguments and of the return value
- * corresponding to desc.
- */
- if (argSize == 0) {
- // the above sizes have not been computed yet,
- // so we compute them...
- argSize = Type.getArgumentsAndReturnSizes(desc);
- // ... and we save them in order
- // not to recompute them in the future
- i.intVal = argSize;
- }
- int size;
- if (opcode == Opcodes.INVOKESTATIC) {
- size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1;
- } else {
- size = stackSize - (argSize >> 2) + (argSize & 0x03);
- }
- // updates current and max stack sizes
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- }
- // adds the instruction to the bytecode of the method
- if (itf) {
- if (argSize == 0) {
- argSize = Type.getArgumentsAndReturnSizes(desc);
- i.intVal = argSize;
- }
- code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0);
- } else {
- code.put12(opcode, i.index);
- }
- }
-
- @Override
- public void visitInvokeDynamicInsn(final String name, final String desc,
- final Handle bsm, final Object... bsmArgs) {
- Item i = cw.newInvokeDynamicItem(name, desc, bsm, bsmArgs);
- int argSize = i.intVal;
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES) {
- currentBlock.frame.execute(Opcodes.INVOKEDYNAMIC, 0, cw, i);
- } else {
- /*
- * computes the stack size variation. In order not to recompute
- * several times this variation for the same Item, we use the
- * intVal field of this item to store this variation, once it
- * has been computed. More precisely this intVal field stores
- * the sizes of the arguments and of the return value
- * corresponding to desc.
- */
- if (argSize == 0) {
- // the above sizes have not been computed yet,
- // so we compute them...
- argSize = Type.getArgumentsAndReturnSizes(desc);
- // ... and we save them in order
- // not to recompute them in the future
- i.intVal = argSize;
- }
- int size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1;
-
- // updates current and max stack sizes
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- }
- // adds the instruction to the bytecode of the method
- code.put12(Opcodes.INVOKEDYNAMIC, i.index);
- code.putShort(0);
- }
-
- @Override
- public void visitJumpInsn(final int opcode, final Label label) {
- Label nextInsn = null;
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES) {
- currentBlock.frame.execute(opcode, 0, null, null);
- // 'label' is the target of a jump instruction
- label.getFirst().status |= Label.TARGET;
- // adds 'label' as a successor of this basic block
- addSuccessor(Edge.NORMAL, label);
- if (opcode != Opcodes.GOTO) {
- // creates a Label for the next basic block
- nextInsn = new Label();
- }
- } else {
- if (opcode == Opcodes.JSR) {
- if ((label.status & Label.SUBROUTINE) == 0) {
- label.status |= Label.SUBROUTINE;
- ++subroutines;
- }
- currentBlock.status |= Label.JSR;
- addSuccessor(stackSize + 1, label);
- // creates a Label for the next basic block
- nextInsn = new Label();
- /*
- * note that, by construction in this method, a JSR block
- * has at least two successors in the control flow graph:
- * the first one leads the next instruction after the JSR,
- * while the second one leads to the JSR target.
- */
- } else {
- // updates current stack size (max stack size unchanged
- // because stack size variation always negative in this
- // case)
- stackSize += Frame.SIZE[opcode];
- addSuccessor(stackSize, label);
- }
- }
- }
- // adds the instruction to the bytecode of the method
- if ((label.status & Label.RESOLVED) != 0
- && label.position - code.length < Short.MIN_VALUE) {
- /*
- * case of a backward jump with an offset < -32768. In this case we
- * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx
- * <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the
- * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <l'>
- * designates the instruction just after the GOTO_W.
- */
- if (opcode == Opcodes.GOTO) {
- code.putByte(200); // GOTO_W
- } else if (opcode == Opcodes.JSR) {
- code.putByte(201); // JSR_W
- } else {
- // if the IF instruction is transformed into IFNOT GOTO_W the
- // next instruction becomes the target of the IFNOT instruction
- if (nextInsn != null) {
- nextInsn.status |= Label.TARGET;
- }
- code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
- : opcode ^ 1);
- code.putShort(8); // jump offset
- code.putByte(200); // GOTO_W
- }
- label.put(this, code, code.length - 1, true);
- } else {
- /*
- * case of a backward jump with an offset >= -32768, or of a forward
- * jump with, of course, an unknown offset. In these cases we store
- * the offset in 2 bytes (which will be increased in
- * resizeInstructions, if needed).
- */
- code.putByte(opcode);
- label.put(this, code, code.length - 1, false);
- }
- if (currentBlock != null) {
- if (nextInsn != null) {
- // if the jump instruction is not a GOTO, the next instruction
- // is also a successor of this instruction. Calling visitLabel
- // adds the label of this next instruction as a successor of the
- // current block, and starts a new basic block
- visitLabel(nextInsn);
- }
- if (opcode == Opcodes.GOTO) {
- noSuccessor();
- }
- }
- }
-
- @Override
- public void visitLabel(final Label label) {
- // resolves previous forward references to label, if any
- resize |= label.resolve(this, code.length, code.data);
- // updates currentBlock
- if ((label.status & Label.DEBUG) != 0) {
- return;
- }
- if (compute == FRAMES) {
- if (currentBlock != null) {
- if (label.position == currentBlock.position) {
- // successive labels, do not start a new basic block
- currentBlock.status |= (label.status & Label.TARGET);
- label.frame = currentBlock.frame;
- return;
- }
- // ends current block (with one new successor)
- addSuccessor(Edge.NORMAL, label);
- }
- // begins a new current block
- currentBlock = label;
- if (label.frame == null) {
- label.frame = new Frame();
- label.frame.owner = label;
- }
- // updates the basic block list
- if (previousBlock != null) {
- if (label.position == previousBlock.position) {
- previousBlock.status |= (label.status & Label.TARGET);
- label.frame = previousBlock.frame;
- currentBlock = previousBlock;
- return;
- }
- previousBlock.successor = label;
- }
- previousBlock = label;
- } else if (compute == MAXS) {
- if (currentBlock != null) {
- // ends current block (with one new successor)
- currentBlock.outputStackMax = maxStackSize;
- addSuccessor(stackSize, label);
- }
- // begins a new current block
- currentBlock = label;
- // resets the relative current and max stack sizes
- stackSize = 0;
- maxStackSize = 0;
- // updates the basic block list
- if (previousBlock != null) {
- previousBlock.successor = label;
- }
- previousBlock = label;
- }
- }
-
- @Override
- public void visitLdcInsn(final Object cst) {
- Item i = cw.newConstItem(cst);
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES) {
- currentBlock.frame.execute(Opcodes.LDC, 0, cw, i);
- } else {
- int size;
- // computes the stack size variation
- if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {
- size = stackSize + 2;
- } else {
- size = stackSize + 1;
- }
- // updates current and max stack sizes
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- }
- // adds the instruction to the bytecode of the method
- int index = i.index;
- if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {
- code.put12(20 /* LDC2_W */, index);
- } else if (index >= 256) {
- code.put12(19 /* LDC_W */, index);
- } else {
- code.put11(Opcodes.LDC, index);
- }
- }
-
- @Override
- public void visitIincInsn(final int var, final int increment) {
- if (currentBlock != null) {
- if (compute == FRAMES) {
- currentBlock.frame.execute(Opcodes.IINC, var, null, null);
- }
- }
- if (compute != NOTHING) {
- // updates max locals
- int n = var + 1;
- if (n > maxLocals) {
- maxLocals = n;
- }
- }
- // adds the instruction to the bytecode of the method
- if ((var > 255) || (increment > 127) || (increment < -128)) {
- code.putByte(196 /* WIDE */).put12(Opcodes.IINC, var)
- .putShort(increment);
- } else {
- code.putByte(Opcodes.IINC).put11(var, increment);
- }
- }
-
- @Override
- public void visitTableSwitchInsn(final int min, final int max,
- final Label dflt, final Label... labels) {
- // adds the instruction to the bytecode of the method
- int source = code.length;
- code.putByte(Opcodes.TABLESWITCH);
- code.putByteArray(null, 0, (4 - code.length % 4) % 4);
- dflt.put(this, code, source, true);
- code.putInt(min).putInt(max);
- for (int i = 0; i < labels.length; ++i) {
- labels[i].put(this, code, source, true);
- }
- // updates currentBlock
- visitSwitchInsn(dflt, labels);
- }
-
- @Override
- public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
- final Label[] labels) {
- // adds the instruction to the bytecode of the method
- int source = code.length;
- code.putByte(Opcodes.LOOKUPSWITCH);
- code.putByteArray(null, 0, (4 - code.length % 4) % 4);
- dflt.put(this, code, source, true);
- code.putInt(labels.length);
- for (int i = 0; i < labels.length; ++i) {
- code.putInt(keys[i]);
- labels[i].put(this, code, source, true);
- }
- // updates currentBlock
- visitSwitchInsn(dflt, labels);
- }
-
- private void visitSwitchInsn(final Label dflt, final Label[] labels) {
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES) {
- currentBlock.frame.execute(Opcodes.LOOKUPSWITCH, 0, null, null);
- // adds current block successors
- addSuccessor(Edge.NORMAL, dflt);
- dflt.getFirst().status |= Label.TARGET;
- for (int i = 0; i < labels.length; ++i) {
- addSuccessor(Edge.NORMAL, labels[i]);
- labels[i].getFirst().status |= Label.TARGET;
- }
- } else {
- // updates current stack size (max stack size unchanged)
- --stackSize;
- // adds current block successors
- addSuccessor(stackSize, dflt);
- for (int i = 0; i < labels.length; ++i) {
- addSuccessor(stackSize, labels[i]);
- }
- }
- // ends current block
- noSuccessor();
- }
- }
-
- @Override
- public void visitMultiANewArrayInsn(final String desc, final int dims) {
- Item i = cw.newClassItem(desc);
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES) {
- currentBlock.frame.execute(Opcodes.MULTIANEWARRAY, dims, cw, i);
- } else {
- // updates current stack size (max stack size unchanged because
- // stack size variation always negative or null)
- stackSize += 1 - dims;
- }
- }
- // adds the instruction to the bytecode of the method
- code.put12(Opcodes.MULTIANEWARRAY, i.index).putByte(dims);
- }
-
- @Override
- public void visitTryCatchBlock(final Label start, final Label end,
- final Label handler, final String type) {
- ++handlerCount;
- Handler h = new Handler();
- h.start = start;
- h.end = end;
- h.handler = handler;
- h.desc = type;
- h.type = type != null ? cw.newClass(type) : 0;
- if (lastHandler == null) {
- firstHandler = h;
- } else {
- lastHandler.next = h;
- }
- lastHandler = h;
- }
-
- @Override
- public void visitLocalVariable(final String name, final String desc,
- final String signature, final Label start, final Label end,
- final int index) {
- if (signature != null) {
- if (localVarType == null) {
- localVarType = new ByteVector();
- }
- ++localVarTypeCount;
- localVarType.putShort(start.position)
- .putShort(end.position - start.position)
- .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(signature))
- .putShort(index);
- }
- if (localVar == null) {
- localVar = new ByteVector();
- }
- ++localVarCount;
- localVar.putShort(start.position)
- .putShort(end.position - start.position)
- .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(desc))
- .putShort(index);
- if (compute != NOTHING) {
- // updates max locals
- char c = desc.charAt(0);
- int n = index + (c == 'J' || c == 'D' ? 2 : 1);
- if (n > maxLocals) {
- maxLocals = n;
- }
- }
- }
-
- @Override
- public void visitLineNumber(final int line, final Label start) {
- if (lineNumber == null) {
- lineNumber = new ByteVector();
- }
- ++lineNumberCount;
- lineNumber.putShort(start.position);
- lineNumber.putShort(line);
- }
-
- @Override
- public void visitMaxs(final int maxStack, final int maxLocals) {
- if (ClassReader.FRAMES && compute == FRAMES) {
- // completes the control flow graph with exception handler blocks
- Handler handler = firstHandler;
- while (handler != null) {
- Label l = handler.start.getFirst();
- Label h = handler.handler.getFirst();
- Label e = handler.end.getFirst();
- // computes the kind of the edges to 'h'
- String t = handler.desc == null ? "java/lang/Throwable"
- : handler.desc;
- int kind = Frame.OBJECT | cw.addType(t);
- // h is an exception handler
- h.status |= Label.TARGET;
- // adds 'h' as a successor of labels between 'start' and 'end'
- while (l != e) {
- // creates an edge to 'h'
- Edge b = new Edge();
- b.info = kind;
- b.successor = h;
- // adds it to the successors of 'l'
- b.next = l.successors;
- l.successors = b;
- // goes to the next label
- l = l.successor;
- }
- handler = handler.next;
- }
-
- // creates and visits the first (implicit) frame
- Frame f = labels.frame;
- Type[] args = Type.getArgumentTypes(descriptor);
- f.initInputFrame(cw, access, args, this.maxLocals);
- visitFrame(f);
-
- /*
- * fix point algorithm: mark the first basic block as 'changed'
- * (i.e. put it in the 'changed' list) and, while there are changed
- * basic blocks, choose one, mark it as unchanged, and update its
- * successors (which can be changed in the process).
- */
- int max = 0;
- Label changed = labels;
- while (changed != null) {
- // removes a basic block from the list of changed basic blocks
- Label l = changed;
- changed = changed.next;
- l.next = null;
- f = l.frame;
- // a reachable jump target must be stored in the stack map
- if ((l.status & Label.TARGET) != 0) {
- l.status |= Label.STORE;
- }
- // all visited labels are reachable, by definition
- l.status |= Label.REACHABLE;
- // updates the (absolute) maximum stack size
- int blockMax = f.inputStack.length + l.outputStackMax;
- if (blockMax > max) {
- max = blockMax;
- }
- // updates the successors of the current basic block
- Edge e = l.successors;
- while (e != null) {
- Label n = e.successor.getFirst();
- boolean change = f.merge(cw, n.frame, e.info);
- if (change && n.next == null) {
- // if n has changed and is not already in the 'changed'
- // list, adds it to this list
- n.next = changed;
- changed = n;
- }
- e = e.next;
- }
- }
-
- // visits all the frames that must be stored in the stack map
- Label l = labels;
- while (l != null) {
- f = l.frame;
- if ((l.status & Label.STORE) != 0) {
- visitFrame(f);
- }
- if ((l.status & Label.REACHABLE) == 0) {
- // finds start and end of dead basic block
- Label k = l.successor;
- int start = l.position;
- int end = (k == null ? code.length : k.position) - 1;
- // if non empty basic block
- if (end >= start) {
- max = Math.max(max, 1);
- // replaces instructions with NOP ... NOP ATHROW
- for (int i = start; i < end; ++i) {
- code.data[i] = Opcodes.NOP;
- }
- code.data[end] = (byte) Opcodes.ATHROW;
- // emits a frame for this unreachable block
- int frameIndex = startFrame(start, 0, 1);
- frame[frameIndex] = Frame.OBJECT
- | cw.addType("java/lang/Throwable");
- endFrame();
- // removes the start-end range from the exception
- // handlers
- firstHandler = Handler.remove(firstHandler, l, k);
- }
- }
- l = l.successor;
- }
-
- handler = firstHandler;
- handlerCount = 0;
- while (handler != null) {
- handlerCount += 1;
- handler = handler.next;
- }
-
- this.maxStack = max;
- } else if (compute == MAXS) {
- // completes the control flow graph with exception handler blocks
- Handler handler = firstHandler;
- while (handler != null) {
- Label l = handler.start;
- Label h = handler.handler;
- Label e = handler.end;
- // adds 'h' as a successor of labels between 'start' and 'end'
- while (l != e) {
- // creates an edge to 'h'
- Edge b = new Edge();
- b.info = Edge.EXCEPTION;
- b.successor = h;
- // adds it to the successors of 'l'
- if ((l.status & Label.JSR) == 0) {
- b.next = l.successors;
- l.successors = b;
- } else {
- // if l is a JSR block, adds b after the first two edges
- // to preserve the hypothesis about JSR block successors
- // order (see {@link #visitJumpInsn})
- b.next = l.successors.next.next;
- l.successors.next.next = b;
- }
- // goes to the next label
- l = l.successor;
- }
- handler = handler.next;
- }
-
- if (subroutines > 0) {
- // completes the control flow graph with the RET successors
- /*
- * first step: finds the subroutines. This step determines, for
- * each basic block, to which subroutine(s) it belongs.
- */
- // finds the basic blocks that belong to the "main" subroutine
- int id = 0;
- labels.visitSubroutine(null, 1, subroutines);
- // finds the basic blocks that belong to the real subroutines
- Label l = labels;
- while (l != null) {
- if ((l.status & Label.JSR) != 0) {
- // the subroutine is defined by l's TARGET, not by l
- Label subroutine = l.successors.next.successor;
- // if this subroutine has not been visited yet...
- if ((subroutine.status & Label.VISITED) == 0) {
- // ...assigns it a new id and finds its basic blocks
- id += 1;
- subroutine.visitSubroutine(null, (id / 32L) << 32
- | (1L << (id % 32)), subroutines);
- }
- }
- l = l.successor;
- }
- // second step: finds the successors of RET blocks
- l = labels;
- while (l != null) {
- if ((l.status & Label.JSR) != 0) {
- Label L = labels;
- while (L != null) {
- L.status &= ~Label.VISITED2;
- L = L.successor;
- }
- // the subroutine is defined by l's TARGET, not by l
- Label subroutine = l.successors.next.successor;
- subroutine.visitSubroutine(l, 0, subroutines);
- }
- l = l.successor;
- }
- }
-
- /*
- * control flow analysis algorithm: while the block stack is not
- * empty, pop a block from this stack, update the max stack size,
- * compute the true (non relative) begin stack size of the
- * successors of this block, and push these successors onto the
- * stack (unless they have already been pushed onto the stack).
- * Note: by hypothesis, the {@link Label#inputStackTop} of the
- * blocks in the block stack are the true (non relative) beginning
- * stack sizes of these blocks.
- */
- int max = 0;
- Label stack = labels;
- while (stack != null) {
- // pops a block from the stack
- Label l = stack;
- stack = stack.next;
- // computes the true (non relative) max stack size of this block
- int start = l.inputStackTop;
- int blockMax = start + l.outputStackMax;
- // updates the global max stack size
- if (blockMax > max) {
- max = blockMax;
- }
- // analyzes the successors of the block
- Edge b = l.successors;
- if ((l.status & Label.JSR) != 0) {
- // ignores the first edge of JSR blocks (virtual successor)
- b = b.next;
- }
- while (b != null) {
- l = b.successor;
- // if this successor has not already been pushed...
- if ((l.status & Label.PUSHED) == 0) {
- // computes its true beginning stack size...
- l.inputStackTop = b.info == Edge.EXCEPTION ? 1 : start
- + b.info;
- // ...and pushes it onto the stack
- l.status |= Label.PUSHED;
- l.next = stack;
- stack = l;
- }
- b = b.next;
- }
- }
- this.maxStack = Math.max(maxStack, max);
- } else {
- this.maxStack = maxStack;
- this.maxLocals = maxLocals;
- }
- }
-
- @Override
- public void visitEnd() {
- }
-
- // ------------------------------------------------------------------------
- // Utility methods: control flow analysis algorithm
- // ------------------------------------------------------------------------
-
- /**
- * Adds a successor to the {@link #currentBlock currentBlock} block.
- *
- * @param info
- * information about the control flow edge to be added.
- * @param successor
- * the successor block to be added to the current block.
- */
- private void addSuccessor(final int info, final Label successor) {
- // creates and initializes an Edge object...
- Edge b = new Edge();
- b.info = info;
- b.successor = successor;
- // ...and adds it to the successor list of the currentBlock block
- b.next = currentBlock.successors;
- currentBlock.successors = b;
- }
-
- /**
- * Ends the current basic block. This method must be used in the case where
- * the current basic block does not have any successor.
- */
- private void noSuccessor() {
- if (compute == FRAMES) {
- Label l = new Label();
- l.frame = new Frame();
- l.frame.owner = l;
- l.resolve(this, code.length, code.data);
- previousBlock.successor = l;
- previousBlock = l;
- } else {
- currentBlock.outputStackMax = maxStackSize;
- }
- currentBlock = null;
- }
-
- // ------------------------------------------------------------------------
- // Utility methods: stack map frames
- // ------------------------------------------------------------------------
-
- /**
- * Visits a frame that has been computed from scratch.
- *
- * @param f
- * the frame that must be visited.
- */
- private void visitFrame(final Frame f) {
- int i, t;
- int nTop = 0;
- int nLocal = 0;
- int nStack = 0;
- int[] locals = f.inputLocals;
- int[] stacks = f.inputStack;
- // computes the number of locals (ignores TOP types that are just after
- // a LONG or a DOUBLE, and all trailing TOP types)
- for (i = 0; i < locals.length; ++i) {
- t = locals[i];
- if (t == Frame.TOP) {
- ++nTop;
- } else {
- nLocal += nTop + 1;
- nTop = 0;
- }
- if (t == Frame.LONG || t == Frame.DOUBLE) {
- ++i;
- }
- }
- // computes the stack size (ignores TOP types that are just after
- // a LONG or a DOUBLE)
- for (i = 0; i < stacks.length; ++i) {
- t = stacks[i];
- ++nStack;
- if (t == Frame.LONG || t == Frame.DOUBLE) {
- ++i;
- }
- }
- // visits the frame and its content
- int frameIndex = startFrame(f.owner.position, nLocal, nStack);
- for (i = 0; nLocal > 0; ++i, --nLocal) {
- t = locals[i];
- frame[frameIndex++] = t;
- if (t == Frame.LONG || t == Frame.DOUBLE) {
- ++i;
- }
- }
- for (i = 0; i < stacks.length; ++i) {
- t = stacks[i];
- frame[frameIndex++] = t;
- if (t == Frame.LONG || t == Frame.DOUBLE) {
- ++i;
- }
- }
- endFrame();
- }
-
- /**
- * Visit the implicit first frame of this method.
- */
- private void visitImplicitFirstFrame() {
- // There can be at most descriptor.length() + 1 locals
- int frameIndex = startFrame(0, descriptor.length() + 1, 0);
- if ((access & Opcodes.ACC_STATIC) == 0) {
- if ((access & ACC_CONSTRUCTOR) == 0) {
- frame[frameIndex++] = Frame.OBJECT | cw.addType(cw.thisName);
- } else {
- frame[frameIndex++] = 6; // Opcodes.UNINITIALIZED_THIS;
- }
- }
- int i = 1;
- loop: while (true) {
- int j = i;
- switch (descriptor.charAt(i++)) {
- case 'Z':
- case 'C':
- case 'B':
- case 'S':
- case 'I':
- frame[frameIndex++] = 1; // Opcodes.INTEGER;
- break;
- case 'F':
- frame[frameIndex++] = 2; // Opcodes.FLOAT;
- break;
- case 'J':
- frame[frameIndex++] = 4; // Opcodes.LONG;
- break;
- case 'D':
- frame[frameIndex++] = 3; // Opcodes.DOUBLE;
- break;
- case '[':
- while (descriptor.charAt(i) == '[') {
- ++i;
- }
- if (descriptor.charAt(i) == 'L') {
- ++i;
- while (descriptor.charAt(i) != ';') {
- ++i;
- }
- }
- frame[frameIndex++] = Frame.OBJECT
- | cw.addType(descriptor.substring(j, ++i));
- break;
- case 'L':
- while (descriptor.charAt(i) != ';') {
- ++i;
- }
- frame[frameIndex++] = Frame.OBJECT
- | cw.addType(descriptor.substring(j + 1, i++));
- break;
- default:
- break loop;
- }
- }
- frame[1] = frameIndex - 3;
- endFrame();
- }
-
- /**
- * Starts the visit of a stack map frame.
- *
- * @param offset
- * the offset of the instruction to which the frame corresponds.
- * @param nLocal
- * the number of local variables in the frame.
- * @param nStack
- * the number of stack elements in the frame.
- * @return the index of the next element to be written in this frame.
- */
- private int startFrame(final int offset, final int nLocal, final int nStack) {
- int n = 3 + nLocal + nStack;
- if (frame == null || frame.length < n) {
- frame = new int[n];
- }
- frame[0] = offset;
- frame[1] = nLocal;
- frame[2] = nStack;
- return 3;
- }
-
- /**
- * Checks if the visit of the current frame {@link #frame} is finished, and
- * if yes, write it in the StackMapTable attribute.
- */
- private void endFrame() {
- if (previousFrame != null) { // do not write the first frame
- if (stackMap == null) {
- stackMap = new ByteVector();
- }
- writeFrame();
- ++frameCount;
- }
- previousFrame = frame;
- frame = null;
- }
-
- /**
- * Compress and writes the current frame {@link #frame} in the StackMapTable
- * attribute.
- */
- private void writeFrame() {
- int clocalsSize = frame[1];
- int cstackSize = frame[2];
- if ((cw.version & 0xFFFF) < Opcodes.V1_6) {
- stackMap.putShort(frame[0]).putShort(clocalsSize);
- writeFrameTypes(3, 3 + clocalsSize);
- stackMap.putShort(cstackSize);
- writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);
- return;
- }
- int localsSize = previousFrame[1];
- int type = FULL_FRAME;
- int k = 0;
- int delta;
- if (frameCount == 0) {
- delta = frame[0];
- } else {
- delta = frame[0] - previousFrame[0] - 1;
- }
- if (cstackSize == 0) {
- k = clocalsSize - localsSize;
- switch (k) {
- case -3:
- case -2:
- case -1:
- type = CHOP_FRAME;
- localsSize = clocalsSize;
- break;
- case 0:
- type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED;
- break;
- case 1:
- case 2:
- case 3:
- type = APPEND_FRAME;
- break;
- }
- } else if (clocalsSize == localsSize && cstackSize == 1) {
- type = delta < 63 ? SAME_LOCALS_1_STACK_ITEM_FRAME
- : SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;
- }
- if (type != FULL_FRAME) {
- // verify if locals are the same
- int l = 3;
- for (int j = 0; j < localsSize; j++) {
- if (frame[l] != previousFrame[l]) {
- type = FULL_FRAME;
- break;
- }
- l++;
- }
- }
- switch (type) {
- case SAME_FRAME:
- stackMap.putByte(delta);
- break;
- case SAME_LOCALS_1_STACK_ITEM_FRAME:
- stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
- writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
- break;
- case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:
- stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED).putShort(
- delta);
- writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
- break;
- case SAME_FRAME_EXTENDED:
- stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
- break;
- case CHOP_FRAME:
- stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
- break;
- case APPEND_FRAME:
- stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
- writeFrameTypes(3 + localsSize, 3 + clocalsSize);
- break;
- // case FULL_FRAME:
- default:
- stackMap.putByte(FULL_FRAME).putShort(delta).putShort(clocalsSize);
- writeFrameTypes(3, 3 + clocalsSize);
- stackMap.putShort(cstackSize);
- writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);
- }
- }
-
- /**
- * Writes some types of the current frame {@link #frame} into the
- * StackMapTableAttribute. This method converts types from the format used
- * in {@link Label} to the format used in StackMapTable attributes. In
- * particular, it converts type table indexes to constant pool indexes.
- *
- * @param start
- * index of the first type in {@link #frame} to write.
- * @param end
- * index of last type in {@link #frame} to write (exclusive).
- */
- private void writeFrameTypes(final int start, final int end) {
- for (int i = start; i < end; ++i) {
- int t = frame[i];
- int d = t & Frame.DIM;
- if (d == 0) {
- int v = t & Frame.BASE_VALUE;
- switch (t & Frame.BASE_KIND) {
- case Frame.OBJECT:
- stackMap.putByte(7).putShort(
- cw.newClass(cw.typeTable[v].strVal1));
- break;
- case Frame.UNINITIALIZED:
- stackMap.putByte(8).putShort(cw.typeTable[v].intVal);
- break;
- default:
- stackMap.putByte(v);
- }
- } else {
- StringBuffer buf = new StringBuffer();
- d >>= 28;
- while (d-- > 0) {
- buf.append('[');
- }
- if ((t & Frame.BASE_KIND) == Frame.OBJECT) {
- buf.append('L');
- buf.append(cw.typeTable[t & Frame.BASE_VALUE].strVal1);
- buf.append(';');
- } else {
- switch (t & 0xF) {
- case 1:
- buf.append('I');
- break;
- case 2:
- buf.append('F');
- break;
- case 3:
- buf.append('D');
- break;
- case 9:
- buf.append('Z');
- break;
- case 10:
- buf.append('B');
- break;
- case 11:
- buf.append('C');
- break;
- case 12:
- buf.append('S');
- break;
- default:
- buf.append('J');
- }
- }
- stackMap.putByte(7).putShort(cw.newClass(buf.toString()));
- }
- }
- }
-
- private void writeFrameType(final Object type) {
- if (type instanceof String) {
- stackMap.putByte(7).putShort(cw.newClass((String) type));
- } else if (type instanceof Integer) {
- stackMap.putByte(((Integer) type).intValue());
- } else {
- stackMap.putByte(8).putShort(((Label) type).position);
- }
- }
-
- // ------------------------------------------------------------------------
- // Utility methods: dump bytecode array
- // ------------------------------------------------------------------------
-
- /**
- * Returns the size of the bytecode of this method.
- *
- * @return the size of the bytecode of this method.
- */
- final int getSize() {
- if (classReaderOffset != 0) {
- return 6 + classReaderLength;
- }
- if (resize) {
- // replaces the temporary jump opcodes introduced by Label.resolve.
- if (ClassReader.RESIZE) {
- resizeInstructions();
- } else {
- throw new RuntimeException("Method code too large!");
- }
- }
- int size = 8;
- if (code.length > 0) {
- if (code.length > 65536) {
- throw new RuntimeException("Method code too large!");
- }
- cw.newUTF8("Code");
- size += 18 + code.length + 8 * handlerCount;
- if (localVar != null) {
- cw.newUTF8("LocalVariableTable");
- size += 8 + localVar.length;
- }
- if (localVarType != null) {
- cw.newUTF8("LocalVariableTypeTable");
- size += 8 + localVarType.length;
- }
- if (lineNumber != null) {
- cw.newUTF8("LineNumberTable");
- size += 8 + lineNumber.length;
- }
- if (stackMap != null) {
- boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6;
- cw.newUTF8(zip ? "StackMapTable" : "StackMap");
- size += 8 + stackMap.length;
- }
- if (cattrs != null) {
- size += cattrs.getSize(cw, code.data, code.length, maxStack,
- maxLocals);
- }
- }
- if (exceptionCount > 0) {
- cw.newUTF8("Exceptions");
- size += 8 + 2 * exceptionCount;
- }
- if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
- if ((cw.version & 0xFFFF) < Opcodes.V1_5
- || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
- cw.newUTF8("Synthetic");
- size += 6;
- }
- }
- if ((access & Opcodes.ACC_DEPRECATED) != 0) {
- cw.newUTF8("Deprecated");
- size += 6;
- }
- if (ClassReader.SIGNATURES && signature != null) {
- cw.newUTF8("Signature");
- cw.newUTF8(signature);
- size += 8;
- }
- if (ClassReader.ANNOTATIONS && annd != null) {
- cw.newUTF8("AnnotationDefault");
- size += 6 + annd.length;
- }
- if (ClassReader.ANNOTATIONS && anns != null) {
- cw.newUTF8("RuntimeVisibleAnnotations");
- size += 8 + anns.getSize();
- }
- if (ClassReader.ANNOTATIONS && ianns != null) {
- cw.newUTF8("RuntimeInvisibleAnnotations");
- size += 8 + ianns.getSize();
- }
- if (ClassReader.ANNOTATIONS && panns != null) {
- cw.newUTF8("RuntimeVisibleParameterAnnotations");
- size += 7 + 2 * (panns.length - synthetics);
- for (int i = panns.length - 1; i >= synthetics; --i) {
- size += panns[i] == null ? 0 : panns[i].getSize();
- }
- }
- if (ClassReader.ANNOTATIONS && ipanns != null) {
- cw.newUTF8("RuntimeInvisibleParameterAnnotations");
- size += 7 + 2 * (ipanns.length - synthetics);
- for (int i = ipanns.length - 1; i >= synthetics; --i) {
- size += ipanns[i] == null ? 0 : ipanns[i].getSize();
- }
- }
- if (attrs != null) {
- size += attrs.getSize(cw, null, 0, -1, -1);
- }
- return size;
- }
-
- /**
- * Puts the bytecode of this method in the given byte vector.
- *
- * @param out
- * the byte vector into which the bytecode of this method must be
- * copied.
- */
- final void put(final ByteVector out) {
- final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
- int mask = ACC_CONSTRUCTOR | Opcodes.ACC_DEPRECATED
- | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
- | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
- out.putShort(access & ~mask).putShort(name).putShort(desc);
- if (classReaderOffset != 0) {
- out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength);
- return;
- }
- int attributeCount = 0;
- if (code.length > 0) {
- ++attributeCount;
- }
- if (exceptionCount > 0) {
- ++attributeCount;
- }
- if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
- if ((cw.version & 0xFFFF) < Opcodes.V1_5
- || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
- ++attributeCount;
- }
- }
- if ((access & Opcodes.ACC_DEPRECATED) != 0) {
- ++attributeCount;
- }
- if (ClassReader.SIGNATURES && signature != null) {
- ++attributeCount;
- }
- if (ClassReader.ANNOTATIONS && annd != null) {
- ++attributeCount;
- }
- if (ClassReader.ANNOTATIONS && anns != null) {
- ++attributeCount;
- }
- if (ClassReader.ANNOTATIONS && ianns != null) {
- ++attributeCount;
- }
- if (ClassReader.ANNOTATIONS && panns != null) {
- ++attributeCount;
- }
- if (ClassReader.ANNOTATIONS && ipanns != null) {
- ++attributeCount;
- }
- if (attrs != null) {
- attributeCount += attrs.getCount();
- }
- out.putShort(attributeCount);
- if (code.length > 0) {
- int size = 12 + code.length + 8 * handlerCount;
- if (localVar != null) {
- size += 8 + localVar.length;
- }
- if (localVarType != null) {
- size += 8 + localVarType.length;
- }
- if (lineNumber != null) {
- size += 8 + lineNumber.length;
- }
- if (stackMap != null) {
- size += 8 + stackMap.length;
- }
- if (cattrs != null) {
- size += cattrs.getSize(cw, code.data, code.length, maxStack,
- maxLocals);
- }
- out.putShort(cw.newUTF8("Code")).putInt(size);
- out.putShort(maxStack).putShort(maxLocals);
- out.putInt(code.length).putByteArray(code.data, 0, code.length);
- out.putShort(handlerCount);
- if (handlerCount > 0) {
- Handler h = firstHandler;
- while (h != null) {
- out.putShort(h.start.position).putShort(h.end.position)
- .putShort(h.handler.position).putShort(h.type);
- h = h.next;
- }
- }
- attributeCount = 0;
- if (localVar != null) {
- ++attributeCount;
- }
- if (localVarType != null) {
- ++attributeCount;
- }
- if (lineNumber != null) {
- ++attributeCount;
- }
- if (stackMap != null) {
- ++attributeCount;
- }
- if (cattrs != null) {
- attributeCount += cattrs.getCount();
- }
- out.putShort(attributeCount);
- if (localVar != null) {
- out.putShort(cw.newUTF8("LocalVariableTable"));
- out.putInt(localVar.length + 2).putShort(localVarCount);
- out.putByteArray(localVar.data, 0, localVar.length);
- }
- if (localVarType != null) {
- out.putShort(cw.newUTF8("LocalVariableTypeTable"));
- out.putInt(localVarType.length + 2).putShort(localVarTypeCount);
- out.putByteArray(localVarType.data, 0, localVarType.length);
- }
- if (lineNumber != null) {
- out.putShort(cw.newUTF8("LineNumberTable"));
- out.putInt(lineNumber.length + 2).putShort(lineNumberCount);
- out.putByteArray(lineNumber.data, 0, lineNumber.length);
- }
- if (stackMap != null) {
- boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6;
- out.putShort(cw.newUTF8(zip ? "StackMapTable" : "StackMap"));
- out.putInt(stackMap.length + 2).putShort(frameCount);
- out.putByteArray(stackMap.data, 0, stackMap.length);
- }
- if (cattrs != null) {
- cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out);
- }
- }
- if (exceptionCount > 0) {
- out.putShort(cw.newUTF8("Exceptions")).putInt(
- 2 * exceptionCount + 2);
- out.putShort(exceptionCount);
- for (int i = 0; i < exceptionCount; ++i) {
- out.putShort(exceptions[i]);
- }
- }
- if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
- if ((cw.version & 0xFFFF) < Opcodes.V1_5
- || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
- out.putShort(cw.newUTF8("Synthetic")).putInt(0);
- }
- }
- if ((access & Opcodes.ACC_DEPRECATED) != 0) {
- out.putShort(cw.newUTF8("Deprecated")).putInt(0);
- }
- if (ClassReader.SIGNATURES && signature != null) {
- out.putShort(cw.newUTF8("Signature")).putInt(2)
- .putShort(cw.newUTF8(signature));
- }
- if (ClassReader.ANNOTATIONS && annd != null) {
- out.putShort(cw.newUTF8("AnnotationDefault"));
- out.putInt(annd.length);
- out.putByteArray(annd.data, 0, annd.length);
- }
- if (ClassReader.ANNOTATIONS && anns != null) {
- out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
- anns.put(out);
- }
- if (ClassReader.ANNOTATIONS && ianns != null) {
- out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
- ianns.put(out);
- }
- if (ClassReader.ANNOTATIONS && panns != null) {
- out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations"));
- AnnotationWriter.put(panns, synthetics, out);
- }
- if (ClassReader.ANNOTATIONS && ipanns != null) {
- out.putShort(cw.newUTF8("RuntimeInvisibleParameterAnnotations"));
- AnnotationWriter.put(ipanns, synthetics, out);
- }
- if (attrs != null) {
- attrs.put(cw, null, 0, -1, -1, out);
- }
- }
-
- // ------------------------------------------------------------------------
- // Utility methods: instruction resizing (used to handle GOTO_W and JSR_W)
- // ------------------------------------------------------------------------
-
- /**
- * Resizes and replaces the temporary instructions inserted by
- * {@link Label#resolve} for wide forward jumps, while keeping jump offsets
- * and instruction addresses consistent. This may require to resize other
- * existing instructions, or even to introduce new instructions: for
- * example, increasing the size of an instruction by 2 at the middle of a
- * method can increases the offset of an IFEQ instruction from 32766 to
- * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W
- * 32765. This, in turn, may require to increase the size of another jump
- * instruction, and so on... All these operations are handled automatically
- * by this method.
- * <p>
- * <i>This method must be called after all the method that is being built
- * has been visited</i>. In particular, the {@link Label Label} objects used
- * to construct the method are no longer valid after this method has been
- * called.
- */
- private void resizeInstructions() {
- byte[] b = code.data; // bytecode of the method
- int u, v, label; // indexes in b
- int i, j; // loop indexes
- /*
- * 1st step: As explained above, resizing an instruction may require to
- * resize another one, which may require to resize yet another one, and
- * so on. The first step of the algorithm consists in finding all the
- * instructions that need to be resized, without modifying the code.
- * This is done by the following "fix point" algorithm:
- *
- * Parse the code to find the jump instructions whose offset will need
- * more than 2 bytes to be stored (the future offset is computed from
- * the current offset and from the number of bytes that will be inserted
- * or removed between the source and target instructions). For each such
- * instruction, adds an entry in (a copy of) the indexes and sizes
- * arrays (if this has not already been done in a previous iteration!).
- *
- * If at least one entry has been added during the previous step, go
- * back to the beginning, otherwise stop.
- *
- * In fact the real algorithm is complicated by the fact that the size
- * of TABLESWITCH and LOOKUPSWITCH instructions depends on their
- * position in the bytecode (because of padding). In order to ensure the
- * convergence of the algorithm, the number of bytes to be added or
- * removed from these instructions is over estimated during the previous
- * loop, and computed exactly only after the loop is finished (this
- * requires another pass to parse the bytecode of the method).
- */
- int[] allIndexes = new int[0]; // copy of indexes
- int[] allSizes = new int[0]; // copy of sizes
- boolean[] resize; // instructions to be resized
- int newOffset; // future offset of a jump instruction
-
- resize = new boolean[code.length];
-
- // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done
- int state = 3;
- do {
- if (state == 3) {
- state = 2;
- }
- u = 0;
- while (u < b.length) {
- int opcode = b[u] & 0xFF; // opcode of current instruction
- int insert = 0; // bytes to be added after this instruction
-
- switch (ClassWriter.TYPE[opcode]) {
- case ClassWriter.NOARG_INSN:
- case ClassWriter.IMPLVAR_INSN:
- u += 1;
- break;
- case ClassWriter.LABEL_INSN:
- if (opcode > 201) {
- // converts temporary opcodes 202 to 217, 218 and
- // 219 to IFEQ ... JSR (inclusive), IFNULL and
- // IFNONNULL
- opcode = opcode < 218 ? opcode - 49 : opcode - 20;
- label = u + readUnsignedShort(b, u + 1);
- } else {
- label = u + readShort(b, u + 1);
- }
- newOffset = getNewOffset(allIndexes, allSizes, u, label);
- if (newOffset < Short.MIN_VALUE
- || newOffset > Short.MAX_VALUE) {
- if (!resize[u]) {
- if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
- // two additional bytes will be required to
- // replace this GOTO or JSR instruction with
- // a GOTO_W or a JSR_W
- insert = 2;
- } else {
- // five additional bytes will be required to
- // replace this IFxxx <l> instruction with
- // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx
- // is the "opposite" opcode of IFxxx (i.e.,
- // IFNE for IFEQ) and where <l'> designates
- // the instruction just after the GOTO_W.
- insert = 5;
- }
- resize[u] = true;
- }
- }
- u += 3;
- break;
- case ClassWriter.LABELW_INSN:
- u += 5;
- break;
- case ClassWriter.TABL_INSN:
- if (state == 1) {
- // true number of bytes to be added (or removed)
- // from this instruction = (future number of padding
- // bytes - current number of padding byte) -
- // previously over estimated variation =
- // = ((3 - newOffset%4) - (3 - u%4)) - u%4
- // = (-newOffset%4 + u%4) - u%4
- // = -(newOffset & 3)
- newOffset = getNewOffset(allIndexes, allSizes, 0, u);
- insert = -(newOffset & 3);
- } else if (!resize[u]) {
- // over estimation of the number of bytes to be
- // added to this instruction = 3 - current number
- // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3
- insert = u & 3;
- resize[u] = true;
- }
- // skips instruction
- u = u + 4 - (u & 3);
- u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12;
- break;
- case ClassWriter.LOOK_INSN:
- if (state == 1) {
- // like TABL_INSN
- newOffset = getNewOffset(allIndexes, allSizes, 0, u);
- insert = -(newOffset & 3);
- } else if (!resize[u]) {
- // like TABL_INSN
- insert = u & 3;
- resize[u] = true;
- }
- // skips instruction
- u = u + 4 - (u & 3);
- u += 8 * readInt(b, u + 4) + 8;
- break;
- case ClassWriter.WIDE_INSN:
- opcode = b[u + 1] & 0xFF;
- if (opcode == Opcodes.IINC) {
- u += 6;
- } else {
- u += 4;
- }
- break;
- case ClassWriter.VAR_INSN:
- case ClassWriter.SBYTE_INSN:
- case ClassWriter.LDC_INSN:
- u += 2;
- break;
- case ClassWriter.SHORT_INSN:
- case ClassWriter.LDCW_INSN:
- case ClassWriter.FIELDORMETH_INSN:
- case ClassWriter.TYPE_INSN:
- case ClassWriter.IINC_INSN:
- u += 3;
- break;
- case ClassWriter.ITFMETH_INSN:
- case ClassWriter.INDYMETH_INSN:
- u += 5;
- break;
- // case ClassWriter.MANA_INSN:
- default:
- u += 4;
- break;
- }
- if (insert != 0) {
- // adds a new (u, insert) entry in the allIndexes and
- // allSizes arrays
- int[] newIndexes = new int[allIndexes.length + 1];
- int[] newSizes = new int[allSizes.length + 1];
- System.arraycopy(allIndexes, 0, newIndexes, 0,
- allIndexes.length);
- System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length);
- newIndexes[allIndexes.length] = u;
- newSizes[allSizes.length] = insert;
- allIndexes = newIndexes;
- allSizes = newSizes;
- if (insert > 0) {
- state = 3;
- }
- }
- }
- if (state < 3) {
- --state;
- }
- } while (state != 0);
-
- // 2nd step:
- // copies the bytecode of the method into a new bytevector, updates the
- // offsets, and inserts (or removes) bytes as requested.
-
- ByteVector newCode = new ByteVector(code.length);
-
- u = 0;
- while (u < code.length) {
- int opcode = b[u] & 0xFF;
- switch (ClassWriter.TYPE[opcode]) {
- case ClassWriter.NOARG_INSN:
- case ClassWriter.IMPLVAR_INSN:
- newCode.putByte(opcode);
- u += 1;
- break;
- case ClassWriter.LABEL_INSN:
- if (opcode > 201) {
- // changes temporary opcodes 202 to 217 (inclusive), 218
- // and 219 to IFEQ ... JSR (inclusive), IFNULL and
- // IFNONNULL
- opcode = opcode < 218 ? opcode - 49 : opcode - 20;
- label = u + readUnsignedShort(b, u + 1);
- } else {
- label = u + readShort(b, u + 1);
- }
- newOffset = getNewOffset(allIndexes, allSizes, u, label);
- if (resize[u]) {
- // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
- // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is
- // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
- // and where <l'> designates the instruction just after
- // the GOTO_W.
- if (opcode == Opcodes.GOTO) {
- newCode.putByte(200); // GOTO_W
- } else if (opcode == Opcodes.JSR) {
- newCode.putByte(201); // JSR_W
- } else {
- newCode.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
- : opcode ^ 1);
- newCode.putShort(8); // jump offset
- newCode.putByte(200); // GOTO_W
- // newOffset now computed from start of GOTO_W
- newOffset -= 3;
- }
- newCode.putInt(newOffset);
- } else {
- newCode.putByte(opcode);
- newCode.putShort(newOffset);
- }
- u += 3;
- break;
- case ClassWriter.LABELW_INSN:
- label = u + readInt(b, u + 1);
- newOffset = getNewOffset(allIndexes, allSizes, u, label);
- newCode.putByte(opcode);
- newCode.putInt(newOffset);
- u += 5;
- break;
- case ClassWriter.TABL_INSN:
- // skips 0 to 3 padding bytes
- v = u;
- u = u + 4 - (v & 3);
- // reads and copies instruction
- newCode.putByte(Opcodes.TABLESWITCH);
- newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
- label = v + readInt(b, u);
- u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
- j = readInt(b, u);
- u += 4;
- newCode.putInt(j);
- j = readInt(b, u) - j + 1;
- u += 4;
- newCode.putInt(readInt(b, u - 4));
- for (; j > 0; --j) {
- label = v + readInt(b, u);
- u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
- }
- break;
- case ClassWriter.LOOK_INSN:
- // skips 0 to 3 padding bytes
- v = u;
- u = u + 4 - (v & 3);
- // reads and copies instruction
- newCode.putByte(Opcodes.LOOKUPSWITCH);
- newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
- label = v + readInt(b, u);
- u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
- j = readInt(b, u);
- u += 4;
- newCode.putInt(j);
- for (; j > 0; --j) {
- newCode.putInt(readInt(b, u));
- u += 4;
- label = v + readInt(b, u);
- u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
- }
- break;
- case ClassWriter.WIDE_INSN:
- opcode = b[u + 1] & 0xFF;
- if (opcode == Opcodes.IINC) {
- newCode.putByteArray(b, u, 6);
- u += 6;
- } else {
- newCode.putByteArray(b, u, 4);
- u += 4;
- }
- break;
- case ClassWriter.VAR_INSN:
- case ClassWriter.SBYTE_INSN:
- case ClassWriter.LDC_INSN:
- newCode.putByteArray(b, u, 2);
- u += 2;
- break;
- case ClassWriter.SHORT_INSN:
- case ClassWriter.LDCW_INSN:
- case ClassWriter.FIELDORMETH_INSN:
- case ClassWriter.TYPE_INSN:
- case ClassWriter.IINC_INSN:
- newCode.putByteArray(b, u, 3);
- u += 3;
- break;
- case ClassWriter.ITFMETH_INSN:
- case ClassWriter.INDYMETH_INSN:
- newCode.putByteArray(b, u, 5);
- u += 5;
- break;
- // case MANA_INSN:
- default:
- newCode.putByteArray(b, u, 4);
- u += 4;
- break;
- }
- }
-
- // recomputes the stack map frames
- if (frameCount > 0) {
- if (compute == FRAMES) {
- frameCount = 0;
- stackMap = null;
- previousFrame = null;
- frame = null;
- Frame f = new Frame();
- f.owner = labels;
- Type[] args = Type.getArgumentTypes(descriptor);
- f.initInputFrame(cw, access, args, maxLocals);
- visitFrame(f);
- Label l = labels;
- while (l != null) {
- /*
- * here we need the original label position. getNewOffset
- * must therefore never have been called for this label.
- */
- u = l.position - 3;
- if ((l.status & Label.STORE) != 0 || (u >= 0 && resize[u])) {
- getNewOffset(allIndexes, allSizes, l);
- // TODO update offsets in UNINITIALIZED values
- visitFrame(l.frame);
- }
- l = l.successor;
- }
- } else {
- /*
- * Resizing an existing stack map frame table is really hard.
- * Not only the table must be parsed to update the offets, but
- * new frames may be needed for jump instructions that were
- * inserted by this method. And updating the offsets or
- * inserting frames can change the format of the following
- * frames, in case of packed frames. In practice the whole table
- * must be recomputed. For this the frames are marked as
- * potentially invalid. This will cause the whole class to be
- * reread and rewritten with the COMPUTE_FRAMES option (see the
- * ClassWriter.toByteArray method). This is not very efficient
- * but is much easier and requires much less code than any other
- * method I can think of.
- */
- cw.invalidFrames = true;
- }
- }
- // updates the exception handler block labels
- Handler h = firstHandler;
- while (h != null) {
- getNewOffset(allIndexes, allSizes, h.start);
- getNewOffset(allIndexes, allSizes, h.end);
- getNewOffset(allIndexes, allSizes, h.handler);
- h = h.next;
- }
- // updates the instructions addresses in the
- // local var and line number tables
- for (i = 0; i < 2; ++i) {
- ByteVector bv = i == 0 ? localVar : localVarType;
- if (bv != null) {
- b = bv.data;
- u = 0;
- while (u < bv.length) {
- label = readUnsignedShort(b, u);
- newOffset = getNewOffset(allIndexes, allSizes, 0, label);
- writeShort(b, u, newOffset);
- label += readUnsignedShort(b, u + 2);
- newOffset = getNewOffset(allIndexes, allSizes, 0, label)
- - newOffset;
- writeShort(b, u + 2, newOffset);
- u += 10;
- }
- }
- }
- if (lineNumber != null) {
- b = lineNumber.data;
- u = 0;
- while (u < lineNumber.length) {
- writeShort(
- b,
- u,
- getNewOffset(allIndexes, allSizes, 0,
- readUnsignedShort(b, u)));
- u += 4;
- }
- }
- // updates the labels of the other attributes
- Attribute attr = cattrs;
- while (attr != null) {
- Label[] labels = attr.getLabels();
- if (labels != null) {
- for (i = labels.length - 1; i >= 0; --i) {
- getNewOffset(allIndexes, allSizes, labels[i]);
- }
- }
- attr = attr.next;
- }
-
- // replaces old bytecodes with new ones
- code = newCode;
- }
-
- /**
- * Reads an unsigned short value in the given byte array.
- *
- * @param b
- * a byte array.
- * @param index
- * the start index of the value to be read.
- * @return the read value.
- */
- static int readUnsignedShort(final byte[] b, final int index) {
- return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
- }
-
- /**
- * Reads a signed short value in the given byte array.
- *
- * @param b
- * a byte array.
- * @param index
- * the start index of the value to be read.
- * @return the read value.
- */
- static short readShort(final byte[] b, final int index) {
- return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
- }
-
- /**
- * Reads a signed int value in the given byte array.
- *
- * @param b
- * a byte array.
- * @param index
- * the start index of the value to be read.
- * @return the read value.
- */
- static int readInt(final byte[] b, final int index) {
- return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)
- | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
- }
-
- /**
- * Writes a short value in the given byte array.
- *
- * @param b
- * a byte array.
- * @param index
- * where the first byte of the short value must be written.
- * @param s
- * the value to be written in the given byte array.
- */
- static void writeShort(final byte[] b, final int index, final int s) {
- b[index] = (byte) (s >>> 8);
- b[index + 1] = (byte) s;
- }
-
- /**
- * Computes the future value of a bytecode offset.
- * <p>
- * Note: it is possible to have several entries for the same instruction in
- * the <tt>indexes</tt> and <tt>sizes</tt>: two entries (index=a,size=b) and
- * (index=a,size=b') are equivalent to a single entry (index=a,size=b+b').
- *
- * @param indexes
- * current positions of the instructions to be resized. Each
- * instruction must be designated by the index of its <i>last</i>
- * byte, plus one (or, in other words, by the index of the
- * <i>first</i> byte of the <i>next</i> instruction).
- * @param sizes
- * the number of bytes to be <i>added</i> to the above
- * instructions. More precisely, for each i < <tt>len</tt>,
- * <tt>sizes</tt>[i] bytes will be added at the end of the
- * instruction designated by <tt>indexes</tt>[i] or, if
- * <tt>sizes</tt>[i] is negative, the <i>last</i> |
- * <tt>sizes[i]</tt>| bytes of the instruction will be removed
- * (the instruction size <i>must not</i> become negative or
- * null).
- * @param begin
- * index of the first byte of the source instruction.
- * @param end
- * index of the first byte of the target instruction.
- * @return the future value of the given bytecode offset.
- */
- static int getNewOffset(final int[] indexes, final int[] sizes,
- final int begin, final int end) {
- int offset = end - begin;
- for (int i = 0; i < indexes.length; ++i) {
- if (begin < indexes[i] && indexes[i] <= end) {
- // forward jump
- offset += sizes[i];
- } else if (end < indexes[i] && indexes[i] <= begin) {
- // backward jump
- offset -= sizes[i];
- }
- }
- return offset;
- }
-
- /**
- * Updates the offset of the given label.
- *
- * @param indexes
- * current positions of the instructions to be resized. Each
- * instruction must be designated by the index of its <i>last</i>
- * byte, plus one (or, in other words, by the index of the
- * <i>first</i> byte of the <i>next</i> instruction).
- * @param sizes
- * the number of bytes to be <i>added</i> to the above
- * instructions. More precisely, for each i < <tt>len</tt>,
- * <tt>sizes</tt>[i] bytes will be added at the end of the
- * instruction designated by <tt>indexes</tt>[i] or, if
- * <tt>sizes</tt>[i] is negative, the <i>last</i> |
- * <tt>sizes[i]</tt>| bytes of the instruction will be removed
- * (the instruction size <i>must not</i> become negative or
- * null).
- * @param label
- * the label whose offset must be updated.
- */
- static void getNewOffset(final int[] indexes, final int[] sizes,
- final Label label) {
- if ((label.status & Label.RESIZED) == 0) {
- label.position = getNewOffset(indexes, sizes, 0, label.position);
- label.status |= Label.RESIZED;
- }
- }
-}
diff --git a/src/jvm/clojure/asm/Opcodes.java b/src/jvm/clojure/asm/Opcodes.java
deleted file mode 100644
index b126807..0000000
--- a/src/jvm/clojure/asm/Opcodes.java
+++ /dev/null
@@ -1,358 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-/**
- * Defines the JVM opcodes, access flags and array type codes. This interface
- * does not define all the JVM opcodes because some opcodes are automatically
- * handled. For example, the xLOAD and xSTORE opcodes are automatically replaced
- * by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n
- * opcodes are therefore not defined in this interface. Likewise for LDC,
- * automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and
- * JSR_W.
- *
- * @author Eric Bruneton
- * @author Eugene Kuleshov
- */
-public interface Opcodes {
-
- // ASM API versions
-
- int ASM4 = 4 << 16 | 0 << 8 | 0;
-
- // versions
-
- int V1_1 = 3 << 16 | 45;
- int V1_2 = 0 << 16 | 46;
- int V1_3 = 0 << 16 | 47;
- int V1_4 = 0 << 16 | 48;
- int V1_5 = 0 << 16 | 49;
- int V1_6 = 0 << 16 | 50;
- int V1_7 = 0 << 16 | 51;
-
- // access flags
-
- int ACC_PUBLIC = 0x0001; // class, field, method
- int ACC_PRIVATE = 0x0002; // class, field, method
- int ACC_PROTECTED = 0x0004; // class, field, method
- int ACC_STATIC = 0x0008; // field, method
- int ACC_FINAL = 0x0010; // class, field, method
- int ACC_SUPER = 0x0020; // class
- int ACC_SYNCHRONIZED = 0x0020; // method
- int ACC_VOLATILE = 0x0040; // field
- int ACC_BRIDGE = 0x0040; // method
- int ACC_VARARGS = 0x0080; // method
- int ACC_TRANSIENT = 0x0080; // field
- int ACC_NATIVE = 0x0100; // method
- int ACC_INTERFACE = 0x0200; // class
- int ACC_ABSTRACT = 0x0400; // class, method
- int ACC_STRICT = 0x0800; // method
- int ACC_SYNTHETIC = 0x1000; // class, field, method
- int ACC_ANNOTATION = 0x2000; // class
- int ACC_ENUM = 0x4000; // class(?) field inner
-
- // ASM specific pseudo access flags
-
- int ACC_DEPRECATED = 0x20000; // class, field, method
-
- // types for NEWARRAY
-
- int T_BOOLEAN = 4;
- int T_CHAR = 5;
- int T_FLOAT = 6;
- int T_DOUBLE = 7;
- int T_BYTE = 8;
- int T_SHORT = 9;
- int T_INT = 10;
- int T_LONG = 11;
-
- // tags for Handle
-
- int H_GETFIELD = 1;
- int H_GETSTATIC = 2;
- int H_PUTFIELD = 3;
- int H_PUTSTATIC = 4;
- int H_INVOKEVIRTUAL = 5;
- int H_INVOKESTATIC = 6;
- int H_INVOKESPECIAL = 7;
- int H_NEWINVOKESPECIAL = 8;
- int H_INVOKEINTERFACE = 9;
-
- // stack map frame types
-
- /**
- * Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}.
- */
- int F_NEW = -1;
-
- /**
- * Represents a compressed frame with complete frame data.
- */
- int F_FULL = 0;
-
- /**
- * Represents a compressed frame where locals are the same as the locals in
- * the previous frame, except that additional 1-3 locals are defined, and
- * with an empty stack.
- */
- int F_APPEND = 1;
-
- /**
- * Represents a compressed frame where locals are the same as the locals in
- * the previous frame, except that the last 1-3 locals are absent and with
- * an empty stack.
- */
- int F_CHOP = 2;
-
- /**
- * Represents a compressed frame with exactly the same locals as the
- * previous frame and with an empty stack.
- */
- int F_SAME = 3;
-
- /**
- * Represents a compressed frame with exactly the same locals as the
- * previous frame and with a single value on the stack.
- */
- int F_SAME1 = 4;
-
- Integer TOP = new Integer(0);
- Integer INTEGER = new Integer(1);
- Integer FLOAT = new Integer(2);
- Integer DOUBLE = new Integer(3);
- Integer LONG = new Integer(4);
- Integer NULL = new Integer(5);
- Integer UNINITIALIZED_THIS = new Integer(6);
-
- // opcodes // visit method (- = idem)
-
- int NOP = 0; // visitInsn
- int ACONST_NULL = 1; // -
- int ICONST_M1 = 2; // -
- int ICONST_0 = 3; // -
- int ICONST_1 = 4; // -
- int ICONST_2 = 5; // -
- int ICONST_3 = 6; // -
- int ICONST_4 = 7; // -
- int ICONST_5 = 8; // -
- int LCONST_0 = 9; // -
- int LCONST_1 = 10; // -
- int FCONST_0 = 11; // -
- int FCONST_1 = 12; // -
- int FCONST_2 = 13; // -
- int DCONST_0 = 14; // -
- int DCONST_1 = 15; // -
- int BIPUSH = 16; // visitIntInsn
- int SIPUSH = 17; // -
- int LDC = 18; // visitLdcInsn
- // int LDC_W = 19; // -
- // int LDC2_W = 20; // -
- int ILOAD = 21; // visitVarInsn
- int LLOAD = 22; // -
- int FLOAD = 23; // -
- int DLOAD = 24; // -
- int ALOAD = 25; // -
- // int ILOAD_0 = 26; // -
- // int ILOAD_1 = 27; // -
- // int ILOAD_2 = 28; // -
- // int ILOAD_3 = 29; // -
- // int LLOAD_0 = 30; // -
- // int LLOAD_1 = 31; // -
- // int LLOAD_2 = 32; // -
- // int LLOAD_3 = 33; // -
- // int FLOAD_0 = 34; // -
- // int FLOAD_1 = 35; // -
- // int FLOAD_2 = 36; // -
- // int FLOAD_3 = 37; // -
- // int DLOAD_0 = 38; // -
- // int DLOAD_1 = 39; // -
- // int DLOAD_2 = 40; // -
- // int DLOAD_3 = 41; // -
- // int ALOAD_0 = 42; // -
- // int ALOAD_1 = 43; // -
- // int ALOAD_2 = 44; // -
- // int ALOAD_3 = 45; // -
- int IALOAD = 46; // visitInsn
- int LALOAD = 47; // -
- int FALOAD = 48; // -
- int DALOAD = 49; // -
- int AALOAD = 50; // -
- int BALOAD = 51; // -
- int CALOAD = 52; // -
- int SALOAD = 53; // -
- int ISTORE = 54; // visitVarInsn
- int LSTORE = 55; // -
- int FSTORE = 56; // -
- int DSTORE = 57; // -
- int ASTORE = 58; // -
- // int ISTORE_0 = 59; // -
- // int ISTORE_1 = 60; // -
- // int ISTORE_2 = 61; // -
- // int ISTORE_3 = 62; // -
- // int LSTORE_0 = 63; // -
- // int LSTORE_1 = 64; // -
- // int LSTORE_2 = 65; // -
- // int LSTORE_3 = 66; // -
- // int FSTORE_0 = 67; // -
- // int FSTORE_1 = 68; // -
- // int FSTORE_2 = 69; // -
- // int FSTORE_3 = 70; // -
- // int DSTORE_0 = 71; // -
- // int DSTORE_1 = 72; // -
- // int DSTORE_2 = 73; // -
- // int DSTORE_3 = 74; // -
- // int ASTORE_0 = 75; // -
- // int ASTORE_1 = 76; // -
- // int ASTORE_2 = 77; // -
- // int ASTORE_3 = 78; // -
- int IASTORE = 79; // visitInsn
- int LASTORE = 80; // -
- int FASTORE = 81; // -
- int DASTORE = 82; // -
- int AASTORE = 83; // -
- int BASTORE = 84; // -
- int CASTORE = 85; // -
- int SASTORE = 86; // -
- int POP = 87; // -
- int POP2 = 88; // -
- int DUP = 89; // -
- int DUP_X1 = 90; // -
- int DUP_X2 = 91; // -
- int DUP2 = 92; // -
- int DUP2_X1 = 93; // -
- int DUP2_X2 = 94; // -
- int SWAP = 95; // -
- int IADD = 96; // -
- int LADD = 97; // -
- int FADD = 98; // -
- int DADD = 99; // -
- int ISUB = 100; // -
- int LSUB = 101; // -
- int FSUB = 102; // -
- int DSUB = 103; // -
- int IMUL = 104; // -
- int LMUL = 105; // -
- int FMUL = 106; // -
- int DMUL = 107; // -
- int IDIV = 108; // -
- int LDIV = 109; // -
- int FDIV = 110; // -
- int DDIV = 111; // -
- int IREM = 112; // -
- int LREM = 113; // -
- int FREM = 114; // -
- int DREM = 115; // -
- int INEG = 116; // -
- int LNEG = 117; // -
- int FNEG = 118; // -
- int DNEG = 119; // -
- int ISHL = 120; // -
- int LSHL = 121; // -
- int ISHR = 122; // -
- int LSHR = 123; // -
- int IUSHR = 124; // -
- int LUSHR = 125; // -
- int IAND = 126; // -
- int LAND = 127; // -
- int IOR = 128; // -
- int LOR = 129; // -
- int IXOR = 130; // -
- int LXOR = 131; // -
- int IINC = 132; // visitIincInsn
- int I2L = 133; // visitInsn
- int I2F = 134; // -
- int I2D = 135; // -
- int L2I = 136; // -
- int L2F = 137; // -
- int L2D = 138; // -
- int F2I = 139; // -
- int F2L = 140; // -
- int F2D = 141; // -
- int D2I = 142; // -
- int D2L = 143; // -
- int D2F = 144; // -
- int I2B = 145; // -
- int I2C = 146; // -
- int I2S = 147; // -
- int LCMP = 148; // -
- int FCMPL = 149; // -
- int FCMPG = 150; // -
- int DCMPL = 151; // -
- int DCMPG = 152; // -
- int IFEQ = 153; // visitJumpInsn
- int IFNE = 154; // -
- int IFLT = 155; // -
- int IFGE = 156; // -
- int IFGT = 157; // -
- int IFLE = 158; // -
- int IF_ICMPEQ = 159; // -
- int IF_ICMPNE = 160; // -
- int IF_ICMPLT = 161; // -
- int IF_ICMPGE = 162; // -
- int IF_ICMPGT = 163; // -
- int IF_ICMPLE = 164; // -
- int IF_ACMPEQ = 165; // -
- int IF_ACMPNE = 166; // -
- int GOTO = 167; // -
- int JSR = 168; // -
- int RET = 169; // visitVarInsn
- int TABLESWITCH = 170; // visiTableSwitchInsn
- int LOOKUPSWITCH = 171; // visitLookupSwitch
- int IRETURN = 172; // visitInsn
- int LRETURN = 173; // -
- int FRETURN = 174; // -
- int DRETURN = 175; // -
- int ARETURN = 176; // -
- int RETURN = 177; // -
- int GETSTATIC = 178; // visitFieldInsn
- int PUTSTATIC = 179; // -
- int GETFIELD = 180; // -
- int PUTFIELD = 181; // -
- int INVOKEVIRTUAL = 182; // visitMethodInsn
- int INVOKESPECIAL = 183; // -
- int INVOKESTATIC = 184; // -
- int INVOKEINTERFACE = 185; // -
- int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsn
- int NEW = 187; // visitTypeInsn
- int NEWARRAY = 188; // visitIntInsn
- int ANEWARRAY = 189; // visitTypeInsn
- int ARRAYLENGTH = 190; // visitInsn
- int ATHROW = 191; // -
- int CHECKCAST = 192; // visitTypeInsn
- int INSTANCEOF = 193; // -
- int MONITORENTER = 194; // visitInsn
- int MONITOREXIT = 195; // -
- // int WIDE = 196; // NOT VISITED
- int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
- int IFNULL = 198; // visitJumpInsn
- int IFNONNULL = 199; // -
- // int GOTO_W = 200; // -
- // int JSR_W = 201; // -
-}
diff --git a/src/jvm/clojure/asm/Type.java b/src/jvm/clojure/asm/Type.java
deleted file mode 100644
index 31db08d..0000000
--- a/src/jvm/clojure/asm/Type.java
+++ /dev/null
@@ -1,895 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-
-/**
- * A Java field or method type. This class can be used to make it easier to
- * manipulate type and method descriptors.
- *
- * @author Eric Bruneton
- * @author Chris Nokleberg
- */
-public class Type {
-
- /**
- * The sort of the <tt>void</tt> type. See {@link #getSort getSort}.
- */
- public static final int VOID = 0;
-
- /**
- * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}.
- */
- public static final int BOOLEAN = 1;
-
- /**
- * The sort of the <tt>char</tt> type. See {@link #getSort getSort}.
- */
- public static final int CHAR = 2;
-
- /**
- * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}.
- */
- public static final int BYTE = 3;
-
- /**
- * The sort of the <tt>short</tt> type. See {@link #getSort getSort}.
- */
- public static final int SHORT = 4;
-
- /**
- * The sort of the <tt>int</tt> type. See {@link #getSort getSort}.
- */
- public static final int INT = 5;
-
- /**
- * The sort of the <tt>float</tt> type. See {@link #getSort getSort}.
- */
- public static final int FLOAT = 6;
-
- /**
- * The sort of the <tt>long</tt> type. See {@link #getSort getSort}.
- */
- public static final int LONG = 7;
-
- /**
- * The sort of the <tt>double</tt> type. See {@link #getSort getSort}.
- */
- public static final int DOUBLE = 8;
-
- /**
- * The sort of array reference types. See {@link #getSort getSort}.
- */
- public static final int ARRAY = 9;
-
- /**
- * The sort of object reference types. See {@link #getSort getSort}.
- */
- public static final int OBJECT = 10;
-
- /**
- * The sort of method types. See {@link #getSort getSort}.
- */
- public static final int METHOD = 11;
-
- /**
- * The <tt>void</tt> type.
- */
- public static final Type VOID_TYPE = new Type(VOID, null, ('V' << 24)
- | (5 << 16) | (0 << 8) | 0, 1);
-
- /**
- * The <tt>boolean</tt> type.
- */
- public static final Type BOOLEAN_TYPE = new Type(BOOLEAN, null, ('Z' << 24)
- | (0 << 16) | (5 << 8) | 1, 1);
-
- /**
- * The <tt>char</tt> type.
- */
- public static final Type CHAR_TYPE = new Type(CHAR, null, ('C' << 24)
- | (0 << 16) | (6 << 8) | 1, 1);
-
- /**
- * The <tt>byte</tt> type.
- */
- public static final Type BYTE_TYPE = new Type(BYTE, null, ('B' << 24)
- | (0 << 16) | (5 << 8) | 1, 1);
-
- /**
- * The <tt>short</tt> type.
- */
- public static final Type SHORT_TYPE = new Type(SHORT, null, ('S' << 24)
- | (0 << 16) | (7 << 8) | 1, 1);
-
- /**
- * The <tt>int</tt> type.
- */
- public static final Type INT_TYPE = new Type(INT, null, ('I' << 24)
- | (0 << 16) | (0 << 8) | 1, 1);
-
- /**
- * The <tt>float</tt> type.
- */
- public static final Type FLOAT_TYPE = new Type(FLOAT, null, ('F' << 24)
- | (2 << 16) | (2 << 8) | 1, 1);
-
- /**
- * The <tt>long</tt> type.
- */
- public static final Type LONG_TYPE = new Type(LONG, null, ('J' << 24)
- | (1 << 16) | (1 << 8) | 2, 1);
-
- /**
- * The <tt>double</tt> type.
- */
- public static final Type DOUBLE_TYPE = new Type(DOUBLE, null, ('D' << 24)
- | (3 << 16) | (3 << 8) | 2, 1);
-
- // ------------------------------------------------------------------------
- // Fields
- // ------------------------------------------------------------------------
-
- /**
- * The sort of this Java type.
- */
- private final int sort;
-
- /**
- * A buffer containing the internal name of this Java type. This field is
- * only used for reference types.
- */
- private final char[] buf;
-
- /**
- * The offset of the internal name of this Java type in {@link #buf buf} or,
- * for primitive types, the size, descriptor and getOpcode offsets for this
- * type (byte 0 contains the size, byte 1 the descriptor, byte 2 the offset
- * for IALOAD or IASTORE, byte 3 the offset for all other instructions).
- */
- private final int off;
-
- /**
- * The length of the internal name of this Java type.
- */
- private final int len;
-
- // ------------------------------------------------------------------------
- // Constructors
- // ------------------------------------------------------------------------
-
- /**
- * Constructs a reference type.
- *
- * @param sort
- * the sort of the reference type to be constructed.
- * @param buf
- * a buffer containing the descriptor of the previous type.
- * @param off
- * the offset of this descriptor in the previous buffer.
- * @param len
- * the length of this descriptor.
- */
- private Type(final int sort, final char[] buf, final int off, final int len) {
- this.sort = sort;
- this.buf = buf;
- this.off = off;
- this.len = len;
- }
-
- /**
- * Returns the Java type corresponding to the given type descriptor.
- *
- * @param typeDescriptor
- * a field or method type descriptor.
- * @return the Java type corresponding to the given type descriptor.
- */
- public static Type getType(final String typeDescriptor) {
- return getType(typeDescriptor.toCharArray(), 0);
- }
-
- /**
- * Returns the Java type corresponding to the given internal name.
- *
- * @param internalName
- * an internal name.
- * @return the Java type corresponding to the given internal name.
- */
- public static Type getObjectType(final String internalName) {
- char[] buf = internalName.toCharArray();
- return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length);
- }
-
- /**
- * Returns the Java type corresponding to the given method descriptor.
- * Equivalent to <code>Type.getType(methodDescriptor)</code>.
- *
- * @param methodDescriptor
- * a method descriptor.
- * @return the Java type corresponding to the given method descriptor.
- */
- public static Type getMethodType(final String methodDescriptor) {
- return getType(methodDescriptor.toCharArray(), 0);
- }
-
- /**
- * Returns the Java method type corresponding to the given argument and
- * return types.
- *
- * @param returnType
- * the return type of the method.
- * @param argumentTypes
- * the argument types of the method.
- * @return the Java type corresponding to the given argument and return
- * types.
- */
- public static Type getMethodType(final Type returnType,
- final Type... argumentTypes) {
- return getType(getMethodDescriptor(returnType, argumentTypes));
- }
-
- /**
- * Returns the Java type corresponding to the given class.
- *
- * @param c
- * a class.
- * @return the Java type corresponding to the given class.
- */
- public static Type getType(final Class<?> c) {
- if (c.isPrimitive()) {
- if (c == Integer.TYPE) {
- return INT_TYPE;
- } else if (c == Void.TYPE) {
- return VOID_TYPE;
- } else if (c == Boolean.TYPE) {
- return BOOLEAN_TYPE;
- } else if (c == Byte.TYPE) {
- return BYTE_TYPE;
- } else if (c == Character.TYPE) {
- return CHAR_TYPE;
- } else if (c == Short.TYPE) {
- return SHORT_TYPE;
- } else if (c == Double.TYPE) {
- return DOUBLE_TYPE;
- } else if (c == Float.TYPE) {
- return FLOAT_TYPE;
- } else /* if (c == Long.TYPE) */{
- return LONG_TYPE;
- }
- } else {
- return getType(getDescriptor(c));
- }
- }
-
- /**
- * Returns the Java method type corresponding to the given constructor.
- *
- * @param c
- * a {@link Constructor Constructor} object.
- * @return the Java method type corresponding to the given constructor.
- */
- public static Type getType(final Constructor<?> c) {
- return getType(getConstructorDescriptor(c));
- }
-
- /**
- * Returns the Java method type corresponding to the given method.
- *
- * @param m
- * a {@link Method Method} object.
- * @return the Java method type corresponding to the given method.
- */
- public static Type getType(final Method m) {
- return getType(getMethodDescriptor(m));
- }
-
- /**
- * Returns the Java types corresponding to the argument types of the given
- * method descriptor.
- *
- * @param methodDescriptor
- * a method descriptor.
- * @return the Java types corresponding to the argument types of the given
- * method descriptor.
- */
- public static Type[] getArgumentTypes(final String methodDescriptor) {
- char[] buf = methodDescriptor.toCharArray();
- int off = 1;
- int size = 0;
- while (true) {
- char car = buf[off++];
- if (car == ')') {
- break;
- } else if (car == 'L') {
- while (buf[off++] != ';') {
- }
- ++size;
- } else if (car != '[') {
- ++size;
- }
- }
- Type[] args = new Type[size];
- off = 1;
- size = 0;
- while (buf[off] != ')') {
- args[size] = getType(buf, off);
- off += args[size].len + (args[size].sort == OBJECT ? 2 : 0);
- size += 1;
- }
- return args;
- }
-
- /**
- * Returns the Java types corresponding to the argument types of the given
- * method.
- *
- * @param method
- * a method.
- * @return the Java types corresponding to the argument types of the given
- * method.
- */
- public static Type[] getArgumentTypes(final Method method) {
- Class<?>[] classes = method.getParameterTypes();
- Type[] types = new Type[classes.length];
- for (int i = classes.length - 1; i >= 0; --i) {
- types[i] = getType(classes[i]);
- }
- return types;
- }
-
- /**
- * Returns the Java type corresponding to the return type of the given
- * method descriptor.
- *
- * @param methodDescriptor
- * a method descriptor.
- * @return the Java type corresponding to the return type of the given
- * method descriptor.
- */
- public static Type getReturnType(final String methodDescriptor) {
- char[] buf = methodDescriptor.toCharArray();
- return getType(buf, methodDescriptor.indexOf(')') + 1);
- }
-
- /**
- * Returns the Java type corresponding to the return type of the given
- * method.
- *
- * @param method
- * a method.
- * @return the Java type corresponding to the return type of the given
- * method.
- */
- public static Type getReturnType(final Method method) {
- return getType(method.getReturnType());
- }
-
- /**
- * Computes the size of the arguments and of the return value of a method.
- *
- * @param desc
- * the descriptor of a method.
- * @return the size of the arguments of the method (plus one for the
- * implicit this argument), argSize, and the size of its return
- * value, retSize, packed into a single int i =
- * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal to
- * <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>).
- */
- public static int getArgumentsAndReturnSizes(final String desc) {
- int n = 1;
- int c = 1;
- while (true) {
- char car = desc.charAt(c++);
- if (car == ')') {
- car = desc.charAt(c);
- return n << 2
- | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1));
- } else if (car == 'L') {
- while (desc.charAt(c++) != ';') {
- }
- n += 1;
- } else if (car == '[') {
- while ((car = desc.charAt(c)) == '[') {
- ++c;
- }
- if (car == 'D' || car == 'J') {
- n -= 1;
- }
- } else if (car == 'D' || car == 'J') {
- n += 2;
- } else {
- n += 1;
- }
- }
- }
-
- /**
- * Returns the Java type corresponding to the given type descriptor. For
- * method descriptors, buf is supposed to contain nothing more than the
- * descriptor itself.
- *
- * @param buf
- * a buffer containing a type descriptor.
- * @param off
- * the offset of this descriptor in the previous buffer.
- * @return the Java type corresponding to the given type descriptor.
- */
- private static Type getType(final char[] buf, final int off) {
- int len;
- switch (buf[off]) {
- case 'V':
- return VOID_TYPE;
- case 'Z':
- return BOOLEAN_TYPE;
- case 'C':
- return CHAR_TYPE;
- case 'B':
- return BYTE_TYPE;
- case 'S':
- return SHORT_TYPE;
- case 'I':
- return INT_TYPE;
- case 'F':
- return FLOAT_TYPE;
- case 'J':
- return LONG_TYPE;
- case 'D':
- return DOUBLE_TYPE;
- case '[':
- len = 1;
- while (buf[off + len] == '[') {
- ++len;
- }
- if (buf[off + len] == 'L') {
- ++len;
- while (buf[off + len] != ';') {
- ++len;
- }
- }
- return new Type(ARRAY, buf, off, len + 1);
- case 'L':
- len = 1;
- while (buf[off + len] != ';') {
- ++len;
- }
- return new Type(OBJECT, buf, off + 1, len - 1);
- // case '(':
- default:
- return new Type(METHOD, buf, off, buf.length - off);
- }
- }
-
- // ------------------------------------------------------------------------
- // Accessors
- // ------------------------------------------------------------------------
-
- /**
- * Returns the sort of this Java type.
- *
- * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR},
- * {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT},
- * {@link #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE},
- * {@link #ARRAY ARRAY}, {@link #OBJECT OBJECT} or {@link #METHOD
- * METHOD}.
- */
- public int getSort() {
- return sort;
- }
-
- /**
- * Returns the number of dimensions of this array type. This method should
- * only be used for an array type.
- *
- * @return the number of dimensions of this array type.
- */
- public int getDimensions() {
- int i = 1;
- while (buf[off + i] == '[') {
- ++i;
- }
- return i;
- }
-
- /**
- * Returns the type of the elements of this array type. This method should
- * only be used for an array type.
- *
- * @return Returns the type of the elements of this array type.
- */
- public Type getElementType() {
- return getType(buf, off + getDimensions());
- }
-
- /**
- * Returns the binary name of the class corresponding to this type. This
- * method must not be used on method types.
- *
- * @return the binary name of the class corresponding to this type.
- */
- public String getClassName() {
- switch (sort) {
- case VOID:
- return "void";
- case BOOLEAN:
- return "boolean";
- case CHAR:
- return "char";
- case BYTE:
- return "byte";
- case SHORT:
- return "short";
- case INT:
- return "int";
- case FLOAT:
- return "float";
- case LONG:
- return "long";
- case DOUBLE:
- return "double";
- case ARRAY:
- StringBuffer b = new StringBuffer(getElementType().getClassName());
- for (int i = getDimensions(); i > 0; --i) {
- b.append("[]");
- }
- return b.toString();
- case OBJECT:
- return new String(buf, off, len).replace('/', '.');
- default:
- return null;
- }
- }
-
- /**
- * Returns the internal name of the class corresponding to this object or
- * array type. The internal name of a class is its fully qualified name (as
- * returned by Class.getName(), where '.' are replaced by '/'. This method
- * should only be used for an object or array type.
- *
- * @return the internal name of the class corresponding to this object type.
- */
- public String getInternalName() {
- return new String(buf, off, len);
- }
-
- /**
- * Returns the argument types of methods of this type. This method should
- * only be used for method types.
- *
- * @return the argument types of methods of this type.
- */
- public Type[] getArgumentTypes() {
- return getArgumentTypes(getDescriptor());
- }
-
- /**
- * Returns the return type of methods of this type. This method should only
- * be used for method types.
- *
- * @return the return type of methods of this type.
- */
- public Type getReturnType() {
- return getReturnType(getDescriptor());
- }
-
- /**
- * Returns the size of the arguments and of the return value of methods of
- * this type. This method should only be used for method types.
- *
- * @return the size of the arguments (plus one for the implicit this
- * argument), argSize, and the size of the return value, retSize,
- * packed into a single int i = <tt>(argSize << 2) | retSize</tt>
- * (argSize is therefore equal to <tt>i >> 2</tt>, and retSize to
- * <tt>i & 0x03</tt>).
- */
- public int getArgumentsAndReturnSizes() {
- return getArgumentsAndReturnSizes(getDescriptor());
- }
-
- // ------------------------------------------------------------------------
- // Conversion to type descriptors
- // ------------------------------------------------------------------------
-
- /**
- * Returns the descriptor corresponding to this Java type.
- *
- * @return the descriptor corresponding to this Java type.
- */
- public String getDescriptor() {
- StringBuffer buf = new StringBuffer();
- getDescriptor(buf);
- return buf.toString();
- }
-
- /**
- * Returns the descriptor corresponding to the given argument and return
- * types.
- *
- * @param returnType
- * the return type of the method.
- * @param argumentTypes
- * the argument types of the method.
- * @return the descriptor corresponding to the given argument and return
- * types.
- */
- public static String getMethodDescriptor(final Type returnType,
- final Type... argumentTypes) {
- StringBuffer buf = new StringBuffer();
- buf.append('(');
- for (int i = 0; i < argumentTypes.length; ++i) {
- argumentTypes[i].getDescriptor(buf);
- }
- buf.append(')');
- returnType.getDescriptor(buf);
- return buf.toString();
- }
-
- /**
- * Appends the descriptor corresponding to this Java type to the given
- * string buffer.
- *
- * @param buf
- * the string buffer to which the descriptor must be appended.
- */
- private void getDescriptor(final StringBuffer buf) {
- if (this.buf == null) {
- // descriptor is in byte 3 of 'off' for primitive types (buf ==
- // null)
- buf.append((char) ((off & 0xFF000000) >>> 24));
- } else if (sort == OBJECT) {
- buf.append('L');
- buf.append(this.buf, off, len);
- buf.append(';');
- } else { // sort == ARRAY || sort == METHOD
- buf.append(this.buf, off, len);
- }
- }
-
- // ------------------------------------------------------------------------
- // Direct conversion from classes to type descriptors,
- // without intermediate Type objects
- // ------------------------------------------------------------------------
-
- /**
- * Returns the internal name of the given class. The internal name of a
- * class is its fully qualified name, as returned by Class.getName(), where
- * '.' are replaced by '/'.
- *
- * @param c
- * an object or array class.
- * @return the internal name of the given class.
- */
- public static String getInternalName(final Class<?> c) {
- return c.getName().replace('.', '/');
- }
-
- /**
- * Returns the descriptor corresponding to the given Java type.
- *
- * @param c
- * an object class, a primitive class or an array class.
- * @return the descriptor corresponding to the given class.
- */
- public static String getDescriptor(final Class<?> c) {
- StringBuffer buf = new StringBuffer();
- getDescriptor(buf, c);
- return buf.toString();
- }
-
- /**
- * Returns the descriptor corresponding to the given constructor.
- *
- * @param c
- * a {@link Constructor Constructor} object.
- * @return the descriptor of the given constructor.
- */
- public static String getConstructorDescriptor(final Constructor<?> c) {
- Class<?>[] parameters = c.getParameterTypes();
- StringBuffer buf = new StringBuffer();
- buf.append('(');
- for (int i = 0; i < parameters.length; ++i) {
- getDescriptor(buf, parameters[i]);
- }
- return buf.append(")V").toString();
- }
-
- /**
- * Returns the descriptor corresponding to the given method.
- *
- * @param m
- * a {@link Method Method} object.
- * @return the descriptor of the given method.
- */
- public static String getMethodDescriptor(final Method m) {
- Class<?>[] parameters = m.getParameterTypes();
- StringBuffer buf = new StringBuffer();
- buf.append('(');
- for (int i = 0; i < parameters.length; ++i) {
- getDescriptor(buf, parameters[i]);
- }
- buf.append(')');
- getDescriptor(buf, m.getReturnType());
- return buf.toString();
- }
-
- /**
- * Appends the descriptor of the given class to the given string buffer.
- *
- * @param buf
- * the string buffer to which the descriptor must be appended.
- * @param c
- * the class whose descriptor must be computed.
- */
- private static void getDescriptor(final StringBuffer buf, final Class<?> c) {
- Class<?> d = c;
- while (true) {
- if (d.isPrimitive()) {
- char car;
- if (d == Integer.TYPE) {
- car = 'I';
- } else if (d == Void.TYPE) {
- car = 'V';
- } else if (d == Boolean.TYPE) {
- car = 'Z';
- } else if (d == Byte.TYPE) {
- car = 'B';
- } else if (d == Character.TYPE) {
- car = 'C';
- } else if (d == Short.TYPE) {
- car = 'S';
- } else if (d == Double.TYPE) {
- car = 'D';
- } else if (d == Float.TYPE) {
- car = 'F';
- } else /* if (d == Long.TYPE) */{
- car = 'J';
- }
- buf.append(car);
- return;
- } else if (d.isArray()) {
- buf.append('[');
- d = d.getComponentType();
- } else {
- buf.append('L');
- String name = d.getName();
- int len = name.length();
- for (int i = 0; i < len; ++i) {
- char car = name.charAt(i);
- buf.append(car == '.' ? '/' : car);
- }
- buf.append(';');
- return;
- }
- }
- }
-
- // ------------------------------------------------------------------------
- // Corresponding size and opcodes
- // ------------------------------------------------------------------------
-
- /**
- * Returns the size of values of this type. This method must not be used for
- * method types.
- *
- * @return the size of values of this type, i.e., 2 for <tt>long</tt> and
- * <tt>double</tt>, 0 for <tt>void</tt> and 1 otherwise.
- */
- public int getSize() {
- // the size is in byte 0 of 'off' for primitive types (buf == null)
- return buf == null ? (off & 0xFF) : 1;
- }
-
- /**
- * Returns a JVM instruction opcode adapted to this Java type. This method
- * must not be used for method types.
- *
- * @param opcode
- * a JVM instruction opcode. This opcode must be one of ILOAD,
- * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG,
- * ISHL, ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
- * @return an opcode that is similar to the given opcode, but adapted to
- * this Java type. For example, if this type is <tt>float</tt> and
- * <tt>opcode</tt> is IRETURN, this method returns FRETURN.
- */
- public int getOpcode(final int opcode) {
- if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) {
- // the offset for IALOAD or IASTORE is in byte 1 of 'off' for
- // primitive types (buf == null)
- return opcode + (buf == null ? (off & 0xFF00) >> 8 : 4);
- } else {
- // the offset for other instructions is in byte 2 of 'off' for
- // primitive types (buf == null)
- return opcode + (buf == null ? (off & 0xFF0000) >> 16 : 4);
- }
- }
-
- // ------------------------------------------------------------------------
- // Equals, hashCode and toString
- // ------------------------------------------------------------------------
-
- /**
- * Tests if the given object is equal to this type.
- *
- * @param o
- * the object to be compared to this type.
- * @return <tt>true</tt> if the given object is equal to this type.
- */
- @Override
- public boolean equals(final Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof Type)) {
- return false;
- }
- Type t = (Type) o;
- if (sort != t.sort) {
- return false;
- }
- if (sort >= ARRAY) {
- if (len != t.len) {
- return false;
- }
- for (int i = off, j = t.off, end = i + len; i < end; i++, j++) {
- if (buf[i] != t.buf[j]) {
- return false;
- }
- }
- }
- return true;
- }
-
- /**
- * Returns a hash code value for this type.
- *
- * @return a hash code value for this type.
- */
- @Override
- public int hashCode() {
- int hc = 13 * sort;
- if (sort >= ARRAY) {
- for (int i = off, end = i + len; i < end; i++) {
- hc = 17 * (hc + buf[i]);
- }
- }
- return hc;
- }
-
- /**
- * Returns a string representation of this type.
- *
- * @return the descriptor of this type.
- */
- @Override
- public String toString() {
- return getDescriptor();
- }
-}
diff --git a/src/jvm/clojure/asm/commons/AdviceAdapter.java b/src/jvm/clojure/asm/commons/AdviceAdapter.java
deleted file mode 100644
index 8ec38d2..0000000
--- a/src/jvm/clojure/asm/commons/AdviceAdapter.java
+++ /dev/null
@@ -1,625 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm.commons;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import clojure.asm.Handle;
-import clojure.asm.Label;
-import clojure.asm.MethodVisitor;
-import clojure.asm.Opcodes;
-import clojure.asm.Type;
-
-/**
- * A {@link clojure.asm.MethodVisitor} to insert before, after and around
- * advices in methods and constructors.
- * <p>
- * The behavior for constructors is like this:
- * <ol>
- *
- * <li>as long as the INVOKESPECIAL for the object initialization has not been
- * reached, every bytecode instruction is dispatched in the ctor code visitor</li>
- *
- * <li>when this one is reached, it is only added in the ctor code visitor and a
- * JP invoke is added</li>
- *
- * <li>after that, only the other code visitor receives the instructions</li>
- *
- * </ol>
- *
- * @author Eugene Kuleshov
- * @author Eric Bruneton
- */
-public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes {
-
- private static final Object THIS = new Object();
-
- private static final Object OTHER = new Object();
-
- protected int methodAccess;
-
- protected String methodDesc;
-
- private boolean constructor;
-
- private boolean superInitialized;
-
- private List<Object> stackFrame;
-
- private Map<Label, List<Object>> branches;
-
- /**
- * Creates a new {@link AdviceAdapter}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param mv
- * the method visitor to which this adapter delegates calls.
- * @param access
- * the method's access flags (see {@link Opcodes}).
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- */
- protected AdviceAdapter(final int api, final MethodVisitor mv,
- final int access, final String name, final String desc) {
- super(api, mv, access, name, desc);
- methodAccess = access;
- methodDesc = desc;
- constructor = "<init>".equals(name);
- }
-
- @Override
- public void visitCode() {
- mv.visitCode();
- if (constructor) {
- stackFrame = new ArrayList<Object>();
- branches = new HashMap<Label, List<Object>>();
- } else {
- superInitialized = true;
- onMethodEnter();
- }
- }
-
- @Override
- public void visitLabel(final Label label) {
- mv.visitLabel(label);
- if (constructor && branches != null) {
- List<Object> frame = branches.get(label);
- if (frame != null) {
- stackFrame = frame;
- branches.remove(label);
- }
- }
- }
-
- @Override
- public void visitInsn(final int opcode) {
- if (constructor) {
- int s;
- switch (opcode) {
- case RETURN: // empty stack
- onMethodExit(opcode);
- break;
- case IRETURN: // 1 before n/a after
- case FRETURN: // 1 before n/a after
- case ARETURN: // 1 before n/a after
- case ATHROW: // 1 before n/a after
- popValue();
- onMethodExit(opcode);
- break;
- case LRETURN: // 2 before n/a after
- case DRETURN: // 2 before n/a after
- popValue();
- popValue();
- onMethodExit(opcode);
- break;
- case NOP:
- case LALOAD: // remove 2 add 2
- case DALOAD: // remove 2 add 2
- case LNEG:
- case DNEG:
- case FNEG:
- case INEG:
- case L2D:
- case D2L:
- case F2I:
- case I2B:
- case I2C:
- case I2S:
- case I2F:
- case ARRAYLENGTH:
- break;
- case ACONST_NULL:
- case ICONST_M1:
- case ICONST_0:
- case ICONST_1:
- case ICONST_2:
- case ICONST_3:
- case ICONST_4:
- case ICONST_5:
- case FCONST_0:
- case FCONST_1:
- case FCONST_2:
- case F2L: // 1 before 2 after
- case F2D:
- case I2L:
- case I2D:
- pushValue(OTHER);
- break;
- case LCONST_0:
- case LCONST_1:
- case DCONST_0:
- case DCONST_1:
- pushValue(OTHER);
- pushValue(OTHER);
- break;
- case IALOAD: // remove 2 add 1
- case FALOAD: // remove 2 add 1
- case AALOAD: // remove 2 add 1
- case BALOAD: // remove 2 add 1
- case CALOAD: // remove 2 add 1
- case SALOAD: // remove 2 add 1
- case POP:
- case IADD:
- case FADD:
- case ISUB:
- case LSHL: // 3 before 2 after
- case LSHR: // 3 before 2 after
- case LUSHR: // 3 before 2 after
- case L2I: // 2 before 1 after
- case L2F: // 2 before 1 after
- case D2I: // 2 before 1 after
- case D2F: // 2 before 1 after
- case FSUB:
- case FMUL:
- case FDIV:
- case FREM:
- case FCMPL: // 2 before 1 after
- case FCMPG: // 2 before 1 after
- case IMUL:
- case IDIV:
- case IREM:
- case ISHL:
- case ISHR:
- case IUSHR:
- case IAND:
- case IOR:
- case IXOR:
- case MONITORENTER:
- case MONITOREXIT:
- popValue();
- break;
- case POP2:
- case LSUB:
- case LMUL:
- case LDIV:
- case LREM:
- case LADD:
- case LAND:
- case LOR:
- case LXOR:
- case DADD:
- case DMUL:
- case DSUB:
- case DDIV:
- case DREM:
- popValue();
- popValue();
- break;
- case IASTORE:
- case FASTORE:
- case AASTORE:
- case BASTORE:
- case CASTORE:
- case SASTORE:
- case LCMP: // 4 before 1 after
- case DCMPL:
- case DCMPG:
- popValue();
- popValue();
- popValue();
- break;
- case LASTORE:
- case DASTORE:
- popValue();
- popValue();
- popValue();
- popValue();
- break;
- case DUP:
- pushValue(peekValue());
- break;
- case DUP_X1:
- s = stackFrame.size();
- stackFrame.add(s - 2, stackFrame.get(s - 1));
- break;
- case DUP_X2:
- s = stackFrame.size();
- stackFrame.add(s - 3, stackFrame.get(s - 1));
- break;
- case DUP2:
- s = stackFrame.size();
- stackFrame.add(s - 2, stackFrame.get(s - 1));
- stackFrame.add(s - 2, stackFrame.get(s - 1));
- break;
- case DUP2_X1:
- s = stackFrame.size();
- stackFrame.add(s - 3, stackFrame.get(s - 1));
- stackFrame.add(s - 3, stackFrame.get(s - 1));
- break;
- case DUP2_X2:
- s = stackFrame.size();
- stackFrame.add(s - 4, stackFrame.get(s - 1));
- stackFrame.add(s - 4, stackFrame.get(s - 1));
- break;
- case SWAP:
- s = stackFrame.size();
- stackFrame.add(s - 2, stackFrame.get(s - 1));
- stackFrame.remove(s);
- break;
- }
- } else {
- switch (opcode) {
- case RETURN:
- case IRETURN:
- case FRETURN:
- case ARETURN:
- case LRETURN:
- case DRETURN:
- case ATHROW:
- onMethodExit(opcode);
- break;
- }
- }
- mv.visitInsn(opcode);
- }
-
- @Override
- public void visitVarInsn(final int opcode, final int var) {
- super.visitVarInsn(opcode, var);
- if (constructor) {
- switch (opcode) {
- case ILOAD:
- case FLOAD:
- pushValue(OTHER);
- break;
- case LLOAD:
- case DLOAD:
- pushValue(OTHER);
- pushValue(OTHER);
- break;
- case ALOAD:
- pushValue(var == 0 ? THIS : OTHER);
- break;
- case ASTORE:
- case ISTORE:
- case FSTORE:
- popValue();
- break;
- case LSTORE:
- case DSTORE:
- popValue();
- popValue();
- break;
- }
- }
- }
-
- @Override
- public void visitFieldInsn(final int opcode, final String owner,
- final String name, final String desc) {
- mv.visitFieldInsn(opcode, owner, name, desc);
- if (constructor) {
- char c = desc.charAt(0);
- boolean longOrDouble = c == 'J' || c == 'D';
- switch (opcode) {
- case GETSTATIC:
- pushValue(OTHER);
- if (longOrDouble) {
- pushValue(OTHER);
- }
- break;
- case PUTSTATIC:
- popValue();
- if (longOrDouble) {
- popValue();
- }
- break;
- case PUTFIELD:
- popValue();
- if (longOrDouble) {
- popValue();
- popValue();
- }
- break;
- // case GETFIELD:
- default:
- if (longOrDouble) {
- pushValue(OTHER);
- }
- }
- }
- }
-
- @Override
- public void visitIntInsn(final int opcode, final int operand) {
- mv.visitIntInsn(opcode, operand);
- if (constructor && opcode != NEWARRAY) {
- pushValue(OTHER);
- }
- }
-
- @Override
- public void visitLdcInsn(final Object cst) {
- mv.visitLdcInsn(cst);
- if (constructor) {
- pushValue(OTHER);
- if (cst instanceof Double || cst instanceof Long) {
- pushValue(OTHER);
- }
- }
- }
-
- @Override
- public void visitMultiANewArrayInsn(final String desc, final int dims) {
- mv.visitMultiANewArrayInsn(desc, dims);
- if (constructor) {
- for (int i = 0; i < dims; i++) {
- popValue();
- }
- pushValue(OTHER);
- }
- }
-
- @Override
- public void visitTypeInsn(final int opcode, final String type) {
- mv.visitTypeInsn(opcode, type);
- // ANEWARRAY, CHECKCAST or INSTANCEOF don't change stack
- if (constructor && opcode == NEW) {
- pushValue(OTHER);
- }
- }
-
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc) {
- mv.visitMethodInsn(opcode, owner, name, desc);
- if (constructor) {
- Type[] types = Type.getArgumentTypes(desc);
- for (int i = 0; i < types.length; i++) {
- popValue();
- if (types[i].getSize() == 2) {
- popValue();
- }
- }
- switch (opcode) {
- // case INVOKESTATIC:
- // break;
- case INVOKEINTERFACE:
- case INVOKEVIRTUAL:
- popValue(); // objectref
- break;
- case INVOKESPECIAL:
- Object type = popValue(); // objectref
- if (type == THIS && !superInitialized) {
- onMethodEnter();
- superInitialized = true;
- // once super has been initialized it is no longer
- // necessary to keep track of stack state
- constructor = false;
- }
- break;
- }
-
- Type returnType = Type.getReturnType(desc);
- if (returnType != Type.VOID_TYPE) {
- pushValue(OTHER);
- if (returnType.getSize() == 2) {
- pushValue(OTHER);
- }
- }
- }
- }
-
- @Override
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
- if (constructor) {
- Type[] types = Type.getArgumentTypes(desc);
- for (int i = 0; i < types.length; i++) {
- popValue();
- if (types[i].getSize() == 2) {
- popValue();
- }
- }
-
- Type returnType = Type.getReturnType(desc);
- if (returnType != Type.VOID_TYPE) {
- pushValue(OTHER);
- if (returnType.getSize() == 2) {
- pushValue(OTHER);
- }
- }
- }
- }
-
- @Override
- public void visitJumpInsn(final int opcode, final Label label) {
- mv.visitJumpInsn(opcode, label);
- if (constructor) {
- switch (opcode) {
- case IFEQ:
- case IFNE:
- case IFLT:
- case IFGE:
- case IFGT:
- case IFLE:
- case IFNULL:
- case IFNONNULL:
- popValue();
- break;
- case IF_ICMPEQ:
- case IF_ICMPNE:
- case IF_ICMPLT:
- case IF_ICMPGE:
- case IF_ICMPGT:
- case IF_ICMPLE:
- case IF_ACMPEQ:
- case IF_ACMPNE:
- popValue();
- popValue();
- break;
- case JSR:
- pushValue(OTHER);
- break;
- }
- addBranch(label);
- }
- }
-
- @Override
- public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
- final Label[] labels) {
- mv.visitLookupSwitchInsn(dflt, keys, labels);
- if (constructor) {
- popValue();
- addBranches(dflt, labels);
- }
- }
-
- @Override
- public void visitTableSwitchInsn(final int min, final int max,
- final Label dflt, final Label... labels) {
- mv.visitTableSwitchInsn(min, max, dflt, labels);
- if (constructor) {
- popValue();
- addBranches(dflt, labels);
- }
- }
-
- @Override
- public void visitTryCatchBlock(Label start, Label end, Label handler,
- String type) {
- super.visitTryCatchBlock(start, end, handler, type);
- if (constructor && !branches.containsKey(handler)) {
- List<Object> stackFrame = new ArrayList<Object>();
- stackFrame.add(OTHER);
- branches.put(handler, stackFrame);
- }
- }
-
- private void addBranches(final Label dflt, final Label[] labels) {
- addBranch(dflt);
- for (int i = 0; i < labels.length; i++) {
- addBranch(labels[i]);
- }
- }
-
- private void addBranch(final Label label) {
- if (branches.containsKey(label)) {
- return;
- }
- branches.put(label, new ArrayList<Object>(stackFrame));
- }
-
- private Object popValue() {
- return stackFrame.remove(stackFrame.size() - 1);
- }
-
- private Object peekValue() {
- return stackFrame.get(stackFrame.size() - 1);
- }
-
- private void pushValue(final Object o) {
- stackFrame.add(o);
- }
-
- /**
- * Called at the beginning of the method or after super class class call in
- * the constructor. <br>
- * <br>
- *
- * <i>Custom code can use or change all the local variables, but should not
- * change state of the stack.</i>
- */
- protected void onMethodEnter() {
- }
-
- /**
- * Called before explicit exit from the method using either return or throw.
- * Top element on the stack contains the return value or exception instance.
- * For example:
- *
- * <pre>
- * public void onMethodExit(int opcode) {
- * if(opcode==RETURN) {
- * visitInsn(ACONST_NULL);
- * } else if(opcode==ARETURN || opcode==ATHROW) {
- * dup();
- * } else {
- * if(opcode==LRETURN || opcode==DRETURN) {
- * dup2();
- * } else {
- * dup();
- * }
- * box(Type.getReturnType(this.methodDesc));
- * }
- * visitIntInsn(SIPUSH, opcode);
- * visitMethodInsn(INVOKESTATIC, owner, "onExit", "(Ljava/lang/Object;I)V");
- * }
- *
- * // an actual call back method
- * public static void onExit(Object param, int opcode) {
- * ...
- * </pre>
- *
- * <br>
- * <br>
- *
- * <i>Custom code can use or change all the local variables, but should not
- * change state of the stack.</i>
- *
- * @param opcode
- * one of the RETURN, IRETURN, FRETURN, ARETURN, LRETURN, DRETURN
- * or ATHROW
- *
- */
- protected void onMethodExit(int opcode) {
- }
-
- // TODO onException, onMethodCall
-}
diff --git a/src/jvm/clojure/asm/commons/AnalyzerAdapter.java b/src/jvm/clojure/asm/commons/AnalyzerAdapter.java
deleted file mode 100644
index 429d8db..0000000
--- a/src/jvm/clojure/asm/commons/AnalyzerAdapter.java
+++ /dev/null
@@ -1,920 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm.commons;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import clojure.asm.Handle;
-import clojure.asm.Label;
-import clojure.asm.MethodVisitor;
-import clojure.asm.Opcodes;
-import clojure.asm.Type;
-
-/**
- * A {@link MethodVisitor} that keeps track of stack map frame changes between
- * {@link #visitFrame(int, int, Object[], int, Object[]) visitFrame} calls. This
- * adapter must be used with the
- * {@link clojure.asm.ClassReader#EXPAND_FRAMES} option. Each
- * visit<i>X</i> instruction delegates to the next visitor in the chain, if any,
- * and then simulates the effect of this instruction on the stack map frame,
- * represented by {@link #locals} and {@link #stack}. The next visitor in the
- * chain can get the state of the stack map frame <i>before</i> each instruction
- * by reading the value of these fields in its visit<i>X</i> methods (this
- * requires a reference to the AnalyzerAdapter that is before it in the chain).
- * If this adapter is used with a class that does not contain stack map table
- * attributes (i.e., pre Java 6 classes) then this adapter may not be able to
- * compute the stack map frame for each instruction. In this case no exception
- * is thrown but the {@link #locals} and {@link #stack} fields will be null for
- * these instructions.
- *
- * @author Eric Bruneton
- */
-public class AnalyzerAdapter extends MethodVisitor {
-
- /**
- * <code>List</code> of the local variable slots for current execution
- * frame. Primitive types are represented by {@link Opcodes#TOP},
- * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
- * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
- * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by
- * two elements, the second one being TOP). Reference types are represented
- * by String objects (representing internal names), and uninitialized types
- * by Label objects (this label designates the NEW instruction that created
- * this uninitialized value). This field is <tt>null</tt> for unreachable
- * instructions.
- */
- public List<Object> locals;
-
- /**
- * <code>List</code> of the operand stack slots for current execution frame.
- * Primitive types are represented by {@link Opcodes#TOP},
- * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
- * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
- * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by
- * two elements, the second one being TOP). Reference types are represented
- * by String objects (representing internal names), and uninitialized types
- * by Label objects (this label designates the NEW instruction that created
- * this uninitialized value). This field is <tt>null</tt> for unreachable
- * instructions.
- */
- public List<Object> stack;
-
- /**
- * The labels that designate the next instruction to be visited. May be
- * <tt>null</tt>.
- */
- private List<Label> labels;
-
- /**
- * Information about uninitialized types in the current execution frame.
- * This map associates internal names to Label objects. Each label
- * designates a NEW instruction that created the currently uninitialized
- * types, and the associated internal name represents the NEW operand, i.e.
- * the final, initialized type value.
- */
- public Map<Object, Object> uninitializedTypes;
-
- /**
- * The maximum stack size of this method.
- */
- private int maxStack;
-
- /**
- * The maximum number of local variables of this method.
- */
- private int maxLocals;
-
- /**
- * The owner's class name.
- */
- private String owner;
-
- /**
- * Creates a new {@link AnalyzerAdapter}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #AnalyzerAdapter(int, String, int, String, String, MethodVisitor)}
- * version.
- *
- * @param owner
- * the owner's class name.
- * @param access
- * the method's access flags (see {@link Opcodes}).
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- * @param mv
- * the method visitor to which this adapter delegates calls. May
- * be <tt>null</tt>.
- */
- public AnalyzerAdapter(final String owner, final int access,
- final String name, final String desc, final MethodVisitor mv) {
- this(Opcodes.ASM4, owner, access, name, desc, mv);
- }
-
- /**
- * Creates a new {@link AnalyzerAdapter}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param owner
- * the owner's class name.
- * @param access
- * the method's access flags (see {@link Opcodes}).
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- * @param mv
- * the method visitor to which this adapter delegates calls. May
- * be <tt>null</tt>.
- */
- protected AnalyzerAdapter(final int api, final String owner,
- final int access, final String name, final String desc,
- final MethodVisitor mv) {
- super(api, mv);
- this.owner = owner;
- locals = new ArrayList<Object>();
- stack = new ArrayList<Object>();
- uninitializedTypes = new HashMap<Object, Object>();
-
- if ((access & Opcodes.ACC_STATIC) == 0) {
- if ("<init>".equals(name)) {
- locals.add(Opcodes.UNINITIALIZED_THIS);
- } else {
- locals.add(owner);
- }
- }
- Type[] types = Type.getArgumentTypes(desc);
- for (int i = 0; i < types.length; ++i) {
- Type type = types[i];
- switch (type.getSort()) {
- case Type.BOOLEAN:
- case Type.CHAR:
- case Type.BYTE:
- case Type.SHORT:
- case Type.INT:
- locals.add(Opcodes.INTEGER);
- break;
- case Type.FLOAT:
- locals.add(Opcodes.FLOAT);
- break;
- case Type.LONG:
- locals.add(Opcodes.LONG);
- locals.add(Opcodes.TOP);
- break;
- case Type.DOUBLE:
- locals.add(Opcodes.DOUBLE);
- locals.add(Opcodes.TOP);
- break;
- case Type.ARRAY:
- locals.add(types[i].getDescriptor());
- break;
- // case Type.OBJECT:
- default:
- locals.add(types[i].getInternalName());
- }
- }
- }
-
- @Override
- public void visitFrame(final int type, final int nLocal,
- final Object[] local, final int nStack, final Object[] stack) {
- if (type != Opcodes.F_NEW) { // uncompressed frame
- throw new IllegalStateException(
- "ClassReader.accept() should be called with EXPAND_FRAMES flag");
- }
-
- if (mv != null) {
- mv.visitFrame(type, nLocal, local, nStack, stack);
- }
-
- if (this.locals != null) {
- this.locals.clear();
- this.stack.clear();
- } else {
- this.locals = new ArrayList<Object>();
- this.stack = new ArrayList<Object>();
- }
- visitFrameTypes(nLocal, local, this.locals);
- visitFrameTypes(nStack, stack, this.stack);
- maxStack = Math.max(maxStack, this.stack.size());
- }
-
- private static void visitFrameTypes(final int n, final Object[] types,
- final List<Object> result) {
- for (int i = 0; i < n; ++i) {
- Object type = types[i];
- result.add(type);
- if (type == Opcodes.LONG || type == Opcodes.DOUBLE) {
- result.add(Opcodes.TOP);
- }
- }
- }
-
- @Override
- public void visitInsn(final int opcode) {
- if (mv != null) {
- mv.visitInsn(opcode);
- }
- execute(opcode, 0, null);
- if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
- || opcode == Opcodes.ATHROW) {
- this.locals = null;
- this.stack = null;
- }
- }
-
- @Override
- public void visitIntInsn(final int opcode, final int operand) {
- if (mv != null) {
- mv.visitIntInsn(opcode, operand);
- }
- execute(opcode, operand, null);
- }
-
- @Override
- public void visitVarInsn(final int opcode, final int var) {
- if (mv != null) {
- mv.visitVarInsn(opcode, var);
- }
- execute(opcode, var, null);
- }
-
- @Override
- public void visitTypeInsn(final int opcode, final String type) {
- if (opcode == Opcodes.NEW) {
- if (labels == null) {
- Label l = new Label();
- labels = new ArrayList<Label>(3);
- labels.add(l);
- if (mv != null) {
- mv.visitLabel(l);
- }
- }
- for (int i = 0; i < labels.size(); ++i) {
- uninitializedTypes.put(labels.get(i), type);
- }
- }
- if (mv != null) {
- mv.visitTypeInsn(opcode, type);
- }
- execute(opcode, 0, type);
- }
-
- @Override
- public void visitFieldInsn(final int opcode, final String owner,
- final String name, final String desc) {
- if (mv != null) {
- mv.visitFieldInsn(opcode, owner, name, desc);
- }
- execute(opcode, 0, desc);
- }
-
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc) {
- if (mv != null) {
- mv.visitMethodInsn(opcode, owner, name, desc);
- }
- if (this.locals == null) {
- labels = null;
- return;
- }
- pop(desc);
- if (opcode != Opcodes.INVOKESTATIC) {
- Object t = pop();
- if (opcode == Opcodes.INVOKESPECIAL && name.charAt(0) == '<') {
- Object u;
- if (t == Opcodes.UNINITIALIZED_THIS) {
- u = this.owner;
- } else {
- u = uninitializedTypes.get(t);
- }
- for (int i = 0; i < locals.size(); ++i) {
- if (locals.get(i) == t) {
- locals.set(i, u);
- }
- }
- for (int i = 0; i < stack.size(); ++i) {
- if (stack.get(i) == t) {
- stack.set(i, u);
- }
- }
- }
- }
- pushDesc(desc);
- labels = null;
- }
-
- @Override
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- if (mv != null) {
- mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
- }
- if (this.locals == null) {
- labels = null;
- return;
- }
- pop(desc);
- pushDesc(desc);
- labels = null;
- }
-
- @Override
- public void visitJumpInsn(final int opcode, final Label label) {
- if (mv != null) {
- mv.visitJumpInsn(opcode, label);
- }
- execute(opcode, 0, null);
- if (opcode == Opcodes.GOTO) {
- this.locals = null;
- this.stack = null;
- }
- }
-
- @Override
- public void visitLabel(final Label label) {
- if (mv != null) {
- mv.visitLabel(label);
- }
- if (labels == null) {
- labels = new ArrayList<Label>(3);
- }
- labels.add(label);
- }
-
- @Override
- public void visitLdcInsn(final Object cst) {
- if (mv != null) {
- mv.visitLdcInsn(cst);
- }
- if (this.locals == null) {
- labels = null;
- return;
- }
- if (cst instanceof Integer) {
- push(Opcodes.INTEGER);
- } else if (cst instanceof Long) {
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- } else if (cst instanceof Float) {
- push(Opcodes.FLOAT);
- } else if (cst instanceof Double) {
- push(Opcodes.DOUBLE);
- push(Opcodes.TOP);
- } else if (cst instanceof String) {
- push("java/lang/String");
- } else if (cst instanceof Type) {
- int sort = ((Type) cst).getSort();
- if (sort == Type.OBJECT || sort == Type.ARRAY) {
- push("java/lang/Class");
- } else if (sort == Type.METHOD) {
- push("java/lang/invoke/MethodType");
- } else {
- throw new IllegalArgumentException();
- }
- } else if (cst instanceof Handle) {
- push("java/lang/invoke/MethodHandle");
- } else {
- throw new IllegalArgumentException();
- }
- labels = null;
- }
-
- @Override
- public void visitIincInsn(final int var, final int increment) {
- if (mv != null) {
- mv.visitIincInsn(var, increment);
- }
- execute(Opcodes.IINC, var, null);
- }
-
- @Override
- public void visitTableSwitchInsn(final int min, final int max,
- final Label dflt, final Label... labels) {
- if (mv != null) {
- mv.visitTableSwitchInsn(min, max, dflt, labels);
- }
- execute(Opcodes.TABLESWITCH, 0, null);
- this.locals = null;
- this.stack = null;
- }
-
- @Override
- public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
- final Label[] labels) {
- if (mv != null) {
- mv.visitLookupSwitchInsn(dflt, keys, labels);
- }
- execute(Opcodes.LOOKUPSWITCH, 0, null);
- this.locals = null;
- this.stack = null;
- }
-
- @Override
- public void visitMultiANewArrayInsn(final String desc, final int dims) {
- if (mv != null) {
- mv.visitMultiANewArrayInsn(desc, dims);
- }
- execute(Opcodes.MULTIANEWARRAY, dims, desc);
- }
-
- @Override
- public void visitMaxs(final int maxStack, final int maxLocals) {
- if (mv != null) {
- this.maxStack = Math.max(this.maxStack, maxStack);
- this.maxLocals = Math.max(this.maxLocals, maxLocals);
- mv.visitMaxs(this.maxStack, this.maxLocals);
- }
- }
-
- // ------------------------------------------------------------------------
-
- private Object get(final int local) {
- maxLocals = Math.max(maxLocals, local);
- return local < locals.size() ? locals.get(local) : Opcodes.TOP;
- }
-
- private void set(final int local, final Object type) {
- maxLocals = Math.max(maxLocals, local);
- while (local >= locals.size()) {
- locals.add(Opcodes.TOP);
- }
- locals.set(local, type);
- }
-
- private void push(final Object type) {
- stack.add(type);
- maxStack = Math.max(maxStack, stack.size());
- }
-
- private void pushDesc(final String desc) {
- int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
- switch (desc.charAt(index)) {
- case 'V':
- return;
- case 'Z':
- case 'C':
- case 'B':
- case 'S':
- case 'I':
- push(Opcodes.INTEGER);
- return;
- case 'F':
- push(Opcodes.FLOAT);
- return;
- case 'J':
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- return;
- case 'D':
- push(Opcodes.DOUBLE);
- push(Opcodes.TOP);
- return;
- case '[':
- if (index == 0) {
- push(desc);
- } else {
- push(desc.substring(index, desc.length()));
- }
- break;
- // case 'L':
- default:
- if (index == 0) {
- push(desc.substring(1, desc.length() - 1));
- } else {
- push(desc.substring(index + 1, desc.length() - 1));
- }
- }
- }
-
- private Object pop() {
- return stack.remove(stack.size() - 1);
- }
-
- private void pop(final int n) {
- int size = stack.size();
- int end = size - n;
- for (int i = size - 1; i >= end; --i) {
- stack.remove(i);
- }
- }
-
- private void pop(final String desc) {
- char c = desc.charAt(0);
- if (c == '(') {
- int n = 0;
- Type[] types = Type.getArgumentTypes(desc);
- for (int i = 0; i < types.length; ++i) {
- n += types[i].getSize();
- }
- pop(n);
- } else if (c == 'J' || c == 'D') {
- pop(2);
- } else {
- pop(1);
- }
- }
-
- private void execute(final int opcode, final int iarg, final String sarg) {
- if (this.locals == null) {
- labels = null;
- return;
- }
- Object t1, t2, t3, t4;
- switch (opcode) {
- case Opcodes.NOP:
- case Opcodes.INEG:
- case Opcodes.LNEG:
- case Opcodes.FNEG:
- case Opcodes.DNEG:
- case Opcodes.I2B:
- case Opcodes.I2C:
- case Opcodes.I2S:
- case Opcodes.GOTO:
- case Opcodes.RETURN:
- break;
- case Opcodes.ACONST_NULL:
- push(Opcodes.NULL);
- break;
- case Opcodes.ICONST_M1:
- case Opcodes.ICONST_0:
- case Opcodes.ICONST_1:
- case Opcodes.ICONST_2:
- case Opcodes.ICONST_3:
- case Opcodes.ICONST_4:
- case Opcodes.ICONST_5:
- case Opcodes.BIPUSH:
- case Opcodes.SIPUSH:
- push(Opcodes.INTEGER);
- break;
- case Opcodes.LCONST_0:
- case Opcodes.LCONST_1:
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- break;
- case Opcodes.FCONST_0:
- case Opcodes.FCONST_1:
- case Opcodes.FCONST_2:
- push(Opcodes.FLOAT);
- break;
- case Opcodes.DCONST_0:
- case Opcodes.DCONST_1:
- push(Opcodes.DOUBLE);
- push(Opcodes.TOP);
- break;
- case Opcodes.ILOAD:
- case Opcodes.FLOAD:
- case Opcodes.ALOAD:
- push(get(iarg));
- break;
- case Opcodes.LLOAD:
- case Opcodes.DLOAD:
- push(get(iarg));
- push(Opcodes.TOP);
- break;
- case Opcodes.IALOAD:
- case Opcodes.BALOAD:
- case Opcodes.CALOAD:
- case Opcodes.SALOAD:
- pop(2);
- push(Opcodes.INTEGER);
- break;
- case Opcodes.LALOAD:
- case Opcodes.D2L:
- pop(2);
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- break;
- case Opcodes.FALOAD:
- pop(2);
- push(Opcodes.FLOAT);
- break;
- case Opcodes.DALOAD:
- case Opcodes.L2D:
- pop(2);
- push(Opcodes.DOUBLE);
- push(Opcodes.TOP);
- break;
- case Opcodes.AALOAD:
- pop(1);
- t1 = pop();
- if (t1 instanceof String) {
- pushDesc(((String) t1).substring(1));
- } else {
- push("java/lang/Object");
- }
- break;
- case Opcodes.ISTORE:
- case Opcodes.FSTORE:
- case Opcodes.ASTORE:
- t1 = pop();
- set(iarg, t1);
- if (iarg > 0) {
- t2 = get(iarg - 1);
- if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) {
- set(iarg - 1, Opcodes.TOP);
- }
- }
- break;
- case Opcodes.LSTORE:
- case Opcodes.DSTORE:
- pop(1);
- t1 = pop();
- set(iarg, t1);
- set(iarg + 1, Opcodes.TOP);
- if (iarg > 0) {
- t2 = get(iarg - 1);
- if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) {
- set(iarg - 1, Opcodes.TOP);
- }
- }
- break;
- case Opcodes.IASTORE:
- case Opcodes.BASTORE:
- case Opcodes.CASTORE:
- case Opcodes.SASTORE:
- case Opcodes.FASTORE:
- case Opcodes.AASTORE:
- pop(3);
- break;
- case Opcodes.LASTORE:
- case Opcodes.DASTORE:
- pop(4);
- break;
- case Opcodes.POP:
- case Opcodes.IFEQ:
- case Opcodes.IFNE:
- case Opcodes.IFLT:
- case Opcodes.IFGE:
- case Opcodes.IFGT:
- case Opcodes.IFLE:
- case Opcodes.IRETURN:
- case Opcodes.FRETURN:
- case Opcodes.ARETURN:
- case Opcodes.TABLESWITCH:
- case Opcodes.LOOKUPSWITCH:
- case Opcodes.ATHROW:
- case Opcodes.MONITORENTER:
- case Opcodes.MONITOREXIT:
- case Opcodes.IFNULL:
- case Opcodes.IFNONNULL:
- pop(1);
- break;
- case Opcodes.POP2:
- case Opcodes.IF_ICMPEQ:
- case Opcodes.IF_ICMPNE:
- case Opcodes.IF_ICMPLT:
- case Opcodes.IF_ICMPGE:
- case Opcodes.IF_ICMPGT:
- case Opcodes.IF_ICMPLE:
- case Opcodes.IF_ACMPEQ:
- case Opcodes.IF_ACMPNE:
- case Opcodes.LRETURN:
- case Opcodes.DRETURN:
- pop(2);
- break;
- case Opcodes.DUP:
- t1 = pop();
- push(t1);
- push(t1);
- break;
- case Opcodes.DUP_X1:
- t1 = pop();
- t2 = pop();
- push(t1);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP_X2:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- push(t1);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2:
- t1 = pop();
- t2 = pop();
- push(t2);
- push(t1);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2_X1:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- push(t2);
- push(t1);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2_X2:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- t4 = pop();
- push(t2);
- push(t1);
- push(t4);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.SWAP:
- t1 = pop();
- t2 = pop();
- push(t1);
- push(t2);
- break;
- case Opcodes.IADD:
- case Opcodes.ISUB:
- case Opcodes.IMUL:
- case Opcodes.IDIV:
- case Opcodes.IREM:
- case Opcodes.IAND:
- case Opcodes.IOR:
- case Opcodes.IXOR:
- case Opcodes.ISHL:
- case Opcodes.ISHR:
- case Opcodes.IUSHR:
- case Opcodes.L2I:
- case Opcodes.D2I:
- case Opcodes.FCMPL:
- case Opcodes.FCMPG:
- pop(2);
- push(Opcodes.INTEGER);
- break;
- case Opcodes.LADD:
- case Opcodes.LSUB:
- case Opcodes.LMUL:
- case Opcodes.LDIV:
- case Opcodes.LREM:
- case Opcodes.LAND:
- case Opcodes.LOR:
- case Opcodes.LXOR:
- pop(4);
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- break;
- case Opcodes.FADD:
- case Opcodes.FSUB:
- case Opcodes.FMUL:
- case Opcodes.FDIV:
- case Opcodes.FREM:
- case Opcodes.L2F:
- case Opcodes.D2F:
- pop(2);
- push(Opcodes.FLOAT);
- break;
- case Opcodes.DADD:
- case Opcodes.DSUB:
- case Opcodes.DMUL:
- case Opcodes.DDIV:
- case Opcodes.DREM:
- pop(4);
- push(Opcodes.DOUBLE);
- push(Opcodes.TOP);
- break;
- case Opcodes.LSHL:
- case Opcodes.LSHR:
- case Opcodes.LUSHR:
- pop(3);
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- break;
- case Opcodes.IINC:
- set(iarg, Opcodes.INTEGER);
- break;
- case Opcodes.I2L:
- case Opcodes.F2L:
- pop(1);
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- break;
- case Opcodes.I2F:
- pop(1);
- push(Opcodes.FLOAT);
- break;
- case Opcodes.I2D:
- case Opcodes.F2D:
- pop(1);
- push(Opcodes.DOUBLE);
- push(Opcodes.TOP);
- break;
- case Opcodes.F2I:
- case Opcodes.ARRAYLENGTH:
- case Opcodes.INSTANCEOF:
- pop(1);
- push(Opcodes.INTEGER);
- break;
- case Opcodes.LCMP:
- case Opcodes.DCMPL:
- case Opcodes.DCMPG:
- pop(4);
- push(Opcodes.INTEGER);
- break;
- case Opcodes.JSR:
- case Opcodes.RET:
- throw new RuntimeException("JSR/RET are not supported");
- case Opcodes.GETSTATIC:
- pushDesc(sarg);
- break;
- case Opcodes.PUTSTATIC:
- pop(sarg);
- break;
- case Opcodes.GETFIELD:
- pop(1);
- pushDesc(sarg);
- break;
- case Opcodes.PUTFIELD:
- pop(sarg);
- pop();
- break;
- case Opcodes.NEW:
- push(labels.get(0));
- break;
- case Opcodes.NEWARRAY:
- pop();
- switch (iarg) {
- case Opcodes.T_BOOLEAN:
- pushDesc("[Z");
- break;
- case Opcodes.T_CHAR:
- pushDesc("[C");
- break;
- case Opcodes.T_BYTE:
- pushDesc("[B");
- break;
- case Opcodes.T_SHORT:
- pushDesc("[S");
- break;
- case Opcodes.T_INT:
- pushDesc("[I");
- break;
- case Opcodes.T_FLOAT:
- pushDesc("[F");
- break;
- case Opcodes.T_DOUBLE:
- pushDesc("[D");
- break;
- // case Opcodes.T_LONG:
- default:
- pushDesc("[J");
- break;
- }
- break;
- case Opcodes.ANEWARRAY:
- pop();
- pushDesc("[" + Type.getObjectType(sarg));
- break;
- case Opcodes.CHECKCAST:
- pop();
- pushDesc(Type.getObjectType(sarg).getDescriptor());
- break;
- // case Opcodes.MULTIANEWARRAY:
- default:
- pop(iarg);
- pushDesc(sarg);
- break;
- }
- labels = null;
- }
-}
diff --git a/src/jvm/clojure/asm/commons/CodeSizeEvaluator.java b/src/jvm/clojure/asm/commons/CodeSizeEvaluator.java
deleted file mode 100644
index 5a35bbf..0000000
--- a/src/jvm/clojure/asm/commons/CodeSizeEvaluator.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm.commons;
-
-import clojure.asm.Handle;
-import clojure.asm.Label;
-import clojure.asm.MethodVisitor;
-import clojure.asm.Opcodes;
-
-/**
- * A {@link MethodVisitor} that can be used to approximate method size.
- *
- * @author Eugene Kuleshov
- */
-public class CodeSizeEvaluator extends MethodVisitor implements Opcodes {
-
- private int minSize;
-
- private int maxSize;
-
- public CodeSizeEvaluator(final MethodVisitor mv) {
- this(Opcodes.ASM4, mv);
- }
-
- protected CodeSizeEvaluator(final int api, final MethodVisitor mv) {
- super(api, mv);
- }
-
- public int getMinSize() {
- return this.minSize;
- }
-
- public int getMaxSize() {
- return this.maxSize;
- }
-
- @Override
- public void visitInsn(final int opcode) {
- minSize += 1;
- maxSize += 1;
- if (mv != null) {
- mv.visitInsn(opcode);
- }
- }
-
- @Override
- public void visitIntInsn(final int opcode, final int operand) {
- if (opcode == SIPUSH) {
- minSize += 3;
- maxSize += 3;
- } else {
- minSize += 2;
- maxSize += 2;
- }
- if (mv != null) {
- mv.visitIntInsn(opcode, operand);
- }
- }
-
- @Override
- public void visitVarInsn(final int opcode, final int var) {
- if (var < 4 && opcode != RET) {
- minSize += 1;
- maxSize += 1;
- } else if (var >= 256) {
- minSize += 4;
- maxSize += 4;
- } else {
- minSize += 2;
- maxSize += 2;
- }
- if (mv != null) {
- mv.visitVarInsn(opcode, var);
- }
- }
-
- @Override
- public void visitTypeInsn(final int opcode, final String type) {
- minSize += 3;
- maxSize += 3;
- if (mv != null) {
- mv.visitTypeInsn(opcode, type);
- }
- }
-
- @Override
- public void visitFieldInsn(final int opcode, final String owner,
- final String name, final String desc) {
- minSize += 3;
- maxSize += 3;
- if (mv != null) {
- mv.visitFieldInsn(opcode, owner, name, desc);
- }
- }
-
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc) {
- if (opcode == INVOKEINTERFACE) {
- minSize += 5;
- maxSize += 5;
- } else {
- minSize += 3;
- maxSize += 3;
- }
- if (mv != null) {
- mv.visitMethodInsn(opcode, owner, name, desc);
- }
- }
-
- @Override
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- minSize += 5;
- maxSize += 5;
- if (mv != null) {
- mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
- }
- }
-
- @Override
- public void visitJumpInsn(final int opcode, final Label label) {
- minSize += 3;
- if (opcode == GOTO || opcode == JSR) {
- maxSize += 5;
- } else {
- maxSize += 8;
- }
- if (mv != null) {
- mv.visitJumpInsn(opcode, label);
- }
- }
-
- @Override
- public void visitLdcInsn(final Object cst) {
- if (cst instanceof Long || cst instanceof Double) {
- minSize += 3;
- maxSize += 3;
- } else {
- minSize += 2;
- maxSize += 3;
- }
- if (mv != null) {
- mv.visitLdcInsn(cst);
- }
- }
-
- @Override
- public void visitIincInsn(final int var, final int increment) {
- if (var > 255 || increment > 127 || increment < -128) {
- minSize += 6;
- maxSize += 6;
- } else {
- minSize += 3;
- maxSize += 3;
- }
- if (mv != null) {
- mv.visitIincInsn(var, increment);
- }
- }
-
- @Override
- public void visitTableSwitchInsn(final int min, final int max,
- final Label dflt, final Label... labels) {
- minSize += 13 + labels.length * 4;
- maxSize += 16 + labels.length * 4;
- if (mv != null) {
- mv.visitTableSwitchInsn(min, max, dflt, labels);
- }
- }
-
- @Override
- public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
- final Label[] labels) {
- minSize += 9 + keys.length * 8;
- maxSize += 12 + keys.length * 8;
- if (mv != null) {
- mv.visitLookupSwitchInsn(dflt, keys, labels);
- }
- }
-
- @Override
- public void visitMultiANewArrayInsn(final String desc, final int dims) {
- minSize += 4;
- maxSize += 4;
- if (mv != null) {
- mv.visitMultiANewArrayInsn(desc, dims);
- }
- }
-}
diff --git a/src/jvm/clojure/asm/commons/GeneratorAdapter.java b/src/jvm/clojure/asm/commons/GeneratorAdapter.java
deleted file mode 100644
index 8727478..0000000
--- a/src/jvm/clojure/asm/commons/GeneratorAdapter.java
+++ /dev/null
@@ -1,1623 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm.commons;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import clojure.asm.ClassVisitor;
-import clojure.asm.Handle;
-import clojure.asm.Label;
-import clojure.asm.MethodVisitor;
-import clojure.asm.Opcodes;
-import clojure.asm.Type;
-
-/**
- * A {@link clojure.asm.MethodVisitor} with convenient methods to generate
- * code. For example, using this adapter, the class below
- *
- * <pre>
- * public class Example {
- * public static void main(String[] args) {
- * System.out.println("Hello world!");
- * }
- * }
- * </pre>
- *
- * can be generated as follows:
- *
- * <pre>
- * ClassWriter cw = new ClassWriter(true);
- * cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);
- *
- * Method m = Method.getMethod("void <init> ()");
- * GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cw);
- * mg.loadThis();
- * mg.invokeConstructor(Type.getType(Object.class), m);
- * mg.returnValue();
- * mg.endMethod();
- *
- * m = Method.getMethod("void main (String[])");
- * mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw);
- * mg.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class));
- * mg.push("Hello world!");
- * mg.invokeVirtual(Type.getType(PrintStream.class),
- * Method.getMethod("void println (String)"));
- * mg.returnValue();
- * mg.endMethod();
- *
- * cw.visitEnd();
- * </pre>
- *
- * @author Juozas Baliuka
- * @author Chris Nokleberg
- * @author Eric Bruneton
- * @author Prashant Deva
- */
-public class GeneratorAdapter extends LocalVariablesSorter {
-
- private static final String CLDESC = "Ljava/lang/Class;";
-
- private static final Type BYTE_TYPE = Type.getObjectType("java/lang/Byte");
-
- private static final Type BOOLEAN_TYPE = Type
- .getObjectType("java/lang/Boolean");
-
- private static final Type SHORT_TYPE = Type
- .getObjectType("java/lang/Short");
-
- private static final Type CHARACTER_TYPE = Type
- .getObjectType("java/lang/Character");
-
- private static final Type INTEGER_TYPE = Type
- .getObjectType("java/lang/Integer");
-
- private static final Type FLOAT_TYPE = Type
- .getObjectType("java/lang/Float");
-
- private static final Type LONG_TYPE = Type.getObjectType("java/lang/Long");
-
- private static final Type DOUBLE_TYPE = Type
- .getObjectType("java/lang/Double");
-
- private static final Type NUMBER_TYPE = Type
- .getObjectType("java/lang/Number");
-
- private static final Type OBJECT_TYPE = Type
- .getObjectType("java/lang/Object");
-
- private static final Method BOOLEAN_VALUE = Method
- .getMethod("boolean booleanValue()");
-
- private static final Method CHAR_VALUE = Method
- .getMethod("char charValue()");
-
- private static final Method INT_VALUE = Method.getMethod("int intValue()");
-
- private static final Method FLOAT_VALUE = Method
- .getMethod("float floatValue()");
-
- private static final Method LONG_VALUE = Method
- .getMethod("long longValue()");
-
- private static final Method DOUBLE_VALUE = Method
- .getMethod("double doubleValue()");
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int ADD = Opcodes.IADD;
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int SUB = Opcodes.ISUB;
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int MUL = Opcodes.IMUL;
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int DIV = Opcodes.IDIV;
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int REM = Opcodes.IREM;
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int NEG = Opcodes.INEG;
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int SHL = Opcodes.ISHL;
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int SHR = Opcodes.ISHR;
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int USHR = Opcodes.IUSHR;
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int AND = Opcodes.IAND;
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int OR = Opcodes.IOR;
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int XOR = Opcodes.IXOR;
-
- /**
- * Constant for the {@link #ifCmp ifCmp} method.
- */
- public static final int EQ = Opcodes.IFEQ;
-
- /**
- * Constant for the {@link #ifCmp ifCmp} method.
- */
- public static final int NE = Opcodes.IFNE;
-
- /**
- * Constant for the {@link #ifCmp ifCmp} method.
- */
- public static final int LT = Opcodes.IFLT;
-
- /**
- * Constant for the {@link #ifCmp ifCmp} method.
- */
- public static final int GE = Opcodes.IFGE;
-
- /**
- * Constant for the {@link #ifCmp ifCmp} method.
- */
- public static final int GT = Opcodes.IFGT;
-
- /**
- * Constant for the {@link #ifCmp ifCmp} method.
- */
- public static final int LE = Opcodes.IFLE;
-
- /**
- * Access flags of the method visited by this adapter.
- */
- private final int access;
-
- /**
- * Return type of the method visited by this adapter.
- */
- private final Type returnType;
-
- /**
- * Argument types of the method visited by this adapter.
- */
- private final Type[] argumentTypes;
-
- /**
- * Types of the local variables of the method visited by this adapter.
- */
- private final List<Type> localTypes = new ArrayList<Type>();
-
- /**
- * Creates a new {@link GeneratorAdapter}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
- * version.
- *
- * @param mv
- * the method visitor to which this adapter delegates calls.
- * @param access
- * the method's access flags (see {@link Opcodes}).
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- */
- public GeneratorAdapter(final MethodVisitor mv, final int access,
- final String name, final String desc) {
- this(Opcodes.ASM4, mv, access, name, desc);
- }
-
- /**
- * Creates a new {@link GeneratorAdapter}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param mv
- * the method visitor to which this adapter delegates calls.
- * @param access
- * the method's access flags (see {@link Opcodes}).
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- */
- protected GeneratorAdapter(final int api, final MethodVisitor mv,
- final int access, final String name, final String desc) {
- super(api, access, desc, mv);
- this.access = access;
- this.returnType = Type.getReturnType(desc);
- this.argumentTypes = Type.getArgumentTypes(desc);
- }
-
- /**
- * Creates a new {@link GeneratorAdapter}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
- * version.
- *
- * @param access
- * access flags of the adapted method.
- * @param method
- * the adapted method.
- * @param mv
- * the method visitor to which this adapter delegates calls.
- */
- public GeneratorAdapter(final int access, final Method method,
- final MethodVisitor mv) {
- this(mv, access, null, method.getDescriptor());
- }
-
- /**
- * Creates a new {@link GeneratorAdapter}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
- * version.
- *
- * @param access
- * access flags of the adapted method.
- * @param method
- * the adapted method.
- * @param signature
- * the signature of the adapted method (may be <tt>null</tt>).
- * @param exceptions
- * the exceptions thrown by the adapted method (may be
- * <tt>null</tt>).
- * @param cv
- * the class visitor to which this adapter delegates calls.
- */
- public GeneratorAdapter(final int access, final Method method,
- final String signature, final Type[] exceptions,
- final ClassVisitor cv) {
- this(access, method, cv
- .visitMethod(access, method.getName(), method.getDescriptor(),
- signature, getInternalNames(exceptions)));
- }
-
- /**
- * Returns the internal names of the given types.
- *
- * @param types
- * a set of types.
- * @return the internal names of the given types.
- */
- private static String[] getInternalNames(final Type[] types) {
- if (types == null) {
- return null;
- }
- String[] names = new String[types.length];
- for (int i = 0; i < names.length; ++i) {
- names[i] = types[i].getInternalName();
- }
- return names;
- }
-
- // ------------------------------------------------------------------------
- // Instructions to push constants on the stack
- // ------------------------------------------------------------------------
-
- /**
- * Generates the instruction to push the given value on the stack.
- *
- * @param value
- * the value to be pushed on the stack.
- */
- public void push(final boolean value) {
- push(value ? 1 : 0);
- }
-
- /**
- * Generates the instruction to push the given value on the stack.
- *
- * @param value
- * the value to be pushed on the stack.
- */
- public void push(final int value) {
- if (value >= -1 && value <= 5) {
- mv.visitInsn(Opcodes.ICONST_0 + value);
- } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
- mv.visitIntInsn(Opcodes.BIPUSH, value);
- } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
- mv.visitIntInsn(Opcodes.SIPUSH, value);
- } else {
- mv.visitLdcInsn(new Integer(value));
- }
- }
-
- /**
- * Generates the instruction to push the given value on the stack.
- *
- * @param value
- * the value to be pushed on the stack.
- */
- public void push(final long value) {
- if (value == 0L || value == 1L) {
- mv.visitInsn(Opcodes.LCONST_0 + (int) value);
- } else {
- mv.visitLdcInsn(new Long(value));
- }
- }
-
- /**
- * Generates the instruction to push the given value on the stack.
- *
- * @param value
- * the value to be pushed on the stack.
- */
- public void push(final float value) {
- int bits = Float.floatToIntBits(value);
- if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2
- mv.visitInsn(Opcodes.FCONST_0 + (int) value);
- } else {
- mv.visitLdcInsn(new Float(value));
- }
- }
-
- /**
- * Generates the instruction to push the given value on the stack.
- *
- * @param value
- * the value to be pushed on the stack.
- */
- public void push(final double value) {
- long bits = Double.doubleToLongBits(value);
- if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d
- mv.visitInsn(Opcodes.DCONST_0 + (int) value);
- } else {
- mv.visitLdcInsn(new Double(value));
- }
- }
-
- /**
- * Generates the instruction to push the given value on the stack.
- *
- * @param value
- * the value to be pushed on the stack. May be <tt>null</tt>.
- */
- public void push(final String value) {
- if (value == null) {
- mv.visitInsn(Opcodes.ACONST_NULL);
- } else {
- mv.visitLdcInsn(value);
- }
- }
-
- /**
- * Generates the instruction to push the given value on the stack.
- *
- * @param value
- * the value to be pushed on the stack.
- */
- public void push(final Type value) {
- if (value == null) {
- mv.visitInsn(Opcodes.ACONST_NULL);
- } else {
- switch (value.getSort()) {
- case Type.BOOLEAN:
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean",
- "TYPE", CLDESC);
- break;
- case Type.CHAR:
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Character",
- "TYPE", CLDESC);
- break;
- case Type.BYTE:
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Byte", "TYPE",
- CLDESC);
- break;
- case Type.SHORT:
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Short", "TYPE",
- CLDESC);
- break;
- case Type.INT:
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Integer",
- "TYPE", CLDESC);
- break;
- case Type.FLOAT:
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Float", "TYPE",
- CLDESC);
- break;
- case Type.LONG:
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Long", "TYPE",
- CLDESC);
- break;
- case Type.DOUBLE:
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Double",
- "TYPE", CLDESC);
- break;
- default:
- mv.visitLdcInsn(value);
- }
- }
- }
-
- /**
- * Generates the instruction to push a handle on the stack.
- *
- * @param handle
- * the handle to be pushed on the stack.
- */
- public void push(final Handle handle) {
- mv.visitLdcInsn(handle);
- }
-
- // ------------------------------------------------------------------------
- // Instructions to load and store method arguments
- // ------------------------------------------------------------------------
-
- /**
- * Returns the index of the given method argument in the frame's local
- * variables array.
- *
- * @param arg
- * the index of a method argument.
- * @return the index of the given method argument in the frame's local
- * variables array.
- */
- private int getArgIndex(final int arg) {
- int index = (access & Opcodes.ACC_STATIC) == 0 ? 1 : 0;
- for (int i = 0; i < arg; i++) {
- index += argumentTypes[i].getSize();
- }
- return index;
- }
-
- /**
- * Generates the instruction to push a local variable on the stack.
- *
- * @param type
- * the type of the local variable to be loaded.
- * @param index
- * an index in the frame's local variables array.
- */
- private void loadInsn(final Type type, final int index) {
- mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), index);
- }
-
- /**
- * Generates the instruction to store the top stack value in a local
- * variable.
- *
- * @param type
- * the type of the local variable to be stored.
- * @param index
- * an index in the frame's local variables array.
- */
- private void storeInsn(final Type type, final int index) {
- mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), index);
- }
-
- /**
- * Generates the instruction to load 'this' on the stack.
- */
- public void loadThis() {
- if ((access & Opcodes.ACC_STATIC) != 0) {
- throw new IllegalStateException(
- "no 'this' pointer within static method");
- }
- mv.visitVarInsn(Opcodes.ALOAD, 0);
- }
-
- /**
- * Generates the instruction to load the given method argument on the stack.
- *
- * @param arg
- * the index of a method argument.
- */
- public void loadArg(final int arg) {
- loadInsn(argumentTypes[arg], getArgIndex(arg));
- }
-
- /**
- * Generates the instructions to load the given method arguments on the
- * stack.
- *
- * @param arg
- * the index of the first method argument to be loaded.
- * @param count
- * the number of method arguments to be loaded.
- */
- public void loadArgs(final int arg, final int count) {
- int index = getArgIndex(arg);
- for (int i = 0; i < count; ++i) {
- Type t = argumentTypes[arg + i];
- loadInsn(t, index);
- index += t.getSize();
- }
- }
-
- /**
- * Generates the instructions to load all the method arguments on the stack.
- */
- public void loadArgs() {
- loadArgs(0, argumentTypes.length);
- }
-
- /**
- * Generates the instructions to load all the method arguments on the stack,
- * as a single object array.
- */
- public void loadArgArray() {
- push(argumentTypes.length);
- newArray(OBJECT_TYPE);
- for (int i = 0; i < argumentTypes.length; i++) {
- dup();
- push(i);
- loadArg(i);
- box(argumentTypes[i]);
- arrayStore(OBJECT_TYPE);
- }
- }
-
- /**
- * Generates the instruction to store the top stack value in the given
- * method argument.
- *
- * @param arg
- * the index of a method argument.
- */
- public void storeArg(final int arg) {
- storeInsn(argumentTypes[arg], getArgIndex(arg));
- }
-
- // ------------------------------------------------------------------------
- // Instructions to load and store local variables
- // ------------------------------------------------------------------------
-
- /**
- * Returns the type of the given local variable.
- *
- * @param local
- * a local variable identifier, as returned by
- * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
- * @return the type of the given local variable.
- */
- public Type getLocalType(final int local) {
- return localTypes.get(local - firstLocal);
- }
-
- @Override
- protected void setLocalType(final int local, final Type type) {
- int index = local - firstLocal;
- while (localTypes.size() < index + 1) {
- localTypes.add(null);
- }
- localTypes.set(index, type);
- }
-
- /**
- * Generates the instruction to load the given local variable on the stack.
- *
- * @param local
- * a local variable identifier, as returned by
- * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
- */
- public void loadLocal(final int local) {
- loadInsn(getLocalType(local), local);
- }
-
- /**
- * Generates the instruction to load the given local variable on the stack.
- *
- * @param local
- * a local variable identifier, as returned by
- * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
- * @param type
- * the type of this local variable.
- */
- public void loadLocal(final int local, final Type type) {
- setLocalType(local, type);
- loadInsn(type, local);
- }
-
- /**
- * Generates the instruction to store the top stack value in the given local
- * variable.
- *
- * @param local
- * a local variable identifier, as returned by
- * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
- */
- public void storeLocal(final int local) {
- storeInsn(getLocalType(local), local);
- }
-
- /**
- * Generates the instruction to store the top stack value in the given local
- * variable.
- *
- * @param local
- * a local variable identifier, as returned by
- * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
- * @param type
- * the type of this local variable.
- */
- public void storeLocal(final int local, final Type type) {
- setLocalType(local, type);
- storeInsn(type, local);
- }
-
- /**
- * Generates the instruction to load an element from an array.
- *
- * @param type
- * the type of the array element to be loaded.
- */
- public void arrayLoad(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
- }
-
- /**
- * Generates the instruction to store an element in an array.
- *
- * @param type
- * the type of the array element to be stored.
- */
- public void arrayStore(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
- }
-
- // ------------------------------------------------------------------------
- // Instructions to manage the stack
- // ------------------------------------------------------------------------
-
- /**
- * Generates a POP instruction.
- */
- public void pop() {
- mv.visitInsn(Opcodes.POP);
- }
-
- /**
- * Generates a POP2 instruction.
- */
- public void pop2() {
- mv.visitInsn(Opcodes.POP2);
- }
-
- /**
- * Generates a DUP instruction.
- */
- public void dup() {
- mv.visitInsn(Opcodes.DUP);
- }
-
- /**
- * Generates a DUP2 instruction.
- */
- public void dup2() {
- mv.visitInsn(Opcodes.DUP2);
- }
-
- /**
- * Generates a DUP_X1 instruction.
- */
- public void dupX1() {
- mv.visitInsn(Opcodes.DUP_X1);
- }
-
- /**
- * Generates a DUP_X2 instruction.
- */
- public void dupX2() {
- mv.visitInsn(Opcodes.DUP_X2);
- }
-
- /**
- * Generates a DUP2_X1 instruction.
- */
- public void dup2X1() {
- mv.visitInsn(Opcodes.DUP2_X1);
- }
-
- /**
- * Generates a DUP2_X2 instruction.
- */
- public void dup2X2() {
- mv.visitInsn(Opcodes.DUP2_X2);
- }
-
- /**
- * Generates a SWAP instruction.
- */
- public void swap() {
- mv.visitInsn(Opcodes.SWAP);
- }
-
- /**
- * Generates the instructions to swap the top two stack values.
- *
- * @param prev
- * type of the top - 1 stack value.
- * @param type
- * type of the top stack value.
- */
- public void swap(final Type prev, final Type type) {
- if (type.getSize() == 1) {
- if (prev.getSize() == 1) {
- swap(); // same as dupX1(), pop();
- } else {
- dupX2();
- pop();
- }
- } else {
- if (prev.getSize() == 1) {
- dup2X1();
- pop2();
- } else {
- dup2X2();
- pop2();
- }
- }
- }
-
- // ------------------------------------------------------------------------
- // Instructions to do mathematical and logical operations
- // ------------------------------------------------------------------------
-
- /**
- * Generates the instruction to do the specified mathematical or logical
- * operation.
- *
- * @param op
- * a mathematical or logical operation. Must be one of ADD, SUB,
- * MUL, DIV, REM, NEG, SHL, SHR, USHR, AND, OR, XOR.
- * @param type
- * the type of the operand(s) for this operation.
- */
- public void math(final int op, final Type type) {
- mv.visitInsn(type.getOpcode(op));
- }
-
- /**
- * Generates the instructions to compute the bitwise negation of the top
- * stack value.
- */
- public void not() {
- mv.visitInsn(Opcodes.ICONST_1);
- mv.visitInsn(Opcodes.IXOR);
- }
-
- /**
- * Generates the instruction to increment the given local variable.
- *
- * @param local
- * the local variable to be incremented.
- * @param amount
- * the amount by which the local variable must be incremented.
- */
- public void iinc(final int local, final int amount) {
- mv.visitIincInsn(local, amount);
- }
-
- /**
- * Generates the instructions to cast a numerical value from one type to
- * another.
- *
- * @param from
- * the type of the top stack value
- * @param to
- * the type into which this value must be cast.
- */
- public void cast(final Type from, final Type to) {
- if (from != to) {
- if (from == Type.DOUBLE_TYPE) {
- if (to == Type.FLOAT_TYPE) {
- mv.visitInsn(Opcodes.D2F);
- } else if (to == Type.LONG_TYPE) {
- mv.visitInsn(Opcodes.D2L);
- } else {
- mv.visitInsn(Opcodes.D2I);
- cast(Type.INT_TYPE, to);
- }
- } else if (from == Type.FLOAT_TYPE) {
- if (to == Type.DOUBLE_TYPE) {
- mv.visitInsn(Opcodes.F2D);
- } else if (to == Type.LONG_TYPE) {
- mv.visitInsn(Opcodes.F2L);
- } else {
- mv.visitInsn(Opcodes.F2I);
- cast(Type.INT_TYPE, to);
- }
- } else if (from == Type.LONG_TYPE) {
- if (to == Type.DOUBLE_TYPE) {
- mv.visitInsn(Opcodes.L2D);
- } else if (to == Type.FLOAT_TYPE) {
- mv.visitInsn(Opcodes.L2F);
- } else {
- mv.visitInsn(Opcodes.L2I);
- cast(Type.INT_TYPE, to);
- }
- } else {
- if (to == Type.BYTE_TYPE) {
- mv.visitInsn(Opcodes.I2B);
- } else if (to == Type.CHAR_TYPE) {
- mv.visitInsn(Opcodes.I2C);
- } else if (to == Type.DOUBLE_TYPE) {
- mv.visitInsn(Opcodes.I2D);
- } else if (to == Type.FLOAT_TYPE) {
- mv.visitInsn(Opcodes.I2F);
- } else if (to == Type.LONG_TYPE) {
- mv.visitInsn(Opcodes.I2L);
- } else if (to == Type.SHORT_TYPE) {
- mv.visitInsn(Opcodes.I2S);
- }
- }
- }
- }
-
- // ------------------------------------------------------------------------
- // Instructions to do boxing and unboxing operations
- // ------------------------------------------------------------------------
-
- private static Type getBoxedType(final Type type) {
- switch (type.getSort()) {
- case Type.BYTE:
- return BYTE_TYPE;
- case Type.BOOLEAN:
- return BOOLEAN_TYPE;
- case Type.SHORT:
- return SHORT_TYPE;
- case Type.CHAR:
- return CHARACTER_TYPE;
- case Type.INT:
- return INTEGER_TYPE;
- case Type.FLOAT:
- return FLOAT_TYPE;
- case Type.LONG:
- return LONG_TYPE;
- case Type.DOUBLE:
- return DOUBLE_TYPE;
- }
- return type;
- }
-
- /**
- * Generates the instructions to box the top stack value. This value is
- * replaced by its boxed equivalent on top of the stack.
- *
- * @param type
- * the type of the top stack value.
- */
- public void box(final Type type) {
- if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
- return;
- }
- if (type == Type.VOID_TYPE) {
- push((String) null);
- } else {
- Type boxed = getBoxedType(type);
- newInstance(boxed);
- if (type.getSize() == 2) {
- // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o
- dupX2();
- dupX2();
- pop();
- } else {
- // p -> po -> opo -> oop -> o
- dupX1();
- swap();
- }
- invokeConstructor(boxed, new Method("<init>", Type.VOID_TYPE,
- new Type[] { type }));
- }
- }
-
- /**
- * Generates the instructions to box the top stack value using Java 5's
- * valueOf() method. This value is replaced by its boxed equivalent on top
- * of the stack.
- *
- * @param type
- * the type of the top stack value.
- */
- public void valueOf(final Type type) {
- if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
- return;
- }
- if (type == Type.VOID_TYPE) {
- push((String) null);
- } else {
- Type boxed = getBoxedType(type);
- invokeStatic(boxed, new Method("valueOf", boxed,
- new Type[] { type }));
- }
- }
-
- /**
- * Generates the instructions to unbox the top stack value. This value is
- * replaced by its unboxed equivalent on top of the stack.
- *
- * @param type
- * the type of the top stack value.
- */
- public void unbox(final Type type) {
- Type t = NUMBER_TYPE;
- Method sig = null;
- switch (type.getSort()) {
- case Type.VOID:
- return;
- case Type.CHAR:
- t = CHARACTER_TYPE;
- sig = CHAR_VALUE;
- break;
- case Type.BOOLEAN:
- t = BOOLEAN_TYPE;
- sig = BOOLEAN_VALUE;
- break;
- case Type.DOUBLE:
- sig = DOUBLE_VALUE;
- break;
- case Type.FLOAT:
- sig = FLOAT_VALUE;
- break;
- case Type.LONG:
- sig = LONG_VALUE;
- break;
- case Type.INT:
- case Type.SHORT:
- case Type.BYTE:
- sig = INT_VALUE;
- }
- if (sig == null) {
- checkCast(type);
- } else {
- checkCast(t);
- invokeVirtual(t, sig);
- }
- }
-
- // ------------------------------------------------------------------------
- // Instructions to jump to other instructions
- // ------------------------------------------------------------------------
-
- /**
- * Creates a new {@link Label}.
- *
- * @return a new {@link Label}.
- */
- public Label newLabel() {
- return new Label();
- }
-
- /**
- * Marks the current code position with the given label.
- *
- * @param label
- * a label.
- */
- public void mark(final Label label) {
- mv.visitLabel(label);
- }
-
- /**
- * Marks the current code position with a new label.
- *
- * @return the label that was created to mark the current code position.
- */
- public Label mark() {
- Label label = new Label();
- mv.visitLabel(label);
- return label;
- }
-
- /**
- * Generates the instructions to jump to a label based on the comparison of
- * the top two stack values.
- *
- * @param type
- * the type of the top two stack values.
- * @param mode
- * how these values must be compared. One of EQ, NE, LT, GE, GT,
- * LE.
- * @param label
- * where to jump if the comparison result is <tt>true</tt>.
- */
- public void ifCmp(final Type type, final int mode, final Label label) {
- switch (type.getSort()) {
- case Type.LONG:
- mv.visitInsn(Opcodes.LCMP);
- break;
- case Type.DOUBLE:
- mv.visitInsn(mode == GE || mode == GT ? Opcodes.DCMPL
- : Opcodes.DCMPG);
- break;
- case Type.FLOAT:
- mv.visitInsn(mode == GE || mode == GT ? Opcodes.FCMPL
- : Opcodes.FCMPG);
- break;
- case Type.ARRAY:
- case Type.OBJECT:
- switch (mode) {
- case EQ:
- mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
- return;
- case NE:
- mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
- return;
- }
- throw new IllegalArgumentException("Bad comparison for type "
- + type);
- default:
- int intOp = -1;
- switch (mode) {
- case EQ:
- intOp = Opcodes.IF_ICMPEQ;
- break;
- case NE:
- intOp = Opcodes.IF_ICMPNE;
- break;
- case GE:
- intOp = Opcodes.IF_ICMPGE;
- break;
- case LT:
- intOp = Opcodes.IF_ICMPLT;
- break;
- case LE:
- intOp = Opcodes.IF_ICMPLE;
- break;
- case GT:
- intOp = Opcodes.IF_ICMPGT;
- break;
- }
- mv.visitJumpInsn(intOp, label);
- return;
- }
- mv.visitJumpInsn(mode, label);
- }
-
- /**
- * Generates the instructions to jump to a label based on the comparison of
- * the top two integer stack values.
- *
- * @param mode
- * how these values must be compared. One of EQ, NE, LT, GE, GT,
- * LE.
- * @param label
- * where to jump if the comparison result is <tt>true</tt>.
- */
- public void ifICmp(final int mode, final Label label) {
- ifCmp(Type.INT_TYPE, mode, label);
- }
-
- /**
- * Generates the instructions to jump to a label based on the comparison of
- * the top integer stack value with zero.
- *
- * @param mode
- * how these values must be compared. One of EQ, NE, LT, GE, GT,
- * LE.
- * @param label
- * where to jump if the comparison result is <tt>true</tt>.
- */
- public void ifZCmp(final int mode, final Label label) {
- mv.visitJumpInsn(mode, label);
- }
-
- /**
- * Generates the instruction to jump to the given label if the top stack
- * value is null.
- *
- * @param label
- * where to jump if the condition is <tt>true</tt>.
- */
- public void ifNull(final Label label) {
- mv.visitJumpInsn(Opcodes.IFNULL, label);
- }
-
- /**
- * Generates the instruction to jump to the given label if the top stack
- * value is not null.
- *
- * @param label
- * where to jump if the condition is <tt>true</tt>.
- */
- public void ifNonNull(final Label label) {
- mv.visitJumpInsn(Opcodes.IFNONNULL, label);
- }
-
- /**
- * Generates the instruction to jump to the given label.
- *
- * @param label
- * where to jump if the condition is <tt>true</tt>.
- */
- public void goTo(final Label label) {
- mv.visitJumpInsn(Opcodes.GOTO, label);
- }
-
- /**
- * Generates a RET instruction.
- *
- * @param local
- * a local variable identifier, as returned by
- * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
- */
- public void ret(final int local) {
- mv.visitVarInsn(Opcodes.RET, local);
- }
-
- /**
- * Generates the instructions for a switch statement.
- *
- * @param keys
- * the switch case keys.
- * @param generator
- * a generator to generate the code for the switch cases.
- */
- public void tableSwitch(final int[] keys,
- final TableSwitchGenerator generator) {
- float density;
- if (keys.length == 0) {
- density = 0;
- } else {
- density = (float) keys.length
- / (keys[keys.length - 1] - keys[0] + 1);
- }
- tableSwitch(keys, generator, density >= 0.5f);
- }
-
- /**
- * Generates the instructions for a switch statement.
- *
- * @param keys
- * the switch case keys.
- * @param generator
- * a generator to generate the code for the switch cases.
- * @param useTable
- * <tt>true</tt> to use a TABLESWITCH instruction, or
- * <tt>false</tt> to use a LOOKUPSWITCH instruction.
- */
- public void tableSwitch(final int[] keys,
- final TableSwitchGenerator generator, final boolean useTable) {
- for (int i = 1; i < keys.length; ++i) {
- if (keys[i] < keys[i - 1]) {
- throw new IllegalArgumentException(
- "keys must be sorted ascending");
- }
- }
- Label def = newLabel();
- Label end = newLabel();
- if (keys.length > 0) {
- int len = keys.length;
- int min = keys[0];
- int max = keys[len - 1];
- int range = max - min + 1;
- if (useTable) {
- Label[] labels = new Label[range];
- Arrays.fill(labels, def);
- for (int i = 0; i < len; ++i) {
- labels[keys[i] - min] = newLabel();
- }
- mv.visitTableSwitchInsn(min, max, def, labels);
- for (int i = 0; i < range; ++i) {
- Label label = labels[i];
- if (label != def) {
- mark(label);
- generator.generateCase(i + min, end);
- }
- }
- } else {
- Label[] labels = new Label[len];
- for (int i = 0; i < len; ++i) {
- labels[i] = newLabel();
- }
- mv.visitLookupSwitchInsn(def, keys, labels);
- for (int i = 0; i < len; ++i) {
- mark(labels[i]);
- generator.generateCase(keys[i], end);
- }
- }
- }
- mark(def);
- generator.generateDefault();
- mark(end);
- }
-
- /**
- * Generates the instruction to return the top stack value to the caller.
- */
- public void returnValue() {
- mv.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
- }
-
- // ------------------------------------------------------------------------
- // Instructions to load and store fields
- // ------------------------------------------------------------------------
-
- /**
- * Generates a get field or set field instruction.
- *
- * @param opcode
- * the instruction's opcode.
- * @param ownerType
- * the class in which the field is defined.
- * @param name
- * the name of the field.
- * @param fieldType
- * the type of the field.
- */
- private void fieldInsn(final int opcode, final Type ownerType,
- final String name, final Type fieldType) {
- mv.visitFieldInsn(opcode, ownerType.getInternalName(), name,
- fieldType.getDescriptor());
- }
-
- /**
- * Generates the instruction to push the value of a static field on the
- * stack.
- *
- * @param owner
- * the class in which the field is defined.
- * @param name
- * the name of the field.
- * @param type
- * the type of the field.
- */
- public void getStatic(final Type owner, final String name, final Type type) {
- fieldInsn(Opcodes.GETSTATIC, owner, name, type);
- }
-
- /**
- * Generates the instruction to store the top stack value in a static field.
- *
- * @param owner
- * the class in which the field is defined.
- * @param name
- * the name of the field.
- * @param type
- * the type of the field.
- */
- public void putStatic(final Type owner, final String name, final Type type) {
- fieldInsn(Opcodes.PUTSTATIC, owner, name, type);
- }
-
- /**
- * Generates the instruction to push the value of a non static field on the
- * stack.
- *
- * @param owner
- * the class in which the field is defined.
- * @param name
- * the name of the field.
- * @param type
- * the type of the field.
- */
- public void getField(final Type owner, final String name, final Type type) {
- fieldInsn(Opcodes.GETFIELD, owner, name, type);
- }
-
- /**
- * Generates the instruction to store the top stack value in a non static
- * field.
- *
- * @param owner
- * the class in which the field is defined.
- * @param name
- * the name of the field.
- * @param type
- * the type of the field.
- */
- public void putField(final Type owner, final String name, final Type type) {
- fieldInsn(Opcodes.PUTFIELD, owner, name, type);
- }
-
- // ------------------------------------------------------------------------
- // Instructions to invoke methods
- // ------------------------------------------------------------------------
-
- /**
- * Generates an invoke method instruction.
- *
- * @param opcode
- * the instruction's opcode.
- * @param type
- * the class in which the method is defined.
- * @param method
- * the method to be invoked.
- */
- private void invokeInsn(final int opcode, final Type type,
- final Method method) {
- String owner = type.getSort() == Type.ARRAY ? type.getDescriptor()
- : type.getInternalName();
- mv.visitMethodInsn(opcode, owner, method.getName(),
- method.getDescriptor());
- }
-
- /**
- * Generates the instruction to invoke a normal method.
- *
- * @param owner
- * the class in which the method is defined.
- * @param method
- * the method to be invoked.
- */
- public void invokeVirtual(final Type owner, final Method method) {
- invokeInsn(Opcodes.INVOKEVIRTUAL, owner, method);
- }
-
- /**
- * Generates the instruction to invoke a constructor.
- *
- * @param type
- * the class in which the constructor is defined.
- * @param method
- * the constructor to be invoked.
- */
- public void invokeConstructor(final Type type, final Method method) {
- invokeInsn(Opcodes.INVOKESPECIAL, type, method);
- }
-
- /**
- * Generates the instruction to invoke a static method.
- *
- * @param owner
- * the class in which the method is defined.
- * @param method
- * the method to be invoked.
- */
- public void invokeStatic(final Type owner, final Method method) {
- invokeInsn(Opcodes.INVOKESTATIC, owner, method);
- }
-
- /**
- * Generates the instruction to invoke an interface method.
- *
- * @param owner
- * the class in which the method is defined.
- * @param method
- * the method to be invoked.
- */
- public void invokeInterface(final Type owner, final Method method) {
- invokeInsn(Opcodes.INVOKEINTERFACE, owner, method);
- }
-
- /**
- * Generates an invokedynamic instruction.
- *
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- * @param bsm
- * the bootstrap method.
- * @param bsmArgs
- * the bootstrap method constant arguments. Each argument must be
- * an {@link Integer}, {@link Float}, {@link Long},
- * {@link Double}, {@link String}, {@link Type} or {@link Handle}
- * value. This method is allowed to modify the content of the
- * array so a caller should expect that this array may change.
- */
- public void invokeDynamic(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
- }
-
- // ------------------------------------------------------------------------
- // Instructions to create objects and arrays
- // ------------------------------------------------------------------------
-
- /**
- * Generates a type dependent instruction.
- *
- * @param opcode
- * the instruction's opcode.
- * @param type
- * the instruction's operand.
- */
- private void typeInsn(final int opcode, final Type type) {
- mv.visitTypeInsn(opcode, type.getInternalName());
- }
-
- /**
- * Generates the instruction to create a new object.
- *
- * @param type
- * the class of the object to be created.
- */
- public void newInstance(final Type type) {
- typeInsn(Opcodes.NEW, type);
- }
-
- /**
- * Generates the instruction to create a new array.
- *
- * @param type
- * the type of the array elements.
- */
- public void newArray(final Type type) {
- int typ;
- switch (type.getSort()) {
- case Type.BOOLEAN:
- typ = Opcodes.T_BOOLEAN;
- break;
- case Type.CHAR:
- typ = Opcodes.T_CHAR;
- break;
- case Type.BYTE:
- typ = Opcodes.T_BYTE;
- break;
- case Type.SHORT:
- typ = Opcodes.T_SHORT;
- break;
- case Type.INT:
- typ = Opcodes.T_INT;
- break;
- case Type.FLOAT:
- typ = Opcodes.T_FLOAT;
- break;
- case Type.LONG:
- typ = Opcodes.T_LONG;
- break;
- case Type.DOUBLE:
- typ = Opcodes.T_DOUBLE;
- break;
- default:
- typeInsn(Opcodes.ANEWARRAY, type);
- return;
- }
- mv.visitIntInsn(Opcodes.NEWARRAY, typ);
- }
-
- // ------------------------------------------------------------------------
- // Miscelaneous instructions
- // ------------------------------------------------------------------------
-
- /**
- * Generates the instruction to compute the length of an array.
- */
- public void arrayLength() {
- mv.visitInsn(Opcodes.ARRAYLENGTH);
- }
-
- /**
- * Generates the instruction to throw an exception.
- */
- public void throwException() {
- mv.visitInsn(Opcodes.ATHROW);
- }
-
- /**
- * Generates the instructions to create and throw an exception. The
- * exception class must have a constructor with a single String argument.
- *
- * @param type
- * the class of the exception to be thrown.
- * @param msg
- * the detailed message of the exception.
- */
- public void throwException(final Type type, final String msg) {
- newInstance(type);
- dup();
- push(msg);
- invokeConstructor(type, Method.getMethod("void <init> (String)"));
- throwException();
- }
-
- /**
- * Generates the instruction to check that the top stack value is of the
- * given type.
- *
- * @param type
- * a class or interface type.
- */
- public void checkCast(final Type type) {
- if (!type.equals(OBJECT_TYPE)) {
- typeInsn(Opcodes.CHECKCAST, type);
- }
- }
-
- /**
- * Generates the instruction to test if the top stack value is of the given
- * type.
- *
- * @param type
- * a class or interface type.
- */
- public void instanceOf(final Type type) {
- typeInsn(Opcodes.INSTANCEOF, type);
- }
-
- /**
- * Generates the instruction to get the monitor of the top stack value.
- */
- public void monitorEnter() {
- mv.visitInsn(Opcodes.MONITORENTER);
- }
-
- /**
- * Generates the instruction to release the monitor of the top stack value.
- */
- public void monitorExit() {
- mv.visitInsn(Opcodes.MONITOREXIT);
- }
-
- // ------------------------------------------------------------------------
- // Non instructions
- // ------------------------------------------------------------------------
-
- /**
- * Marks the end of the visited method.
- */
- public void endMethod() {
- if ((access & Opcodes.ACC_ABSTRACT) == 0) {
- mv.visitMaxs(0, 0);
- }
- mv.visitEnd();
- }
-
- /**
- * Marks the start of an exception handler.
- *
- * @param start
- * beginning of the exception handler's scope (inclusive).
- * @param end
- * end of the exception handler's scope (exclusive).
- * @param exception
- * internal name of the type of exceptions handled by the
- * handler.
- */
- public void catchException(final Label start, final Label end,
- final Type exception) {
- if (exception == null) {
- mv.visitTryCatchBlock(start, end, mark(), null);
- } else {
- mv.visitTryCatchBlock(start, end, mark(),
- exception.getInternalName());
- }
- }
-}
diff --git a/src/jvm/clojure/asm/commons/InstructionAdapter.java b/src/jvm/clojure/asm/commons/InstructionAdapter.java
deleted file mode 100644
index e61c109..0000000
--- a/src/jvm/clojure/asm/commons/InstructionAdapter.java
+++ /dev/null
@@ -1,1090 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm.commons;
-
-import clojure.asm.Handle;
-import clojure.asm.Label;
-import clojure.asm.MethodVisitor;
-import clojure.asm.Opcodes;
-import clojure.asm.Type;
-
-/**
- * A {@link MethodVisitor} providing a more detailed API to generate and
- * transform instructions.
- *
- * @author Eric Bruneton
- */
-public class InstructionAdapter extends MethodVisitor {
-
- public final static Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;");
-
- /**
- * Creates a new {@link InstructionAdapter}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #InstructionAdapter(int, MethodVisitor)} version.
- *
- * @param mv
- * the method visitor to which this adapter delegates calls.
- */
- public InstructionAdapter(final MethodVisitor mv) {
- this(Opcodes.ASM4, mv);
- }
-
- /**
- * Creates a new {@link InstructionAdapter}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param mv
- * the method visitor to which this adapter delegates calls.
- */
- protected InstructionAdapter(final int api, final MethodVisitor mv) {
- super(api, mv);
- }
-
- @Override
- public void visitInsn(final int opcode) {
- switch (opcode) {
- case Opcodes.NOP:
- nop();
- break;
- case Opcodes.ACONST_NULL:
- aconst(null);
- break;
- case Opcodes.ICONST_M1:
- case Opcodes.ICONST_0:
- case Opcodes.ICONST_1:
- case Opcodes.ICONST_2:
- case Opcodes.ICONST_3:
- case Opcodes.ICONST_4:
- case Opcodes.ICONST_5:
- iconst(opcode - Opcodes.ICONST_0);
- break;
- case Opcodes.LCONST_0:
- case Opcodes.LCONST_1:
- lconst(opcode - Opcodes.LCONST_0);
- break;
- case Opcodes.FCONST_0:
- case Opcodes.FCONST_1:
- case Opcodes.FCONST_2:
- fconst(opcode - Opcodes.FCONST_0);
- break;
- case Opcodes.DCONST_0:
- case Opcodes.DCONST_1:
- dconst(opcode - Opcodes.DCONST_0);
- break;
- case Opcodes.IALOAD:
- aload(Type.INT_TYPE);
- break;
- case Opcodes.LALOAD:
- aload(Type.LONG_TYPE);
- break;
- case Opcodes.FALOAD:
- aload(Type.FLOAT_TYPE);
- break;
- case Opcodes.DALOAD:
- aload(Type.DOUBLE_TYPE);
- break;
- case Opcodes.AALOAD:
- aload(OBJECT_TYPE);
- break;
- case Opcodes.BALOAD:
- aload(Type.BYTE_TYPE);
- break;
- case Opcodes.CALOAD:
- aload(Type.CHAR_TYPE);
- break;
- case Opcodes.SALOAD:
- aload(Type.SHORT_TYPE);
- break;
- case Opcodes.IASTORE:
- astore(Type.INT_TYPE);
- break;
- case Opcodes.LASTORE:
- astore(Type.LONG_TYPE);
- break;
- case Opcodes.FASTORE:
- astore(Type.FLOAT_TYPE);
- break;
- case Opcodes.DASTORE:
- astore(Type.DOUBLE_TYPE);
- break;
- case Opcodes.AASTORE:
- astore(OBJECT_TYPE);
- break;
- case Opcodes.BASTORE:
- astore(Type.BYTE_TYPE);
- break;
- case Opcodes.CASTORE:
- astore(Type.CHAR_TYPE);
- break;
- case Opcodes.SASTORE:
- astore(Type.SHORT_TYPE);
- break;
- case Opcodes.POP:
- pop();
- break;
- case Opcodes.POP2:
- pop2();
- break;
- case Opcodes.DUP:
- dup();
- break;
- case Opcodes.DUP_X1:
- dupX1();
- break;
- case Opcodes.DUP_X2:
- dupX2();
- break;
- case Opcodes.DUP2:
- dup2();
- break;
- case Opcodes.DUP2_X1:
- dup2X1();
- break;
- case Opcodes.DUP2_X2:
- dup2X2();
- break;
- case Opcodes.SWAP:
- swap();
- break;
- case Opcodes.IADD:
- add(Type.INT_TYPE);
- break;
- case Opcodes.LADD:
- add(Type.LONG_TYPE);
- break;
- case Opcodes.FADD:
- add(Type.FLOAT_TYPE);
- break;
- case Opcodes.DADD:
- add(Type.DOUBLE_TYPE);
- break;
- case Opcodes.ISUB:
- sub(Type.INT_TYPE);
- break;
- case Opcodes.LSUB:
- sub(Type.LONG_TYPE);
- break;
- case Opcodes.FSUB:
- sub(Type.FLOAT_TYPE);
- break;
- case Opcodes.DSUB:
- sub(Type.DOUBLE_TYPE);
- break;
- case Opcodes.IMUL:
- mul(Type.INT_TYPE);
- break;
- case Opcodes.LMUL:
- mul(Type.LONG_TYPE);
- break;
- case Opcodes.FMUL:
- mul(Type.FLOAT_TYPE);
- break;
- case Opcodes.DMUL:
- mul(Type.DOUBLE_TYPE);
- break;
- case Opcodes.IDIV:
- div(Type.INT_TYPE);
- break;
- case Opcodes.LDIV:
- div(Type.LONG_TYPE);
- break;
- case Opcodes.FDIV:
- div(Type.FLOAT_TYPE);
- break;
- case Opcodes.DDIV:
- div(Type.DOUBLE_TYPE);
- break;
- case Opcodes.IREM:
- rem(Type.INT_TYPE);
- break;
- case Opcodes.LREM:
- rem(Type.LONG_TYPE);
- break;
- case Opcodes.FREM:
- rem(Type.FLOAT_TYPE);
- break;
- case Opcodes.DREM:
- rem(Type.DOUBLE_TYPE);
- break;
- case Opcodes.INEG:
- neg(Type.INT_TYPE);
- break;
- case Opcodes.LNEG:
- neg(Type.LONG_TYPE);
- break;
- case Opcodes.FNEG:
- neg(Type.FLOAT_TYPE);
- break;
- case Opcodes.DNEG:
- neg(Type.DOUBLE_TYPE);
- break;
- case Opcodes.ISHL:
- shl(Type.INT_TYPE);
- break;
- case Opcodes.LSHL:
- shl(Type.LONG_TYPE);
- break;
- case Opcodes.ISHR:
- shr(Type.INT_TYPE);
- break;
- case Opcodes.LSHR:
- shr(Type.LONG_TYPE);
- break;
- case Opcodes.IUSHR:
- ushr(Type.INT_TYPE);
- break;
- case Opcodes.LUSHR:
- ushr(Type.LONG_TYPE);
- break;
- case Opcodes.IAND:
- and(Type.INT_TYPE);
- break;
- case Opcodes.LAND:
- and(Type.LONG_TYPE);
- break;
- case Opcodes.IOR:
- or(Type.INT_TYPE);
- break;
- case Opcodes.LOR:
- or(Type.LONG_TYPE);
- break;
- case Opcodes.IXOR:
- xor(Type.INT_TYPE);
- break;
- case Opcodes.LXOR:
- xor(Type.LONG_TYPE);
- break;
- case Opcodes.I2L:
- cast(Type.INT_TYPE, Type.LONG_TYPE);
- break;
- case Opcodes.I2F:
- cast(Type.INT_TYPE, Type.FLOAT_TYPE);
- break;
- case Opcodes.I2D:
- cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
- break;
- case Opcodes.L2I:
- cast(Type.LONG_TYPE, Type.INT_TYPE);
- break;
- case Opcodes.L2F:
- cast(Type.LONG_TYPE, Type.FLOAT_TYPE);
- break;
- case Opcodes.L2D:
- cast(Type.LONG_TYPE, Type.DOUBLE_TYPE);
- break;
- case Opcodes.F2I:
- cast(Type.FLOAT_TYPE, Type.INT_TYPE);
- break;
- case Opcodes.F2L:
- cast(Type.FLOAT_TYPE, Type.LONG_TYPE);
- break;
- case Opcodes.F2D:
- cast(Type.FLOAT_TYPE, Type.DOUBLE_TYPE);
- break;
- case Opcodes.D2I:
- cast(Type.DOUBLE_TYPE, Type.INT_TYPE);
- break;
- case Opcodes.D2L:
- cast(Type.DOUBLE_TYPE, Type.LONG_TYPE);
- break;
- case Opcodes.D2F:
- cast(Type.DOUBLE_TYPE, Type.FLOAT_TYPE);
- break;
- case Opcodes.I2B:
- cast(Type.INT_TYPE, Type.BYTE_TYPE);
- break;
- case Opcodes.I2C:
- cast(Type.INT_TYPE, Type.CHAR_TYPE);
- break;
- case Opcodes.I2S:
- cast(Type.INT_TYPE, Type.SHORT_TYPE);
- break;
- case Opcodes.LCMP:
- lcmp();
- break;
- case Opcodes.FCMPL:
- cmpl(Type.FLOAT_TYPE);
- break;
- case Opcodes.FCMPG:
- cmpg(Type.FLOAT_TYPE);
- break;
- case Opcodes.DCMPL:
- cmpl(Type.DOUBLE_TYPE);
- break;
- case Opcodes.DCMPG:
- cmpg(Type.DOUBLE_TYPE);
- break;
- case Opcodes.IRETURN:
- areturn(Type.INT_TYPE);
- break;
- case Opcodes.LRETURN:
- areturn(Type.LONG_TYPE);
- break;
- case Opcodes.FRETURN:
- areturn(Type.FLOAT_TYPE);
- break;
- case Opcodes.DRETURN:
- areturn(Type.DOUBLE_TYPE);
- break;
- case Opcodes.ARETURN:
- areturn(OBJECT_TYPE);
- break;
- case Opcodes.RETURN:
- areturn(Type.VOID_TYPE);
- break;
- case Opcodes.ARRAYLENGTH:
- arraylength();
- break;
- case Opcodes.ATHROW:
- athrow();
- break;
- case Opcodes.MONITORENTER:
- monitorenter();
- break;
- case Opcodes.MONITOREXIT:
- monitorexit();
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- @Override
- public void visitIntInsn(final int opcode, final int operand) {
- switch (opcode) {
- case Opcodes.BIPUSH:
- iconst(operand);
- break;
- case Opcodes.SIPUSH:
- iconst(operand);
- break;
- case Opcodes.NEWARRAY:
- switch (operand) {
- case Opcodes.T_BOOLEAN:
- newarray(Type.BOOLEAN_TYPE);
- break;
- case Opcodes.T_CHAR:
- newarray(Type.CHAR_TYPE);
- break;
- case Opcodes.T_BYTE:
- newarray(Type.BYTE_TYPE);
- break;
- case Opcodes.T_SHORT:
- newarray(Type.SHORT_TYPE);
- break;
- case Opcodes.T_INT:
- newarray(Type.INT_TYPE);
- break;
- case Opcodes.T_FLOAT:
- newarray(Type.FLOAT_TYPE);
- break;
- case Opcodes.T_LONG:
- newarray(Type.LONG_TYPE);
- break;
- case Opcodes.T_DOUBLE:
- newarray(Type.DOUBLE_TYPE);
- break;
- default:
- throw new IllegalArgumentException();
- }
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- @Override
- public void visitVarInsn(final int opcode, final int var) {
- switch (opcode) {
- case Opcodes.ILOAD:
- load(var, Type.INT_TYPE);
- break;
- case Opcodes.LLOAD:
- load(var, Type.LONG_TYPE);
- break;
- case Opcodes.FLOAD:
- load(var, Type.FLOAT_TYPE);
- break;
- case Opcodes.DLOAD:
- load(var, Type.DOUBLE_TYPE);
- break;
- case Opcodes.ALOAD:
- load(var, OBJECT_TYPE);
- break;
- case Opcodes.ISTORE:
- store(var, Type.INT_TYPE);
- break;
- case Opcodes.LSTORE:
- store(var, Type.LONG_TYPE);
- break;
- case Opcodes.FSTORE:
- store(var, Type.FLOAT_TYPE);
- break;
- case Opcodes.DSTORE:
- store(var, Type.DOUBLE_TYPE);
- break;
- case Opcodes.ASTORE:
- store(var, OBJECT_TYPE);
- break;
- case Opcodes.RET:
- ret(var);
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- @Override
- public void visitTypeInsn(final int opcode, final String type) {
- Type t = Type.getObjectType(type);
- switch (opcode) {
- case Opcodes.NEW:
- anew(t);
- break;
- case Opcodes.ANEWARRAY:
- newarray(t);
- break;
- case Opcodes.CHECKCAST:
- checkcast(t);
- break;
- case Opcodes.INSTANCEOF:
- instanceOf(t);
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- @Override
- public void visitFieldInsn(final int opcode, final String owner,
- final String name, final String desc) {
- switch (opcode) {
- case Opcodes.GETSTATIC:
- getstatic(owner, name, desc);
- break;
- case Opcodes.PUTSTATIC:
- putstatic(owner, name, desc);
- break;
- case Opcodes.GETFIELD:
- getfield(owner, name, desc);
- break;
- case Opcodes.PUTFIELD:
- putfield(owner, name, desc);
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc) {
- switch (opcode) {
- case Opcodes.INVOKESPECIAL:
- invokespecial(owner, name, desc);
- break;
- case Opcodes.INVOKEVIRTUAL:
- invokevirtual(owner, name, desc);
- break;
- case Opcodes.INVOKESTATIC:
- invokestatic(owner, name, desc);
- break;
- case Opcodes.INVOKEINTERFACE:
- invokeinterface(owner, name, desc);
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- @Override
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- invokedynamic(name, desc, bsm, bsmArgs);
- }
-
- @Override
- public void visitJumpInsn(final int opcode, final Label label) {
- switch (opcode) {
- case Opcodes.IFEQ:
- ifeq(label);
- break;
- case Opcodes.IFNE:
- ifne(label);
- break;
- case Opcodes.IFLT:
- iflt(label);
- break;
- case Opcodes.IFGE:
- ifge(label);
- break;
- case Opcodes.IFGT:
- ifgt(label);
- break;
- case Opcodes.IFLE:
- ifle(label);
- break;
- case Opcodes.IF_ICMPEQ:
- ificmpeq(label);
- break;
- case Opcodes.IF_ICMPNE:
- ificmpne(label);
- break;
- case Opcodes.IF_ICMPLT:
- ificmplt(label);
- break;
- case Opcodes.IF_ICMPGE:
- ificmpge(label);
- break;
- case Opcodes.IF_ICMPGT:
- ificmpgt(label);
- break;
- case Opcodes.IF_ICMPLE:
- ificmple(label);
- break;
- case Opcodes.IF_ACMPEQ:
- ifacmpeq(label);
- break;
- case Opcodes.IF_ACMPNE:
- ifacmpne(label);
- break;
- case Opcodes.GOTO:
- goTo(label);
- break;
- case Opcodes.JSR:
- jsr(label);
- break;
- case Opcodes.IFNULL:
- ifnull(label);
- break;
- case Opcodes.IFNONNULL:
- ifnonnull(label);
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- @Override
- public void visitLabel(final Label label) {
- mark(label);
- }
-
- @Override
- public void visitLdcInsn(final Object cst) {
- if (cst instanceof Integer) {
- int val = ((Integer) cst).intValue();
- iconst(val);
- } else if (cst instanceof Byte) {
- int val = ((Byte) cst).intValue();
- iconst(val);
- } else if (cst instanceof Character) {
- int val = ((Character) cst).charValue();
- iconst(val);
- } else if (cst instanceof Short) {
- int val = ((Short) cst).intValue();
- iconst(val);
- } else if (cst instanceof Boolean) {
- int val = ((Boolean) cst).booleanValue() ? 1 : 0;
- iconst(val);
- } else if (cst instanceof Float) {
- float val = ((Float) cst).floatValue();
- fconst(val);
- } else if (cst instanceof Long) {
- long val = ((Long) cst).longValue();
- lconst(val);
- } else if (cst instanceof Double) {
- double val = ((Double) cst).doubleValue();
- dconst(val);
- } else if (cst instanceof String) {
- aconst(cst);
- } else if (cst instanceof Type) {
- tconst((Type) cst);
- } else if (cst instanceof Handle) {
- hconst((Handle) cst);
- } else {
- throw new IllegalArgumentException();
- }
- }
-
- @Override
- public void visitIincInsn(final int var, final int increment) {
- iinc(var, increment);
- }
-
- @Override
- public void visitTableSwitchInsn(final int min, final int max,
- final Label dflt, final Label... labels) {
- tableswitch(min, max, dflt, labels);
- }
-
- @Override
- public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
- final Label[] labels) {
- lookupswitch(dflt, keys, labels);
- }
-
- @Override
- public void visitMultiANewArrayInsn(final String desc, final int dims) {
- multianewarray(desc, dims);
- }
-
- // -----------------------------------------------------------------------
-
- public void nop() {
- mv.visitInsn(Opcodes.NOP);
- }
-
- public void aconst(final Object cst) {
- if (cst == null) {
- mv.visitInsn(Opcodes.ACONST_NULL);
- } else {
- mv.visitLdcInsn(cst);
- }
- }
-
- public void iconst(final int cst) {
- if (cst >= -1 && cst <= 5) {
- mv.visitInsn(Opcodes.ICONST_0 + cst);
- } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {
- mv.visitIntInsn(Opcodes.BIPUSH, cst);
- } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {
- mv.visitIntInsn(Opcodes.SIPUSH, cst);
- } else {
- mv.visitLdcInsn(new Integer(cst));
- }
- }
-
- public void lconst(final long cst) {
- if (cst == 0L || cst == 1L) {
- mv.visitInsn(Opcodes.LCONST_0 + (int) cst);
- } else {
- mv.visitLdcInsn(new Long(cst));
- }
- }
-
- public void fconst(final float cst) {
- int bits = Float.floatToIntBits(cst);
- if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2
- mv.visitInsn(Opcodes.FCONST_0 + (int) cst);
- } else {
- mv.visitLdcInsn(new Float(cst));
- }
- }
-
- public void dconst(final double cst) {
- long bits = Double.doubleToLongBits(cst);
- if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d
- mv.visitInsn(Opcodes.DCONST_0 + (int) cst);
- } else {
- mv.visitLdcInsn(new Double(cst));
- }
- }
-
- public void tconst(final Type type) {
- mv.visitLdcInsn(type);
- }
-
- public void hconst(final Handle handle) {
- mv.visitLdcInsn(handle);
- }
-
- public void load(final int var, final Type type) {
- mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), var);
- }
-
- public void aload(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
- }
-
- public void store(final int var, final Type type) {
- mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), var);
- }
-
- public void astore(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
- }
-
- public void pop() {
- mv.visitInsn(Opcodes.POP);
- }
-
- public void pop2() {
- mv.visitInsn(Opcodes.POP2);
- }
-
- public void dup() {
- mv.visitInsn(Opcodes.DUP);
- }
-
- public void dup2() {
- mv.visitInsn(Opcodes.DUP2);
- }
-
- public void dupX1() {
- mv.visitInsn(Opcodes.DUP_X1);
- }
-
- public void dupX2() {
- mv.visitInsn(Opcodes.DUP_X2);
- }
-
- public void dup2X1() {
- mv.visitInsn(Opcodes.DUP2_X1);
- }
-
- public void dup2X2() {
- mv.visitInsn(Opcodes.DUP2_X2);
- }
-
- public void swap() {
- mv.visitInsn(Opcodes.SWAP);
- }
-
- public void add(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IADD));
- }
-
- public void sub(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.ISUB));
- }
-
- public void mul(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IMUL));
- }
-
- public void div(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IDIV));
- }
-
- public void rem(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IREM));
- }
-
- public void neg(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.INEG));
- }
-
- public void shl(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.ISHL));
- }
-
- public void shr(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.ISHR));
- }
-
- public void ushr(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IUSHR));
- }
-
- public void and(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IAND));
- }
-
- public void or(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IOR));
- }
-
- public void xor(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IXOR));
- }
-
- public void iinc(final int var, final int increment) {
- mv.visitIincInsn(var, increment);
- }
-
- public void cast(final Type from, final Type to) {
- if (from != to) {
- if (from == Type.DOUBLE_TYPE) {
- if (to == Type.FLOAT_TYPE) {
- mv.visitInsn(Opcodes.D2F);
- } else if (to == Type.LONG_TYPE) {
- mv.visitInsn(Opcodes.D2L);
- } else {
- mv.visitInsn(Opcodes.D2I);
- cast(Type.INT_TYPE, to);
- }
- } else if (from == Type.FLOAT_TYPE) {
- if (to == Type.DOUBLE_TYPE) {
- mv.visitInsn(Opcodes.F2D);
- } else if (to == Type.LONG_TYPE) {
- mv.visitInsn(Opcodes.F2L);
- } else {
- mv.visitInsn(Opcodes.F2I);
- cast(Type.INT_TYPE, to);
- }
- } else if (from == Type.LONG_TYPE) {
- if (to == Type.DOUBLE_TYPE) {
- mv.visitInsn(Opcodes.L2D);
- } else if (to == Type.FLOAT_TYPE) {
- mv.visitInsn(Opcodes.L2F);
- } else {
- mv.visitInsn(Opcodes.L2I);
- cast(Type.INT_TYPE, to);
- }
- } else {
- if (to == Type.BYTE_TYPE) {
- mv.visitInsn(Opcodes.I2B);
- } else if (to == Type.CHAR_TYPE) {
- mv.visitInsn(Opcodes.I2C);
- } else if (to == Type.DOUBLE_TYPE) {
- mv.visitInsn(Opcodes.I2D);
- } else if (to == Type.FLOAT_TYPE) {
- mv.visitInsn(Opcodes.I2F);
- } else if (to == Type.LONG_TYPE) {
- mv.visitInsn(Opcodes.I2L);
- } else if (to == Type.SHORT_TYPE) {
- mv.visitInsn(Opcodes.I2S);
- }
- }
- }
- }
-
- public void lcmp() {
- mv.visitInsn(Opcodes.LCMP);
- }
-
- public void cmpl(final Type type) {
- mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPL : Opcodes.DCMPL);
- }
-
- public void cmpg(final Type type) {
- mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPG : Opcodes.DCMPG);
- }
-
- public void ifeq(final Label label) {
- mv.visitJumpInsn(Opcodes.IFEQ, label);
- }
-
- public void ifne(final Label label) {
- mv.visitJumpInsn(Opcodes.IFNE, label);
- }
-
- public void iflt(final Label label) {
- mv.visitJumpInsn(Opcodes.IFLT, label);
- }
-
- public void ifge(final Label label) {
- mv.visitJumpInsn(Opcodes.IFGE, label);
- }
-
- public void ifgt(final Label label) {
- mv.visitJumpInsn(Opcodes.IFGT, label);
- }
-
- public void ifle(final Label label) {
- mv.visitJumpInsn(Opcodes.IFLE, label);
- }
-
- public void ificmpeq(final Label label) {
- mv.visitJumpInsn(Opcodes.IF_ICMPEQ, label);
- }
-
- public void ificmpne(final Label label) {
- mv.visitJumpInsn(Opcodes.IF_ICMPNE, label);
- }
-
- public void ificmplt(final Label label) {
- mv.visitJumpInsn(Opcodes.IF_ICMPLT, label);
- }
-
- public void ificmpge(final Label label) {
- mv.visitJumpInsn(Opcodes.IF_ICMPGE, label);
- }
-
- public void ificmpgt(final Label label) {
- mv.visitJumpInsn(Opcodes.IF_ICMPGT, label);
- }
-
- public void ificmple(final Label label) {
- mv.visitJumpInsn(Opcodes.IF_ICMPLE, label);
- }
-
- public void ifacmpeq(final Label label) {
- mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
- }
-
- public void ifacmpne(final Label label) {
- mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
- }
-
- public void goTo(final Label label) {
- mv.visitJumpInsn(Opcodes.GOTO, label);
- }
-
- public void jsr(final Label label) {
- mv.visitJumpInsn(Opcodes.JSR, label);
- }
-
- public void ret(final int var) {
- mv.visitVarInsn(Opcodes.RET, var);
- }
-
- public void tableswitch(final int min, final int max, final Label dflt,
- final Label... labels) {
- mv.visitTableSwitchInsn(min, max, dflt, labels);
- }
-
- public void lookupswitch(final Label dflt, final int[] keys,
- final Label[] labels) {
- mv.visitLookupSwitchInsn(dflt, keys, labels);
- }
-
- public void areturn(final Type t) {
- mv.visitInsn(t.getOpcode(Opcodes.IRETURN));
- }
-
- public void getstatic(final String owner, final String name,
- final String desc) {
- mv.visitFieldInsn(Opcodes.GETSTATIC, owner, name, desc);
- }
-
- public void putstatic(final String owner, final String name,
- final String desc) {
- mv.visitFieldInsn(Opcodes.PUTSTATIC, owner, name, desc);
- }
-
- public void getfield(final String owner, final String name,
- final String desc) {
- mv.visitFieldInsn(Opcodes.GETFIELD, owner, name, desc);
- }
-
- public void putfield(final String owner, final String name,
- final String desc) {
- mv.visitFieldInsn(Opcodes.PUTFIELD, owner, name, desc);
- }
-
- public void invokevirtual(final String owner, final String name,
- final String desc) {
- mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc);
- }
-
- public void invokespecial(final String owner, final String name,
- final String desc) {
- mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc);
- }
-
- public void invokestatic(final String owner, final String name,
- final String desc) {
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc);
- }
-
- public void invokeinterface(final String owner, final String name,
- final String desc) {
- mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, desc);
- }
-
- public void invokedynamic(String name, String desc, Handle bsm,
- Object[] bsmArgs) {
- mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
- }
-
- public void anew(final Type type) {
- mv.visitTypeInsn(Opcodes.NEW, type.getInternalName());
- }
-
- public void newarray(final Type type) {
- int typ;
- switch (type.getSort()) {
- case Type.BOOLEAN:
- typ = Opcodes.T_BOOLEAN;
- break;
- case Type.CHAR:
- typ = Opcodes.T_CHAR;
- break;
- case Type.BYTE:
- typ = Opcodes.T_BYTE;
- break;
- case Type.SHORT:
- typ = Opcodes.T_SHORT;
- break;
- case Type.INT:
- typ = Opcodes.T_INT;
- break;
- case Type.FLOAT:
- typ = Opcodes.T_FLOAT;
- break;
- case Type.LONG:
- typ = Opcodes.T_LONG;
- break;
- case Type.DOUBLE:
- typ = Opcodes.T_DOUBLE;
- break;
- default:
- mv.visitTypeInsn(Opcodes.ANEWARRAY, type.getInternalName());
- return;
- }
- mv.visitIntInsn(Opcodes.NEWARRAY, typ);
- }
-
- public void arraylength() {
- mv.visitInsn(Opcodes.ARRAYLENGTH);
- }
-
- public void athrow() {
- mv.visitInsn(Opcodes.ATHROW);
- }
-
- public void checkcast(final Type type) {
- mv.visitTypeInsn(Opcodes.CHECKCAST, type.getInternalName());
- }
-
- public void instanceOf(final Type type) {
- mv.visitTypeInsn(Opcodes.INSTANCEOF, type.getInternalName());
- }
-
- public void monitorenter() {
- mv.visitInsn(Opcodes.MONITORENTER);
- }
-
- public void monitorexit() {
- mv.visitInsn(Opcodes.MONITOREXIT);
- }
-
- public void multianewarray(final String desc, final int dims) {
- mv.visitMultiANewArrayInsn(desc, dims);
- }
-
- public void ifnull(final Label label) {
- mv.visitJumpInsn(Opcodes.IFNULL, label);
- }
-
- public void ifnonnull(final Label label) {
- mv.visitJumpInsn(Opcodes.IFNONNULL, label);
- }
-
- public void mark(final Label label) {
- mv.visitLabel(label);
- }
-}
diff --git a/src/jvm/clojure/asm/commons/LocalVariablesSorter.java b/src/jvm/clojure/asm/commons/LocalVariablesSorter.java
deleted file mode 100644
index 85f23ba..0000000
--- a/src/jvm/clojure/asm/commons/LocalVariablesSorter.java
+++ /dev/null
@@ -1,360 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm.commons;
-
-import clojure.asm.Label;
-import clojure.asm.MethodVisitor;
-import clojure.asm.Opcodes;
-import clojure.asm.Type;
-
-/**
- * A {@link MethodVisitor} that renumbers local variables in their order of
- * appearance. This adapter allows one to easily add new local variables to a
- * method. It may be used by inheriting from this class, but the preferred way
- * of using it is via delegation: the next visitor in the chain can indeed add
- * new locals when needed by calling {@link #newLocal} on this adapter (this
- * requires a reference back to this {@link LocalVariablesSorter}).
- *
- * @author Chris Nokleberg
- * @author Eugene Kuleshov
- * @author Eric Bruneton
- */
-public class LocalVariablesSorter extends MethodVisitor {
-
- private static final Type OBJECT_TYPE = Type
- .getObjectType("java/lang/Object");
-
- /**
- * Mapping from old to new local variable indexes. A local variable at index
- * i of size 1 is remapped to 'mapping[2*i]', while a local variable at
- * index i of size 2 is remapped to 'mapping[2*i+1]'.
- */
- private int[] mapping = new int[40];
-
- /**
- * Array used to store stack map local variable types after remapping.
- */
- private Object[] newLocals = new Object[20];
-
- /**
- * Index of the first local variable, after formal parameters.
- */
- protected final int firstLocal;
-
- /**
- * Index of the next local variable to be created by {@link #newLocal}.
- */
- protected int nextLocal;
-
- /**
- * Indicates if at least one local variable has moved due to remapping.
- */
- private boolean changed;
-
- /**
- * Creates a new {@link LocalVariablesSorter}. <i>Subclasses must not use
- * this constructor</i>. Instead, they must use the
- * {@link #LocalVariablesSorter(int, int, String, MethodVisitor)} version.
- *
- * @param access
- * access flags of the adapted method.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- * @param mv
- * the method visitor to which this adapter delegates calls.
- */
- public LocalVariablesSorter(final int access, final String desc,
- final MethodVisitor mv) {
- this(Opcodes.ASM4, access, desc, mv);
- }
-
- /**
- * Creates a new {@link LocalVariablesSorter}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param access
- * access flags of the adapted method.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- * @param mv
- * the method visitor to which this adapter delegates calls.
- */
- protected LocalVariablesSorter(final int api, final int access,
- final String desc, final MethodVisitor mv) {
- super(api, mv);
- Type[] args = Type.getArgumentTypes(desc);
- nextLocal = (Opcodes.ACC_STATIC & access) == 0 ? 1 : 0;
- for (int i = 0; i < args.length; i++) {
- nextLocal += args[i].getSize();
- }
- firstLocal = nextLocal;
- }
-
- @Override
- public void visitVarInsn(final int opcode, final int var) {
- Type type;
- switch (opcode) {
- case Opcodes.LLOAD:
- case Opcodes.LSTORE:
- type = Type.LONG_TYPE;
- break;
-
- case Opcodes.DLOAD:
- case Opcodes.DSTORE:
- type = Type.DOUBLE_TYPE;
- break;
-
- case Opcodes.FLOAD:
- case Opcodes.FSTORE:
- type = Type.FLOAT_TYPE;
- break;
-
- case Opcodes.ILOAD:
- case Opcodes.ISTORE:
- type = Type.INT_TYPE;
- break;
-
- default:
- // case Opcodes.ALOAD:
- // case Opcodes.ASTORE:
- // case RET:
- type = OBJECT_TYPE;
- break;
- }
- mv.visitVarInsn(opcode, remap(var, type));
- }
-
- @Override
- public void visitIincInsn(final int var, final int increment) {
- mv.visitIincInsn(remap(var, Type.INT_TYPE), increment);
- }
-
- @Override
- public void visitMaxs(final int maxStack, final int maxLocals) {
- mv.visitMaxs(maxStack, nextLocal);
- }
-
- @Override
- public void visitLocalVariable(final String name, final String desc,
- final String signature, final Label start, final Label end,
- final int index) {
- int newIndex = remap(index, Type.getType(desc));
- mv.visitLocalVariable(name, desc, signature, start, end, newIndex);
- }
-
- @Override
- public void visitFrame(final int type, final int nLocal,
- final Object[] local, final int nStack, final Object[] stack) {
- if (type != Opcodes.F_NEW) { // uncompressed frame
- throw new IllegalStateException(
- "ClassReader.accept() should be called with EXPAND_FRAMES flag");
- }
-
- if (!changed) { // optimization for the case where mapping = identity
- mv.visitFrame(type, nLocal, local, nStack, stack);
- return;
- }
-
- // creates a copy of newLocals
- Object[] oldLocals = new Object[newLocals.length];
- System.arraycopy(newLocals, 0, oldLocals, 0, oldLocals.length);
-
- updateNewLocals(newLocals);
-
- // copies types from 'local' to 'newLocals'
- // 'newLocals' already contains the variables added with 'newLocal'
-
- int index = 0; // old local variable index
- int number = 0; // old local variable number
- for (; number < nLocal; ++number) {
- Object t = local[number];
- int size = t == Opcodes.LONG || t == Opcodes.DOUBLE ? 2 : 1;
- if (t != Opcodes.TOP) {
- Type typ = OBJECT_TYPE;
- if (t == Opcodes.INTEGER) {
- typ = Type.INT_TYPE;
- } else if (t == Opcodes.FLOAT) {
- typ = Type.FLOAT_TYPE;
- } else if (t == Opcodes.LONG) {
- typ = Type.LONG_TYPE;
- } else if (t == Opcodes.DOUBLE) {
- typ = Type.DOUBLE_TYPE;
- } else if (t instanceof String) {
- typ = Type.getObjectType((String) t);
- }
- setFrameLocal(remap(index, typ), t);
- }
- index += size;
- }
-
- // removes TOP after long and double types as well as trailing TOPs
-
- index = 0;
- number = 0;
- for (int i = 0; index < newLocals.length; ++i) {
- Object t = newLocals[index++];
- if (t != null && t != Opcodes.TOP) {
- newLocals[i] = t;
- number = i + 1;
- if (t == Opcodes.LONG || t == Opcodes.DOUBLE) {
- index += 1;
- }
- } else {
- newLocals[i] = Opcodes.TOP;
- }
- }
-
- // visits remapped frame
- mv.visitFrame(type, number, newLocals, nStack, stack);
-
- // restores original value of 'newLocals'
- newLocals = oldLocals;
- }
-
- // -------------
-
- /**
- * Creates a new local variable of the given type.
- *
- * @param type
- * the type of the local variable to be created.
- * @return the identifier of the newly created local variable.
- */
- public int newLocal(final Type type) {
- Object t;
- switch (type.getSort()) {
- case Type.BOOLEAN:
- case Type.CHAR:
- case Type.BYTE:
- case Type.SHORT:
- case Type.INT:
- t = Opcodes.INTEGER;
- break;
- case Type.FLOAT:
- t = Opcodes.FLOAT;
- break;
- case Type.LONG:
- t = Opcodes.LONG;
- break;
- case Type.DOUBLE:
- t = Opcodes.DOUBLE;
- break;
- case Type.ARRAY:
- t = type.getDescriptor();
- break;
- // case Type.OBJECT:
- default:
- t = type.getInternalName();
- break;
- }
- int local = newLocalMapping(type);
- setLocalType(local, type);
- setFrameLocal(local, t);
- return local;
- }
-
- /**
- * Notifies subclasses that a new stack map frame is being visited. The
- * array argument contains the stack map frame types corresponding to the
- * local variables added with {@link #newLocal}. This method can update
- * these types in place for the stack map frame being visited. The default
- * implementation of this method does nothing, i.e. a local variable added
- * with {@link #newLocal} will have the same type in all stack map frames.
- * But this behavior is not always the desired one, for instance if a local
- * variable is added in the middle of a try/catch block: the frame for the
- * exception handler should have a TOP type for this new local.
- *
- * @param newLocals
- * the stack map frame types corresponding to the local variables
- * added with {@link #newLocal} (and null for the others). The
- * format of this array is the same as in
- * {@link MethodVisitor#visitFrame}, except that long and double
- * types use two slots. The types for the current stack map frame
- * must be updated in place in this array.
- */
- protected void updateNewLocals(Object[] newLocals) {
- }
-
- /**
- * Notifies subclasses that a local variable has been added or remapped. The
- * default implementation of this method does nothing.
- *
- * @param local
- * a local variable identifier, as returned by {@link #newLocal
- * newLocal()}.
- * @param type
- * the type of the value being stored in the local variable.
- */
- protected void setLocalType(final int local, final Type type) {
- }
-
- private void setFrameLocal(final int local, final Object type) {
- int l = newLocals.length;
- if (local >= l) {
- Object[] a = new Object[Math.max(2 * l, local + 1)];
- System.arraycopy(newLocals, 0, a, 0, l);
- newLocals = a;
- }
- newLocals[local] = type;
- }
-
- private int remap(final int var, final Type type) {
- if (var + type.getSize() <= firstLocal) {
- return var;
- }
- int key = 2 * var + type.getSize() - 1;
- int size = mapping.length;
- if (key >= size) {
- int[] newMapping = new int[Math.max(2 * size, key + 1)];
- System.arraycopy(mapping, 0, newMapping, 0, size);
- mapping = newMapping;
- }
- int value = mapping[key];
- if (value == 0) {
- value = newLocalMapping(type);
- setLocalType(value, type);
- mapping[key] = value + 1;
- } else {
- value--;
- }
- if (value != var) {
- changed = true;
- }
- return value;
- }
-
- protected int newLocalMapping(final Type type) {
- int local = nextLocal;
- nextLocal += type.getSize();
- return local;
- }
-}
diff --git a/src/jvm/clojure/asm/commons/Method.java b/src/jvm/clojure/asm/commons/Method.java
deleted file mode 100644
index ee16c93..0000000
--- a/src/jvm/clojure/asm/commons/Method.java
+++ /dev/null
@@ -1,282 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm.commons;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import clojure.asm.Type;
-
-/**
- * A named method descriptor.
- *
- * @author Juozas Baliuka
- * @author Chris Nokleberg
- * @author Eric Bruneton
- */
-public class Method {
-
- /**
- * The method name.
- */
- private final String name;
-
- /**
- * The method descriptor.
- */
- private final String desc;
-
- /**
- * Maps primitive Java type names to their descriptors.
- */
- private static final Map<String, String> DESCRIPTORS;
-
- static {
- DESCRIPTORS = new HashMap<String, String>();
- DESCRIPTORS.put("void", "V");
- DESCRIPTORS.put("byte", "B");
- DESCRIPTORS.put("char", "C");
- DESCRIPTORS.put("double", "D");
- DESCRIPTORS.put("float", "F");
- DESCRIPTORS.put("int", "I");
- DESCRIPTORS.put("long", "J");
- DESCRIPTORS.put("short", "S");
- DESCRIPTORS.put("boolean", "Z");
- }
-
- /**
- * Creates a new {@link Method}.
- *
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor.
- */
- public Method(final String name, final String desc) {
- this.name = name;
- this.desc = desc;
- }
-
- /**
- * Creates a new {@link Method}.
- *
- * @param name
- * the method's name.
- * @param returnType
- * the method's return type.
- * @param argumentTypes
- * the method's argument types.
- */
- public Method(final String name, final Type returnType,
- final Type[] argumentTypes) {
- this(name, Type.getMethodDescriptor(returnType, argumentTypes));
- }
-
- /**
- * Creates a new {@link Method}.
- *
- * @param m
- * a java.lang.reflect method descriptor
- * @return a {@link Method} corresponding to the given Java method
- * declaration.
- */
- public static Method getMethod(java.lang.reflect.Method m) {
- return new Method(m.getName(), Type.getMethodDescriptor(m));
- }
-
- /**
- * Creates a new {@link Method}.
- *
- * @param c
- * a java.lang.reflect constructor descriptor
- * @return a {@link Method} corresponding to the given Java constructor
- * declaration.
- */
- public static Method getMethod(java.lang.reflect.Constructor<?> c) {
- return new Method("<init>", Type.getConstructorDescriptor(c));
- }
-
- /**
- * Returns a {@link Method} corresponding to the given Java method
- * declaration.
- *
- * @param method
- * a Java method declaration, without argument names, of the form
- * "returnType name (argumentType1, ... argumentTypeN)", where
- * the types are in plain Java (e.g. "int", "float",
- * "java.util.List", ...). Classes of the java.lang package can
- * be specified by their unqualified name; all other classes
- * names must be fully qualified.
- * @return a {@link Method} corresponding to the given Java method
- * declaration.
- * @throws IllegalArgumentException
- * if <code>method</code> could not get parsed.
- */
- public static Method getMethod(final String method)
- throws IllegalArgumentException {
- return getMethod(method, false);
- }
-
- /**
- * Returns a {@link Method} corresponding to the given Java method
- * declaration.
- *
- * @param method
- * a Java method declaration, without argument names, of the form
- * "returnType name (argumentType1, ... argumentTypeN)", where
- * the types are in plain Java (e.g. "int", "float",
- * "java.util.List", ...). Classes of the java.lang package may
- * be specified by their unqualified name, depending on the
- * defaultPackage argument; all other classes names must be fully
- * qualified.
- * @param defaultPackage
- * true if unqualified class names belong to the default package,
- * or false if they correspond to java.lang classes. For instance
- * "Object" means "Object" if this option is true, or
- * "java.lang.Object" otherwise.
- * @return a {@link Method} corresponding to the given Java method
- * declaration.
- * @throws IllegalArgumentException
- * if <code>method</code> could not get parsed.
- */
- public static Method getMethod(final String method,
- final boolean defaultPackage) throws IllegalArgumentException {
- int space = method.indexOf(' ');
- int start = method.indexOf('(', space) + 1;
- int end = method.indexOf(')', start);
- if (space == -1 || start == -1 || end == -1) {
- throw new IllegalArgumentException();
- }
- String returnType = method.substring(0, space);
- String methodName = method.substring(space + 1, start - 1).trim();
- StringBuffer sb = new StringBuffer();
- sb.append('(');
- int p;
- do {
- String s;
- p = method.indexOf(',', start);
- if (p == -1) {
- s = map(method.substring(start, end).trim(), defaultPackage);
- } else {
- s = map(method.substring(start, p).trim(), defaultPackage);
- start = p + 1;
- }
- sb.append(s);
- } while (p != -1);
- sb.append(')');
- sb.append(map(returnType, defaultPackage));
- return new Method(methodName, sb.toString());
- }
-
- private static String map(final String type, final boolean defaultPackage) {
- if ("".equals(type)) {
- return type;
- }
-
- StringBuffer sb = new StringBuffer();
- int index = 0;
- while ((index = type.indexOf("[]", index) + 1) > 0) {
- sb.append('[');
- }
-
- String t = type.substring(0, type.length() - sb.length() * 2);
- String desc = DESCRIPTORS.get(t);
- if (desc != null) {
- sb.append(desc);
- } else {
- sb.append('L');
- if (t.indexOf('.') < 0) {
- if (!defaultPackage) {
- sb.append("java/lang/");
- }
- sb.append(t);
- } else {
- sb.append(t.replace('.', '/'));
- }
- sb.append(';');
- }
- return sb.toString();
- }
-
- /**
- * Returns the name of the method described by this object.
- *
- * @return the name of the method described by this object.
- */
- public String getName() {
- return name;
- }
-
- /**
- * Returns the descriptor of the method described by this object.
- *
- * @return the descriptor of the method described by this object.
- */
- public String getDescriptor() {
- return desc;
- }
-
- /**
- * Returns the return type of the method described by this object.
- *
- * @return the return type of the method described by this object.
- */
- public Type getReturnType() {
- return Type.getReturnType(desc);
- }
-
- /**
- * Returns the argument types of the method described by this object.
- *
- * @return the argument types of the method described by this object.
- */
- public Type[] getArgumentTypes() {
- return Type.getArgumentTypes(desc);
- }
-
- @Override
- public String toString() {
- return name + desc;
- }
-
- @Override
- public boolean equals(final Object o) {
- if (!(o instanceof Method)) {
- return false;
- }
- Method other = (Method) o;
- return name.equals(other.name) && desc.equals(other.desc);
- }
-
- @Override
- public int hashCode() {
- return name.hashCode() ^ desc.hashCode();
- }
-}
\ No newline at end of file
diff --git a/src/jvm/clojure/asm/commons/SerialVersionUIDAdder.java b/src/jvm/clojure/asm/commons/SerialVersionUIDAdder.java
deleted file mode 100644
index 65dd583..0000000
--- a/src/jvm/clojure/asm/commons/SerialVersionUIDAdder.java
+++ /dev/null
@@ -1,533 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm.commons;
-
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutput;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.security.MessageDigest;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-
-import clojure.asm.ClassVisitor;
-import clojure.asm.FieldVisitor;
-import clojure.asm.MethodVisitor;
-import clojure.asm.Opcodes;
-
-/**
- * A {@link ClassVisitor} that adds a serial version unique identifier to a
- * class if missing. Here is typical usage of this class:
- *
- * <pre>
- * ClassWriter cw = new ClassWriter(...);
- * ClassVisitor sv = new SerialVersionUIDAdder(cw);
- * ClassVisitor ca = new MyClassAdapter(sv);
- * new ClassReader(orginalClass).accept(ca, false);
- * </pre>
- *
- * The SVUID algorithm can be found <a href=
- * "http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html"
- * >http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html</a>:
- *
- * <pre>
- * The serialVersionUID is computed using the signature of a stream of bytes
- * that reflect the class definition. The National Institute of Standards and
- * Technology (NIST) Secure Hash Algorithm (SHA-1) is used to compute a
- * signature for the stream. The first two 32-bit quantities are used to form a
- * 64-bit hash. A java.lang.DataOutputStream is used to convert primitive data
- * types to a sequence of bytes. The values input to the stream are defined by
- * the Java Virtual Machine (VM) specification for classes.
- *
- * The sequence of items in the stream is as follows:
- *
- * 1. The class name written using UTF encoding.
- * 2. The class modifiers written as a 32-bit integer.
- * 3. The name of each interface sorted by name written using UTF encoding.
- * 4. For each field of the class sorted by field name (except private static
- * and private transient fields):
- * 1. The name of the field in UTF encoding.
- * 2. The modifiers of the field written as a 32-bit integer.
- * 3. The descriptor of the field in UTF encoding
- * 5. If a class initializer exists, write out the following:
- * 1. The name of the method, <clinit>, in UTF encoding.
- * 2. The modifier of the method, java.lang.reflect.Modifier.STATIC,
- * written as a 32-bit integer.
- * 3. The descriptor of the method, ()V, in UTF encoding.
- * 6. For each non-private constructor sorted by method name and signature:
- * 1. The name of the method, <init>, in UTF encoding.
- * 2. The modifiers of the method written as a 32-bit integer.
- * 3. The descriptor of the method in UTF encoding.
- * 7. For each non-private method sorted by method name and signature:
- * 1. The name of the method in UTF encoding.
- * 2. The modifiers of the method written as a 32-bit integer.
- * 3. The descriptor of the method in UTF encoding.
- * 8. The SHA-1 algorithm is executed on the stream of bytes produced by
- * DataOutputStream and produces five 32-bit values sha[0..4].
- *
- * 9. The hash value is assembled from the first and second 32-bit values of
- * the SHA-1 message digest. If the result of the message digest, the five
- * 32-bit words H0 H1 H2 H3 H4, is in an array of five int values named
- * sha, the hash value would be computed as follows:
- *
- * long hash = ((sha[0] >>> 24) & 0xFF) |
- * ((sha[0] >>> 16) & 0xFF) << 8 |
- * ((sha[0] >>> 8) & 0xFF) << 16 |
- * ((sha[0] >>> 0) & 0xFF) << 24 |
- * ((sha[1] >>> 24) & 0xFF) << 32 |
- * ((sha[1] >>> 16) & 0xFF) << 40 |
- * ((sha[1] >>> 8) & 0xFF) << 48 |
- * ((sha[1] >>> 0) & 0xFF) << 56;
- * </pre>
- *
- * @author Rajendra Inamdar, Vishal Vishnoi
- */
-public class SerialVersionUIDAdder extends ClassVisitor {
-
- /**
- * Flag that indicates if we need to compute SVUID.
- */
- private boolean computeSVUID;
-
- /**
- * Set to true if the class already has SVUID.
- */
- private boolean hasSVUID;
-
- /**
- * Classes access flags.
- */
- private int access;
-
- /**
- * Internal name of the class
- */
- private String name;
-
- /**
- * Interfaces implemented by the class.
- */
- private String[] interfaces;
-
- /**
- * Collection of fields. (except private static and private transient
- * fields)
- */
- private Collection<Item> svuidFields;
-
- /**
- * Set to true if the class has static initializer.
- */
- private boolean hasStaticInitializer;
-
- /**
- * Collection of non-private constructors.
- */
- private Collection<Item> svuidConstructors;
-
- /**
- * Collection of non-private methods.
- */
- private Collection<Item> svuidMethods;
-
- /**
- * Creates a new {@link SerialVersionUIDAdder}. <i>Subclasses must not use
- * this constructor</i>. Instead, they must use the
- * {@link #SerialVersionUIDAdder(int, ClassVisitor)} version.
- *
- * @param cv
- * a {@link ClassVisitor} to which this visitor will delegate
- * calls.
- */
- public SerialVersionUIDAdder(final ClassVisitor cv) {
- this(Opcodes.ASM4, cv);
- }
-
- /**
- * Creates a new {@link SerialVersionUIDAdder}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param cv
- * a {@link ClassVisitor} to which this visitor will delegate
- * calls.
- */
- protected SerialVersionUIDAdder(final int api, final ClassVisitor cv) {
- super(api, cv);
- svuidFields = new ArrayList<Item>();
- svuidConstructors = new ArrayList<Item>();
- svuidMethods = new ArrayList<Item>();
- }
-
- // ------------------------------------------------------------------------
- // Overriden methods
- // ------------------------------------------------------------------------
-
- /*
- * Visit class header and get class name, access , and interfaces
- * information (step 1,2, and 3) for SVUID computation.
- */
- @Override
- public void visit(final int version, final int access, final String name,
- final String signature, final String superName,
- final String[] interfaces) {
- computeSVUID = (access & Opcodes.ACC_INTERFACE) == 0;
-
- if (computeSVUID) {
- this.name = name;
- this.access = access;
- this.interfaces = interfaces;
- }
-
- super.visit(version, access, name, signature, superName, interfaces);
- }
-
- /*
- * Visit the methods and get constructor and method information (step 5 and
- * 7). Also determine if there is a class initializer (step 6).
- */
- @Override
- public MethodVisitor visitMethod(final int access, final String name,
- final String desc, final String signature, final String[] exceptions) {
- if (computeSVUID) {
- if ("<clinit>".equals(name)) {
- hasStaticInitializer = true;
- }
- /*
- * Remembers non private constructors and methods for SVUID
- * computation For constructor and method modifiers, only the
- * ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
- * ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT and ACC_STRICT flags
- * are used.
- */
- int mods = access
- & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE
- | Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
- | Opcodes.ACC_FINAL | Opcodes.ACC_SYNCHRONIZED
- | Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_STRICT);
-
- // all non private methods
- if ((access & Opcodes.ACC_PRIVATE) == 0) {
- if ("<init>".equals(name)) {
- svuidConstructors.add(new Item(name, mods, desc));
- } else if (!"<clinit>".equals(name)) {
- svuidMethods.add(new Item(name, mods, desc));
- }
- }
- }
-
- return super.visitMethod(access, name, desc, signature, exceptions);
- }
-
- /*
- * Gets class field information for step 4 of the algorithm. Also determines
- * if the class already has a SVUID.
- */
- @Override
- public FieldVisitor visitField(final int access, final String name,
- final String desc, final String signature, final Object value) {
- if (computeSVUID) {
- if ("serialVersionUID".equals(name)) {
- // since the class already has SVUID, we won't be computing it.
- computeSVUID = false;
- hasSVUID = true;
- }
- /*
- * Remember field for SVUID computation For field modifiers, only
- * the ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC,
- * ACC_FINAL, ACC_VOLATILE, and ACC_TRANSIENT flags are used when
- * computing serialVersionUID values.
- */
- if ((access & Opcodes.ACC_PRIVATE) == 0
- || (access & (Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT)) == 0) {
- int mods = access
- & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE
- | Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
- | Opcodes.ACC_FINAL | Opcodes.ACC_VOLATILE | Opcodes.ACC_TRANSIENT);
- svuidFields.add(new Item(name, mods, desc));
- }
- }
-
- return super.visitField(access, name, desc, signature, value);
- }
-
- /**
- * Handle a bizarre special case. Nested classes (static classes declared
- * inside another class) that are protected have their access bit set to
- * public in their class files to deal with some odd reflection situation.
- * Our SVUID computation must do as the JVM does and ignore access bits in
- * the class file in favor of the access bits InnerClass attribute.
- */
- @Override
- public void visitInnerClass(final String aname, final String outerName,
- final String innerName, final int attr_access) {
- if ((name != null) && name.equals(aname)) {
- this.access = attr_access;
- }
- super.visitInnerClass(aname, outerName, innerName, attr_access);
- }
-
- /*
- * Add the SVUID if class doesn't have one
- */
- @Override
- public void visitEnd() {
- // compute SVUID and add it to the class
- if (computeSVUID && !hasSVUID) {
- try {
- addSVUID(computeSVUID());
- } catch (Throwable e) {
- throw new RuntimeException("Error while computing SVUID for "
- + name, e);
- }
- }
-
- super.visitEnd();
- }
-
- // ------------------------------------------------------------------------
- // Utility methods
- // ------------------------------------------------------------------------
-
- /**
- * Returns true if the class already has a SVUID field. The result of this
- * method is only valid when visitEnd is or has been called.
- *
- * @return true if the class already has a SVUID field.
- */
- public boolean hasSVUID() {
- return hasSVUID;
- }
-
- protected void addSVUID(long svuid) {
- FieldVisitor fv = super.visitField(Opcodes.ACC_FINAL
- + Opcodes.ACC_STATIC, "serialVersionUID", "J", null, new Long(
- svuid));
- if (fv != null) {
- fv.visitEnd();
- }
- }
-
- /**
- * Computes and returns the value of SVUID.
- *
- * @return Returns the serial version UID
- * @throws IOException
- * if an I/O error occurs
- */
- protected long computeSVUID() throws IOException {
- ByteArrayOutputStream bos;
- DataOutputStream dos = null;
- long svuid = 0;
-
- try {
- bos = new ByteArrayOutputStream();
- dos = new DataOutputStream(bos);
-
- /*
- * 1. The class name written using UTF encoding.
- */
- dos.writeUTF(name.replace('/', '.'));
-
- /*
- * 2. The class modifiers written as a 32-bit integer.
- */
- dos.writeInt(access
- & (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL
- | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT));
-
- /*
- * 3. The name of each interface sorted by name written using UTF
- * encoding.
- */
- Arrays.sort(interfaces);
- for (int i = 0; i < interfaces.length; i++) {
- dos.writeUTF(interfaces[i].replace('/', '.'));
- }
-
- /*
- * 4. For each field of the class sorted by field name (except
- * private static and private transient fields):
- *
- * 1. The name of the field in UTF encoding. 2. The modifiers of the
- * field written as a 32-bit integer. 3. The descriptor of the field
- * in UTF encoding
- *
- * Note that field signatures are not dot separated. Method and
- * constructor signatures are dot separated. Go figure...
- */
- writeItems(svuidFields, dos, false);
-
- /*
- * 5. If a class initializer exists, write out the following: 1. The
- * name of the method, <clinit>, in UTF encoding. 2. The modifier of
- * the method, java.lang.reflect.Modifier.STATIC, written as a
- * 32-bit integer. 3. The descriptor of the method, ()V, in UTF
- * encoding.
- */
- if (hasStaticInitializer) {
- dos.writeUTF("<clinit>");
- dos.writeInt(Opcodes.ACC_STATIC);
- dos.writeUTF("()V");
- } // if..
-
- /*
- * 6. For each non-private constructor sorted by method name and
- * signature: 1. The name of the method, <init>, in UTF encoding. 2.
- * The modifiers of the method written as a 32-bit integer. 3. The
- * descriptor of the method in UTF encoding.
- */
- writeItems(svuidConstructors, dos, true);
-
- /*
- * 7. For each non-private method sorted by method name and
- * signature: 1. The name of the method in UTF encoding. 2. The
- * modifiers of the method written as a 32-bit integer. 3. The
- * descriptor of the method in UTF encoding.
- */
- writeItems(svuidMethods, dos, true);
-
- dos.flush();
-
- /*
- * 8. The SHA-1 algorithm is executed on the stream of bytes
- * produced by DataOutputStream and produces five 32-bit values
- * sha[0..4].
- */
- byte[] hashBytes = computeSHAdigest(bos.toByteArray());
-
- /*
- * 9. The hash value is assembled from the first and second 32-bit
- * values of the SHA-1 message digest. If the result of the message
- * digest, the five 32-bit words H0 H1 H2 H3 H4, is in an array of
- * five int values named sha, the hash value would be computed as
- * follows:
- *
- * long hash = ((sha[0] >>> 24) & 0xFF) | ((sha[0] >>> 16) & 0xFF)
- * << 8 | ((sha[0] >>> 8) & 0xFF) << 16 | ((sha[0] >>> 0) & 0xFF) <<
- * 24 | ((sha[1] >>> 24) & 0xFF) << 32 | ((sha[1] >>> 16) & 0xFF) <<
- * 40 | ((sha[1] >>> 8) & 0xFF) << 48 | ((sha[1] >>> 0) & 0xFF) <<
- * 56;
- */
- for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
- svuid = (svuid << 8) | (hashBytes[i] & 0xFF);
- }
- } finally {
- // close the stream (if open)
- if (dos != null) {
- dos.close();
- }
- }
-
- return svuid;
- }
-
- /**
- * Returns the SHA-1 message digest of the given value.
- *
- * @param value
- * the value whose SHA message digest must be computed.
- * @return the SHA-1 message digest of the given value.
- */
- protected byte[] computeSHAdigest(final byte[] value) {
- try {
- return MessageDigest.getInstance("SHA").digest(value);
- } catch (Exception e) {
- throw new UnsupportedOperationException(e.toString());
- }
- }
-
- /**
- * Sorts the items in the collection and writes it to the data output stream
- *
- * @param itemCollection
- * collection of items
- * @param dos
- * a <code>DataOutputStream</code> value
- * @param dotted
- * a <code>boolean</code> value
- * @exception IOException
- * if an error occurs
- */
- private static void writeItems(final Collection<Item> itemCollection,
- final DataOutput dos, final boolean dotted) throws IOException {
- int size = itemCollection.size();
- Item[] items = itemCollection.toArray(new Item[size]);
- Arrays.sort(items);
- for (int i = 0; i < size; i++) {
- dos.writeUTF(items[i].name);
- dos.writeInt(items[i].access);
- dos.writeUTF(dotted ? items[i].desc.replace('/', '.')
- : items[i].desc);
- }
- }
-
- // ------------------------------------------------------------------------
- // Inner classes
- // ------------------------------------------------------------------------
-
- private static class Item implements Comparable<Item> {
-
- final String name;
-
- final int access;
-
- final String desc;
-
- Item(final String name, final int access, final String desc) {
- this.name = name;
- this.access = access;
- this.desc = desc;
- }
-
- public int compareTo(final Item other) {
- int retVal = name.compareTo(other.name);
- if (retVal == 0) {
- retVal = desc.compareTo(other.desc);
- }
- return retVal;
- }
-
- @Override
- public boolean equals(final Object o) {
- if (o instanceof Item) {
- return compareTo((Item) o) == 0;
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return (name + desc).hashCode();
- }
- }
-}
diff --git a/src/jvm/clojure/asm/commons/StaticInitMerger.java b/src/jvm/clojure/asm/commons/StaticInitMerger.java
deleted file mode 100644
index 1be4dcd..0000000
--- a/src/jvm/clojure/asm/commons/StaticInitMerger.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm.commons;
-
-import clojure.asm.ClassVisitor;
-import clojure.asm.MethodVisitor;
-import clojure.asm.Opcodes;
-
-/**
- * A {@link ClassVisitor} that merges clinit methods into a single one.
- *
- * @author Eric Bruneton
- */
-public class StaticInitMerger extends ClassVisitor {
-
- private String name;
-
- private MethodVisitor clinit;
-
- private final String prefix;
-
- private int counter;
-
- public StaticInitMerger(final String prefix, final ClassVisitor cv) {
- this(Opcodes.ASM4, prefix, cv);
- }
-
- protected StaticInitMerger(final int api, final String prefix,
- final ClassVisitor cv) {
- super(api, cv);
- this.prefix = prefix;
- }
-
- @Override
- public void visit(final int version, final int access, final String name,
- final String signature, final String superName,
- final String[] interfaces) {
- cv.visit(version, access, name, signature, superName, interfaces);
- this.name = name;
- }
-
- @Override
- public MethodVisitor visitMethod(final int access, final String name,
- final String desc, final String signature, final String[] exceptions) {
- MethodVisitor mv;
- if ("<clinit>".equals(name)) {
- int a = Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC;
- String n = prefix + counter++;
- mv = cv.visitMethod(a, n, desc, signature, exceptions);
-
- if (clinit == null) {
- clinit = cv.visitMethod(a, name, desc, null, null);
- }
- clinit.visitMethodInsn(Opcodes.INVOKESTATIC, this.name, n, desc);
- } else {
- mv = cv.visitMethod(access, name, desc, signature, exceptions);
- }
- return mv;
- }
-
- @Override
- public void visitEnd() {
- if (clinit != null) {
- clinit.visitInsn(Opcodes.RETURN);
- clinit.visitMaxs(0, 0);
- }
- cv.visitEnd();
- }
-}
diff --git a/src/jvm/clojure/asm/commons/TableSwitchGenerator.java b/src/jvm/clojure/asm/commons/TableSwitchGenerator.java
deleted file mode 100644
index 7c1cf6e..0000000
--- a/src/jvm/clojure/asm/commons/TableSwitchGenerator.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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 clojure.asm.commons;
-
-import clojure.asm.Label;
-
-/**
- * A code generator for switch statements.
- *
- * @author Juozas Baliuka
- * @author Chris Nokleberg
- * @author Eric Bruneton
- */
-public interface TableSwitchGenerator {
-
- /**
- * Generates the code for a switch case.
- *
- * @param key
- * the switch case key.
- * @param end
- * a label that corresponds to the end of the switch statement.
- */
- void generateCase(int key, Label end);
-
- /**
- * Generates the code for the default switch case.
- */
- void generateDefault();
-}
diff --git a/src/jvm/clojure/asm/commons/package.html b/src/jvm/clojure/asm/commons/package.html
deleted file mode 100644
index 4ce0db8..0000000
--- a/src/jvm/clojure/asm/commons/package.html
+++ /dev/null
@@ -1,48 +0,0 @@
-<html>
-<!--
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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.
--->
-<body>
-Provides some useful class and method adapters. <i>The preferred way of using
-these adapters is by chaining them together and to custom adapters (instead of
-inheriting from them)</i>. Indeed this approach provides more combination
-possibilities than inheritance. For instance, suppose you want to implement an
-adapter MyAdapter than needs sorted local variables and intermediate stack map
-frame values taking into account the local variables sort. By using inheritance,
-this would require MyAdapter to extend AnalyzerAdapter, itself extending
-LocalVariablesSorter. But AnalyzerAdapter is not a subclass of
-LocalVariablesSorter, so this is not possible. On the contrary, by using
-delegation, you can make LocalVariablesSorter delegate to AnalyzerAdapter,
-itself delegating to MyAdapter. In this case AnalyzerAdapter computes
-intermediate frames based on the output of LocalVariablesSorter, and MyAdapter
-can add new locals by calling the newLocal method on LocalVariablesSorter, and
-can get the stack map frame state before each instruction by reading the locals
-and stack fields in AnalyzerAdapter (this requires references from MyAdapter
-back to LocalVariablesSorter and AnalyzerAdapter).
-</body>
\ No newline at end of file
diff --git a/src/jvm/clojure/asm/package.html b/src/jvm/clojure/asm/package.html
deleted file mode 100644
index 82c1ff9..0000000
--- a/src/jvm/clojure/asm/package.html
+++ /dev/null
@@ -1,87 +0,0 @@
-<html>
-<!--
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 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.
--->
-<body>
-Provides a small and fast bytecode manipulation framework.
-
-<p>
-The <a href="http://www.objectweb.org/asm">ASM</a> framework is organized
-around the {@link clojure.asm.ClassVisitor ClassVisitor},
-{@link clojure.asm.FieldVisitor FieldVisitor},
-{@link clojure.asm.MethodVisitor MethodVisitor} and
-{@link clojure.asm.AnnotationVisitor AnnotationVisitor} abstract classes,
-which allow one to visit the fields, methods and annotations of a class,
-including the bytecode instructions of each method.
-
-<p>
-In addition to these main abstract classes, ASM provides a {@link
-clojure.asm.ClassReader ClassReader} class, that can parse an
-existing class and make a given visitor visit it. ASM also provides
-a {@link clojure.asm.ClassWriter ClassWriter} class, which is
-a visitor that generates Java class files.
-
-<p>
-In order to generate a class from scratch, only the {@link
-clojure.asm.ClassWriter ClassWriter} class is necessary. Indeed,
-in order to generate a class, one must just call its visit<i>Xxx</i>
-methods with the appropriate arguments to generate the desired fields
-and methods. See the "helloworld" example in the ASM distribution for
-more details about class generation.
-
-<p>
-In order to modify existing classes, one must use a {@link
-clojure.asm.ClassReader ClassReader} class to analyze
-the original class, a class modifier, and a {@link clojure.asm.ClassWriter
-ClassWriter} to construct the modified class. The class modifier
-is just a {@link clojure.asm.ClassVisitor ClassVisitor}
-that delegates most of the work to another {@link clojure.asm.ClassVisitor
-ClassVisitor}, but that sometimes changes some parameter values,
-or call additional methods, in order to implement the desired
-modification process. In order to make it easier to implement such
-class modifiers, the {@link clojure.asm.ClassVisitor
-ClassVisitor} and {@link clojure.asm.MethodVisitor MethodVisitor}
-classes delegate by default all the method calls they receive to an
-optional visitor. See the "adapt" example in the ASM
-distribution for more details about class modification.
-
-<p>
-The size of the core ASM library, <tt>asm.jar</tt>, is only 45KB, which is much
-smaller than the size of the
-<a href="http://jakarta.apache.org/bcel">BCEL</a> library (504KB), and than the
-size of the
-<a href="http://serp.sourceforge.net">SERP</a> library (150KB). ASM is also
-much faster than these tools. Indeed the overhead of a load time class
-transformation process is of the order of 60% with ASM, 700% or more with BCEL,
-and 1100% or more with SERP (see the <tt>test/perf</tt> directory in the ASM
-distribution)!
-
- at since ASM 1.3
-</body>
-</html>
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/clojure.git
More information about the pkg-java-commits
mailing list