diff -Nru mvel-2.0.19/META-INF/MANIFEST.MF mvel-2.0.19-gil/META-INF/MANIFEST.MF --- mvel-2.0.19/META-INF/MANIFEST.MF 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/META-INF/MANIFEST.MF 2012-05-26 20:03:01.182447003 +0200 @@ -2,53 +2,52 @@ Export-Package: org.mvel2;uses:="org.mvel2.util,org.mvel2.conversion,o rg.mvel2.integration.impl,org.mvel2.optimizers.impl.refl.nodes,org.mv el2.integration,org.mvel2.compiler,org.mvel2.ast,org.mvel2.debug";ver - sion="2.0.19",org.mvel2.asm;version="2.0.19",org.mvel2.asm.signature; - version="2.0.19",org.mvel2.asm.util;uses:="org.mvel2.asm,org.mvel2.as - m.signature";version="2.0.19",org.mvel2.ast;uses:="org.mvel2.integrat - ion,org.mvel2.optimizers,org.mvel2,org.mvel2.debug,org.mvel2.compiler - ,org.mvel2.util,org.mvel2.math,org.mvel2.integration.impl";version="2 - .0.19",org.mvel2.compiler;uses:="org.mvel2.integration,org.mvel2,org. - mvel2.util,org.mvel2.ast,org.mvel2.optimizers,org.mvel2.integration.i - mpl,org.mvel2.optimizers.impl.refl.nodes";version="2.0.19",org.mvel2. - conversion;uses:="org.mvel2,org.mvel2.compiler";version="2.0.19",org. - mvel2.debug;uses:="org.mvel2.integration,org.mvel2.util,org.mvel2.ast - ,org.mvel2.compiler,org.mvel2";version="2.0.19",org.mvel2.integration - ;uses:="org.mvel2.ast";version="2.0.19",org.mvel2.integration.impl;us - es:="org.mvel2.integration,org.mvel2,org.mvel2.ast,org.mvel2.util";ve - rsion="2.0.19",org.mvel2.math;uses:="org.mvel2,org.mvel2.debug,org.mv - el2.util";version="2.0.19",org.mvel2.optimizers;uses:="org.mvel2,org. - mvel2.util,org.mvel2.compiler,org.mvel2.integration,org.mvel2.optimiz - ers.dynamic,org.mvel2.optimizers.impl.asm,org.mvel2.optimizers.impl.r - efl";version="2.0.19",org.mvel2.optimizers.dynamic;uses:="org.mvel2.c - ompiler,org.mvel2.util,org.mvel2.integration,org.mvel2.optimizers,org - .mvel2,org.mvel2.optimizers.impl.asm";version="2.0.19",org.mvel2.opti - mizers.impl.asm;uses:="org.mvel2.integration,org.mvel2.optimizers.imp - l.refl.nodes,org.mvel2.util,org.mvel2.asm,org.mvel2.optimizers,org.mv - el2,org.mvel2.compiler,org.mvel2.ast";version="2.0.19",org.mvel2.opti - mizers.impl.refl;uses:="org.mvel2.optimizers.impl.refl.nodes,org.mvel - 2.integration,org.mvel2.util,org.mvel2.optimizers.impl.refl.collectio - n,org.mvel2.optimizers,org.mvel2,org.mvel2.compiler,org.mvel2.ast";ve - rsion="2.0.19",org.mvel2.optimizers.impl.refl.collection;uses:="org.m - vel2.integration,org.mvel2.compiler,org.mvel2,org.mvel2.util";version - ="2.0.19",org.mvel2.optimizers.impl.refl.nodes;uses:="org.mvel2.integ - ration,org.mvel2.compiler,org.mvel2,org.mvel2.util,org.mvel2.ast,org. - mvel2.optimizers";version="2.0.19",org.mvel2.sh;uses:="org.mvel2,org. - mvel2.templates,org.mvel2.integration.impl,org.mvel2.integration,org. - mvel2.util,org.mvel2.sh.command.basic,org.mvel2.sh.command.file";vers - ion="2.0.19",org.mvel2.sh.command.basic;uses:="org.mvel2.sh,org.mvel2 - .sh.text,org.mvel2.util,org.mvel2";version="2.0.19",org.mvel2.sh.comm - and.file;uses:="org.mvel2.sh";version="2.0.19",org.mvel2.sh.text;uses - :="org.mvel2.util";version="2.0.19",org.mvel2.templates;uses:="org.mv - el2.templates.res,org.mvel2.templates.util,org.mvel2,org.mvel2.util,o - rg.mvel2.integration.impl,org.mvel2.integration,org.mvel2.templates.u - til.io";version="2.0.19",org.mvel2.templates.res;uses:="org.mvel2.tem - plates,org.mvel2.integration,org.mvel2.templates.util,org.mvel2,org.m - vel2.util,org.mvel2.integration.impl";version="2.0.19",org.mvel2.temp - lates.util;uses:="org.mvel2.templates.res,org.mvel2.templates,org.mve - l2.util";version="2.0.19",org.mvel2.templates.util.io;uses:="org.mvel - 2.templates.util,org.mvel2.util";version="2.0.19",org.mvel2.util;uses - :="org.mvel2.ast,org.mvel2.integration,org.mvel2,org.mvel2.compiler,o - rg.mvel2.integration.impl,org.mvel2.math,sun.misc";version="2.0.19" + sion="2.0.19",org.mvel2.ast;uses:="org.mvel2.integration,org.mvel2.op + timizers,org.mvel2,org.mvel2.debug,org.mvel2.compiler,org.mvel2.util, + org.mvel2.math,org.mvel2.integration.impl";version="2.0.19",org.mvel2. + compiler;uses:="org.mvel2.integration,org.mvel2,org.mvel2.util,org.mve + l2.ast,org.mvel2.optimizers,org.mvel2.integration.impl,org.mvel2.optim + izers.impl.refl.nodes";version="2.0.19",org.mvel2.conversion;uses:="or + g.mvel2,org.mvel2.compiler";version="2.0.19",org.mvel2.debug;uses:="or + g.mvel2.integration,org.mvel2.util,org.mvel2.ast,org.mvel2.compiler,or + g.mvel2";version="2.0.19",org.mvel2.integration;uses:="org.mvel2.ast"; + version="2.0.19",org.mvel2.integration.impl;uses:="org.mvel2.integrati + on,org.mvel2,org.mvel2.ast,org.mvel2.util";version="2.0.19",org.mvel2. + math;uses:="org.mvel2,org.mvel2.debug,org.mvel2.util";version="2.0.19" + ,org.mvel2.optimizers;uses:="org.mvel2,org.mvel2.util,org.mvel2.compil + er,org.mvel2.integration,org.mvel2.optimizers.dynamic,org.mvel2.optimi + zers.impl.asm,org.mvel2.optimizers.impl.refl";version="2.0.19",org.mve + l2.optimizers.dynamic;uses:="org.mvel2.compiler,org.mvel2.util,org.mve + l2.integration,org.mvel2.optimizers,org.mvel2,org.mvel2.optimizers.imp + l.asm";version="2.0.19",org.mvel2.optimizers.impl.asm;uses:="org.mvel2 + .integration,org.mvel2.optimizers.impl.refl.nodes,org.mvel2.util,org.o + bjectweb.asm,org.mvel2.optimizers,org.mvel2,org.mvel2.compiler,org.mvel + 2.ast";version="2.0.19",org.mvel2.optimizers.impl.refl;uses:="org.mvel2 + .optimizers.impl.refl.nodes,org.mvel2.integration,org.mvel2.util,org.mv + el2.optimizers.impl.refl.collection,org.mvel2.optimizers,org.mvel2,org. + mvel2.compiler,org.mvel2.ast";version="2.0.19",org.mvel2.optimizers.imp + l.refl.collection;uses:="org.mvel2.integration,org.mvel2.compiler,org.m + vel2,org.mvel2.util";version="2.0.19",org.mvel2.optimizers.impl.refl.no + des;uses:="org.mvel2.integration,org.mvel2.compiler,org.mvel2,org.mvel2 + .util,org.mvel2.ast,org.mvel2.optimizers";version="2.0.19",org.mvel2.sh + ;uses:="org.mvel2,org.mvel2.templates,org.mvel2.integration.impl,org.mve + l2.integration,org.mvel2.util,org.mvel2.sh.command.basic,org.mvel2.sh.co + mmand.file";version="2.0.19",org.mvel2.sh.command.basic;uses:="org.mvel2 + .sh,org.mvel2.sh.text,org.mvel2.util,org.mvel2";version="2.0.19",org.mve + l2.sh.command.file;uses:="org.mvel2.sh";version="2.0.19",org.mvel2.sh.te + xt;uses:="org.mvel2.util";version="2.0.19",org.mvel2.templates;uses:="or + g.mvel2.templates.res,org.mvel2.templates.util,org.mvel2,org.mvel2.util,o + rg.mvel2.integration.impl,org.mvel2.integration,org.mvel2.templates.util. + io";version="2.0.19",org.mvel2.templates.res;uses:="org.mvel2.templates, + org.mvel2.integration,org.mvel2.templates.util,org.mvel2,org.mvel2.util, + org.mvel2.integration.impl";version="2.0.19",org.mvel2.templates.util;use + s:="org.mvel2.templates.res,org.mvel2.templates,org.mvel2.util";version=" + 2.0.19",org.mvel2.templates.util.io;uses:="org.mvel2.templates.util,org.m + vel2.util";version="2.0.19",org.mvel2.util;uses:="org.mvel2.ast,org.mvel + 2.integration,org.mvel2,org.mvel2.compiler,org.mvel2.integration.impl,or + g.mvel2.math,sun.misc";version="2.0.19",org.objectweb.asm;version="3.3.1" + ,org.objectweb.asm.signature;version="3.3.1",org.mvel2.asm.util;uses:="o + rg.objectweb.asm,org.objectweb.asm.signature";version="3.3.1" Bundle-Version: 2.0.19 Tool: Bnd-0.0.357 Bundle-Name: mvel2 @@ -56,19 +55,17 @@ Created-By: 1.6.0_21 (Apple Inc.) Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.mvel2 -Import-Package: org.mvel2;version="2.0",org.mvel2.asm;version="2.0",or - g.mvel2.asm.signature;version="2.0",org.mvel2.asm.util;version="2.0", - org.mvel2.ast;version="2.0",org.mvel2.compiler;version="2.0",org.mvel - 2.conversion;version="2.0",org.mvel2.debug;version="2.0",org.mvel2.in - tegration;version="2.0",org.mvel2.integration.impl;version="2.0",org. - mvel2.math;version="2.0",org.mvel2.optimizers;version="2.0",org.mvel2 - .optimizers.dynamic;version="2.0",org.mvel2.optimizers.impl.asm;versi - on="2.0",org.mvel2.optimizers.impl.refl;version="2.0",org.mvel2.optim - izers.impl.refl.collection;version="2.0",org.mvel2.optimizers.impl.re - fl.nodes;version="2.0",org.mvel2.sh;version="2.0",org.mvel2.sh.comman - d.basic;version="2.0",org.mvel2.sh.command.file;version="2.0",org.mve - l2.sh.text;version="2.0",org.mvel2.templates;version="2.0",org.mvel2. - templates.res;version="2.0",org.mvel2.templates.util;version="2.0",or - g.mvel2.templates.util.io;version="2.0",org.mvel2.util;version="2.0", - sun.misc;resolution:=optional +Import-Package: org.mvel2;version="2.0",org.mvel2.ast;version="2.0", + org.mvel2.compiler;version="2.0",org.mvel2.conversion;version="2.0", + org.mvel2.debug;version="2.0",org.mvel2.integration;version="2.0",o + rg.mvel2.integration.impl;version="2.0",org.mvel2.math;version="2.0", + org.mvel2.optimizers;version="2.0",org.mvel2.optimizers.dynamic;versi + on="2.0",org.mvel2.optimizers.impl.asm;version="2.0",org.mvel2.optimi + zers.impl.refl;version="2.0",org.mvel2.optimizers.impl.refl.collectio + n;version="2.0",org.mvel2.optimizers.impl.refl.nodes;version="2.0",or + g.mvel2.sh;version="2.0",org.mvel2.sh.command.basic;version="2.0",org + .mvel2.sh.command.file;version="2.0",org.mvel2.sh.text;version="2.0", + org.mvel2.templates;version="2.0",org.mvel2.templates.res;version="2.0" + ,org.mvel2.templates.util;version="2.0",org.mvel2.templates.util.io;ver + sion="2.0",org.mvel2.util;version="2.0",sun.misc;resolution:=optional diff -Nru mvel-2.0.19/pom.xml mvel-2.0.19-gil/pom.xml --- mvel-2.0.19/pom.xml 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/pom.xml 2012-05-26 19:29:54.883461242 +0200 @@ -20,13 +20,13 @@ </pluginRepositories> <build> - <extensions> + <!--extensions> <extension> <groupId>org.apache.maven.wagon</groupId> <artifactId>wagon-webdav</artifactId> <version>1.0-beta-2</version> </extension> - </extensions> + </extensions--> <plugins> <plugin> @@ -156,6 +156,19 @@ <dependencies> <dependency> + <groupId>asm</groupId> + <artifactId>asm</artifactId> + <version>3.3.1</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>asm</groupId> + <artifactId>asm-util</artifactId> + <version>3.3.1</version> + <scope>compile</scope> + </dependency> + + <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/AnnotationVisitor.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/AnnotationVisitor.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/AnnotationVisitor.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/AnnotationVisitor.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,97 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm; - -/** - * A visitor to visit a Java annotation. The methods of this interface 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 interface AnnotationVisitor { - - /** - * 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}. 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). - */ - void visit(String name, Object 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. - */ - void visitEnum(String name, String desc, String 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>. - */ - AnnotationVisitor visitAnnotation(String name, String desc); - - /** - * 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>. - */ - AnnotationVisitor visitArray(String name); - - /** - * Visits the end of the annotation. - */ - void visitEnd(); -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/AnnotationWriter.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/AnnotationWriter.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/AnnotationWriter.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/AnnotationWriter.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,322 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm; - -/** - * An {@link AnnotationVisitor} that generates annotations in bytecode form. - * - * @author Eric Bruneton - * @author Eugene Kuleshov - */ -final class AnnotationWriter implements 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) { - this.cw = cw; - this.named = named; - this.bv = bv; - this.parent = parent; - this.offset = offset; - } - - // ------------------------------------------------------------------------ - // Implementation of the AnnotationVisitor interface - // ------------------------------------------------------------------------ - - 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); - } - } - - 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)); - } - - 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); - } - - 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); - } - - 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 out where the annotations must be put. - */ - static void put(final AnnotationWriter[] panns, final ByteVector out) { - int size = 1 + 2 * panns.length; - for (int i = 0; i < panns.length; ++i) { - size += panns[i] == null ? 0 : panns[i].getSize(); - } - out.putInt(size).putByte(panns.length); - for (int i = 0; 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 -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/Attribute.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/Attribute.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/Attribute.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/Attribute.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,250 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.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 -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/ByteVector.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/ByteVector.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/ByteVector.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/ByteVector.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,297 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.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(); - if (length + 2 + charLength > data.length) { - enlarge(2 + charLength); - } - int len = length; - 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 -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/ClassAdapter.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/ClassAdapter.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/ClassAdapter.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/ClassAdapter.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,115 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm; - -/** - * An empty {@link ClassVisitor} that delegates to another {@link ClassVisitor}. - * This class can be used as a super class to quickly implement usefull class - * adapter classes, just by overriding the necessary methods. - * - * @author Eric Bruneton - */ -public class ClassAdapter implements ClassVisitor { - - /** - * The {@link ClassVisitor} to which this adapter delegates calls. - */ - protected ClassVisitor cv; - - /** - * Constructs a new {@link ClassAdapter} object. - * - * @param cv the class visitor to which this adapter must delegate calls. - */ - public ClassAdapter(final ClassVisitor cv) { - this.cv = cv; - } - - 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); - } - - public void visitSource(final String source, final String debug) { - cv.visitSource(source, debug); - } - - public void visitOuterClass( - final String owner, - final String name, - final String desc) { - cv.visitOuterClass(owner, name, desc); - } - - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) { - return cv.visitAnnotation(desc, visible); - } - - public void visitAttribute(final Attribute attr) { - cv.visitAttribute(attr); - } - - public void visitInnerClass( - final String name, - final String outerName, - final String innerName, - final int access) { - cv.visitInnerClass(name, outerName, innerName, access); - } - - public FieldVisitor visitField( - final int access, - final String name, - final String desc, - final String signature, - final Object value) { - return cv.visitField(access, name, desc, signature, value); - } - - public MethodVisitor visitMethod( - final int access, - final String name, - final String desc, - final String signature, - final String[] exceptions) { - return cv.visitMethod(access, name, desc, signature, exceptions); - } - - public void visitEnd() { - cv.visitEnd(); - } -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/ClassReader.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/ClassReader.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/ClassReader.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/ClassReader.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,2012 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.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 { - - /** - * 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 final static 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 final static 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 final static 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 final static 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; - // 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: - 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.CLASS: - // case ClassWriter.STR: - 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() { - int n = items[readUnsignedShort(header + 4)]; - return n == 0 ? null : readUTF8(n, 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.STR: - // case ClassWriter.CLASS: - 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; - } - - /** - * 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)); - } - - /** - * Constructs a new {@link ClassReader} object. - * - * @param name the fully qualified name of the class to be read. - * @throws IOException if an exception occurs during reading. - */ - public ClassReader(final String name) throws IOException { - this(ClassLoader.getSystemResourceAsStream(name.replace('.', '/') - + ".class")); - } - - /** - * Reads the bytecode of a class. - * - * @param is an input stream from which to read the class. - * @return the bytecode read from the given input stream. - * @throws IOException if a problem occurs during reading. - */ - private static byte[] readClass(final InputStream is) throws IOException { - if (is == null) { - throw new IOException("Class not found"); - } - 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) { - byte[] c = new byte[b.length + 1000]; - System.arraycopy(b, 0, c, 0, len); - b = c; - } - } - } - - // ------------------------------------------------------------------------ - // 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}. - */ - 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}. - */ - public void accept( - final ClassVisitor classVisitor, - final Attribute[] attrs, - final int flags) { - byte[] b = this.b; // the bytecode array - char[] c = new char[maxStringLength]; // buffer used to read strings - int i, j, k; // loop variables - int u, v, w; // indexes in b - Attribute attr; - - int access; - String name; - String desc; - String attrName; - String signature; - int anns = 0; - int ianns = 0; - Attribute cattrs = null; - - // visits the header - u = header; - access = readUnsignedShort(u); - name = readClass(u + 2, c); - v = items[readUnsignedShort(u + 4)]; - String superClassName = v == 0 ? null : readUTF8(v, c); - String[] implementedItfs = new String[readUnsignedShort(u + 6)]; - w = 0; - u += 8; - for (i = 0; i < implementedItfs.length; ++i) { - implementedItfs[i] = readClass(u, c); - u += 2; - } - - boolean skipCode = (flags & SKIP_CODE) != 0; - boolean skipDebug = (flags & SKIP_DEBUG) != 0; - boolean unzip = (flags & EXPAND_FRAMES) != 0; - - // skips fields and methods - v = u; - i = readUnsignedShort(v); - v += 2; - for (; i > 0; --i) { - j = readUnsignedShort(v + 6); - v += 8; - for (; j > 0; --j) { - v += 6 + readInt(v + 2); - } - } - i = readUnsignedShort(v); - v += 2; - for (; i > 0; --i) { - j = readUnsignedShort(v + 6); - v += 8; - for (; j > 0; --j) { - v += 6 + readInt(v + 2); - } - } - // reads the class's attributes - signature = null; - String sourceFile = null; - String sourceDebug = null; - String enclosingOwner = null; - String enclosingName = null; - String enclosingDesc = null; - - i = readUnsignedShort(v); - v += 2; - for (; i > 0; --i) { - attrName = readUTF8(v, c); - // tests are sorted in decreasing frequency order - // (based on frequencies observed on typical classes) - if (attrName.equals("SourceFile")) { - sourceFile = readUTF8(v + 6, c); - } - else if (attrName.equals("InnerClasses")) { - w = v + 6; - } - else if (attrName.equals("EnclosingMethod")) { - enclosingOwner = readClass(v + 6, c); - int item = readUnsignedShort(v + 8); - if (item != 0) { - enclosingName = readUTF8(items[item], c); - enclosingDesc = readUTF8(items[item] + 2, c); - } - } - else if (attrName.equals("Signature")) { - signature = readUTF8(v + 6, c); - } - else if (attrName.equals("RuntimeVisibleAnnotations")) { - anns = v + 6; - } - else if (attrName.equals("Deprecated")) { - access |= Opcodes.ACC_DEPRECATED; - } - else if (attrName.equals("Synthetic")) { - access |= Opcodes.ACC_SYNTHETIC; - } - else if (attrName.equals("SourceDebugExtension")) { - int len = readInt(v + 2); - sourceDebug = readUTF(v + 6, len, new char[len]); - } - else if (attrName.equals("RuntimeInvisibleAnnotations")) { - ianns = v + 6; - } - else { - attr = readAttribute(attrs, - attrName, - v + 6, - readInt(v + 2), - c, - -1, - null); - if (attr != null) { - attr.next = cattrs; - cattrs = attr; - } - } - v += 6 + readInt(v + 2); - } - // calls the visit method - classVisitor.visit(readInt(4), - access, - name, - signature, - superClassName, - implementedItfs); - - // calls the visitSource method - if (!skipDebug && (sourceFile != null || sourceDebug != null)) { - classVisitor.visitSource(sourceFile, sourceDebug); - } - - // calls the visitOuterClass method - if (enclosingOwner != null) { - classVisitor.visitOuterClass(enclosingOwner, - enclosingName, - enclosingDesc); - } - - // visits the class annotations - for (i = 1; i >= 0; --i) { - v = i == 0 ? ianns : anns; - if (v != 0) { - j = readUnsignedShort(v); - v += 2; - for (; j > 0; --j) { - v = readAnnotationValues(v + 2, - c, - true, - classVisitor.visitAnnotation(readUTF8(v, c), i != 0)); - } - } - } - - // visits the class attributes - while (cattrs != null) { - attr = cattrs.next; - cattrs.next = null; - classVisitor.visitAttribute(cattrs); - cattrs = attr; - } - - // calls the visitInnerClass method - if (w != 0) { - i = readUnsignedShort(w); - w += 2; - for (; i > 0; --i) { - classVisitor.visitInnerClass(readUnsignedShort(w) == 0 - ? null - : readClass(w, c), readUnsignedShort(w + 2) == 0 - ? null - : readClass(w + 2, c), readUnsignedShort(w + 4) == 0 - ? null - : readUTF8(w + 4, c), readUnsignedShort(w + 6)); - w += 8; - } - } - - // visits the fields - i = readUnsignedShort(u); - u += 2; - for (; i > 0; --i) { - access = readUnsignedShort(u); - name = readUTF8(u + 2, c); - desc = readUTF8(u + 4, c); - // visits the field's attributes and looks for a ConstantValue - // attribute - int fieldValueItem = 0; - signature = null; - anns = 0; - ianns = 0; - cattrs = null; - - j = readUnsignedShort(u + 6); - u += 8; - for (; j > 0; --j) { - attrName = readUTF8(u, c); - // tests are sorted in decreasing frequency order - // (based on frequencies observed on typical classes) - if (attrName.equals("ConstantValue")) { - fieldValueItem = readUnsignedShort(u + 6); - } - else if (attrName.equals("Signature")) { - signature = readUTF8(u + 6, c); - } - else if (attrName.equals("Deprecated")) { - access |= Opcodes.ACC_DEPRECATED; - } - else if (attrName.equals("Synthetic")) { - access |= Opcodes.ACC_SYNTHETIC; - } - else if (attrName.equals("RuntimeVisibleAnnotations")) { - anns = u + 6; - } - else if (attrName.equals("RuntimeInvisibleAnnotations")) { - ianns = u + 6; - } - else { - attr = readAttribute(attrs, - attrName, - u + 6, - readInt(u + 2), - c, - -1, - null); - if (attr != null) { - attr.next = cattrs; - cattrs = attr; - } - } - u += 6 + readInt(u + 2); - } - // visits the field - FieldVisitor fv = classVisitor.visitField(access, - name, - desc, - signature, - fieldValueItem == 0 ? null : readConst(fieldValueItem, c)); - // visits the field annotations and attributes - if (fv != null) { - for (j = 1; j >= 0; --j) { - v = j == 0 ? ianns : anns; - if (v != 0) { - k = readUnsignedShort(v); - v += 2; - for (; k > 0; --k) { - v = readAnnotationValues(v + 2, - c, - true, - fv.visitAnnotation(readUTF8(v, c), j != 0)); - } - } - } - while (cattrs != null) { - attr = cattrs.next; - cattrs.next = null; - fv.visitAttribute(cattrs); - cattrs = attr; - } - fv.visitEnd(); - } - } - - // visits the methods - i = readUnsignedShort(u); - u += 2; - for (; i > 0; --i) { - int u0 = u + 6; - access = readUnsignedShort(u); - name = readUTF8(u + 2, c); - desc = readUTF8(u + 4, c); - signature = null; - anns = 0; - ianns = 0; - int dann = 0; - int mpanns = 0; - int impanns = 0; - cattrs = null; - v = 0; - w = 0; - - // looks for Code and Exceptions attributes - j = readUnsignedShort(u + 6); - u += 8; - for (; j > 0; --j) { - attrName = readUTF8(u, c); - int attrSize = readInt(u + 2); - u += 6; - // tests are sorted in decreasing frequency order - // (based on frequencies observed on typical classes) - if (attrName.equals("Code")) { - if (!skipCode) { - v = u; - } - } - else if (attrName.equals("Exceptions")) { - w = u; - } - else if (attrName.equals("Signature")) { - signature = readUTF8(u, c); - } - else if (attrName.equals("Deprecated")) { - access |= Opcodes.ACC_DEPRECATED; - } - else if (attrName.equals("RuntimeVisibleAnnotations")) { - anns = u; - } - else if (attrName.equals("AnnotationDefault")) { - dann = u; - } - else if (attrName.equals("Synthetic")) { - access |= Opcodes.ACC_SYNTHETIC; - } - else if (attrName.equals("RuntimeInvisibleAnnotations")) { - ianns = u; - } - else if (attrName.equals("RuntimeVisibleParameterAnnotations")) { - mpanns = u; - } - else if (attrName.equals("RuntimeInvisibleParameterAnnotations")) { - impanns = u; - } - else { - attr = readAttribute(attrs, - attrName, - u, - attrSize, - c, - -1, - null); - if (attr != null) { - attr.next = cattrs; - cattrs = attr; - } - } - u += attrSize; - } - // reads declared exceptions - String[] exceptions; - if (w == 0) { - exceptions = null; - } - else { - exceptions = new String[readUnsignedShort(w)]; - w += 2; - for (j = 0; j < exceptions.length; ++j) { - exceptions[j] = readClass(w, c); - w += 2; - } - } - - // visits the method's code, if any - MethodVisitor mv = classVisitor.visitMethod(access, - name, - desc, - signature, - exceptions); - - if (mv != null) { - /* - * 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 (mv instanceof MethodWriter) { - MethodWriter mw = (MethodWriter) mv; - if (mw.cw.cr == this) { - if (signature == mw.signature) { - boolean sameExceptions = false; - if (exceptions == null) { - sameExceptions = mw.exceptionCount == 0; - } - else { - if (exceptions.length == mw.exceptionCount) { - sameExceptions = true; - for (j = exceptions.length - 1; j >= 0; --j) { - w -= 2; - if (mw.exceptions[j] != readUnsignedShort(w)) { - 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 = u0; - mw.classReaderLength = u - u0; - continue; - } - } - } - } - - if (dann != 0) { - AnnotationVisitor dv = mv.visitAnnotationDefault(); - readAnnotationValue(dann, c, null, dv); - if (dv != null) { - dv.visitEnd(); - } - } - for (j = 1; j >= 0; --j) { - w = j == 0 ? ianns : anns; - if (w != 0) { - k = readUnsignedShort(w); - w += 2; - for (; k > 0; --k) { - w = readAnnotationValues(w + 2, - c, - true, - mv.visitAnnotation(readUTF8(w, c), j != 0)); - } - } - } - if (mpanns != 0) { - readParameterAnnotations(mpanns, c, true, mv); - } - if (impanns != 0) { - readParameterAnnotations(impanns, c, false, mv); - } - while (cattrs != null) { - attr = cattrs.next; - cattrs.next = null; - mv.visitAttribute(cattrs); - cattrs = attr; - } - } - - if (mv != null && v != 0) { - int maxStack = readUnsignedShort(v); - int maxLocals = readUnsignedShort(v + 2); - int codeLength = readInt(v + 4); - v += 8; - - int codeStart = v; - int codeEnd = v + codeLength; - - mv.visitCode(); - - // 1st phase: finds the labels - int label; - Label[] labels = new Label[codeLength + 1]; - while (v < codeEnd) { - int opcode = b[v] & 0xFF; - switch (ClassWriter.TYPE[opcode]) { - case ClassWriter.NOARG_INSN: - case ClassWriter.IMPLVAR_INSN: - v += 1; - break; - case ClassWriter.LABEL_INSN: - label = v - codeStart + readShort(v + 1); - if (labels[label] == null) { - labels[label] = new Label(); - } - v += 3; - break; - case ClassWriter.LABELW_INSN: - label = v - codeStart + readInt(v + 1); - if (labels[label] == null) { - labels[label] = new Label(); - } - v += 5; - break; - case ClassWriter.WIDE_INSN: - opcode = b[v + 1] & 0xFF; - if (opcode == Opcodes.IINC) { - v += 6; - } - else { - v += 4; - } - break; - case ClassWriter.TABL_INSN: - // skips 0 to 3 padding bytes - w = v - codeStart; - v = v + 4 - (w & 3); - // reads instruction - label = w + readInt(v); - if (labels[label] == null) { - labels[label] = new Label(); - } - j = readInt(v + 8) - readInt(v + 4) + 1; - v += 12; - for (; j > 0; --j) { - label = w + readInt(v); - v += 4; - if (labels[label] == null) { - labels[label] = new Label(); - } - } - break; - case ClassWriter.LOOK_INSN: - // skips 0 to 3 padding bytes - w = v - codeStart; - v = v + 4 - (w & 3); - // reads instruction - label = w + readInt(v); - if (labels[label] == null) { - labels[label] = new Label(); - } - j = readInt(v + 4); - v += 8; - for (; j > 0; --j) { - label = w + readInt(v + 4); - v += 8; - if (labels[label] == null) { - labels[label] = new Label(); - } - } - break; - case ClassWriter.VAR_INSN: - case ClassWriter.SBYTE_INSN: - case ClassWriter.LDC_INSN: - v += 2; - break; - case ClassWriter.SHORT_INSN: - case ClassWriter.LDCW_INSN: - case ClassWriter.FIELDORMETH_INSN: - case ClassWriter.TYPE_INSN: - case ClassWriter.IINC_INSN: - v += 3; - break; - case ClassWriter.ITFMETH_INSN: - v += 5; - break; - // case MANA_INSN: - default: - v += 4; - break; - } - } - // parses the try catch entries - j = readUnsignedShort(v); - v += 2; - for (; j > 0; --j) { - label = readUnsignedShort(v); - Label start = labels[label]; - if (start == null) { - labels[label] = start = new Label(); - } - label = readUnsignedShort(v + 2); - Label end = labels[label]; - if (end == null) { - labels[label] = end = new Label(); - } - label = readUnsignedShort(v + 4); - Label handler = labels[label]; - if (handler == null) { - labels[label] = handler = new Label(); - } - int type = readUnsignedShort(v + 6); - if (type == 0) { - mv.visitTryCatchBlock(start, end, handler, null); - } - else { - mv.visitTryCatchBlock(start, - end, - handler, - readUTF8(items[type], c)); - } - v += 8; - } - // parses the local variable, line number tables, and code - // attributes - int varTable = 0; - int varTypeTable = 0; - int stackMap = 0; - int frameCount = 0; - int frameMode = 0; - int frameOffset = 0; - int frameLocalCount = 0; - int frameLocalDiff = 0; - int frameStackCount = 0; - Object[] frameLocal = null; - Object[] frameStack = null; - boolean zip = true; - cattrs = null; - j = readUnsignedShort(v); - v += 2; - for (; j > 0; --j) { - attrName = readUTF8(v, c); - if (attrName.equals("LocalVariableTable")) { - if (!skipDebug) { - varTable = v + 6; - k = readUnsignedShort(v + 6); - w = v + 8; - for (; k > 0; --k) { - label = readUnsignedShort(w); - if (labels[label] == null) { - labels[label] = new Label(true); - } - label += readUnsignedShort(w + 2); - if (labels[label] == null) { - labels[label] = new Label(true); - } - w += 10; - } - } - } - else if (attrName.equals("LocalVariableTypeTable")) { - varTypeTable = v + 6; - } - else if (attrName.equals("LineNumberTable")) { - if (!skipDebug) { - k = readUnsignedShort(v + 6); - w = v + 8; - for (; k > 0; --k) { - label = readUnsignedShort(w); - if (labels[label] == null) { - labels[label] = new Label(true); - } - labels[label].line = readUnsignedShort(w + 2); - w += 4; - } - } - } - else if (attrName.equals("StackMapTable")) { - if ((flags & SKIP_FRAMES) == 0) { - stackMap = v + 8; - frameCount = readUnsignedShort(v + 6); - } - /* - * 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. - */ - // - // but for UNINITIALIZED type offsets? - } - else if (attrName.equals("StackMap")) { - if ((flags & SKIP_FRAMES) == 0) { - stackMap = v + 8; - frameCount = readUnsignedShort(v + 6); - zip = false; - } - /* - * 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 (k = 0; k < attrs.length; ++k) { - if (attrs[k].type.equals(attrName)) { - attr = attrs[k].read(this, - v + 6, - readInt(v + 2), - c, - codeStart - 8, - labels); - if (attr != null) { - attr.next = cattrs; - cattrs = attr; - } - } - } - } - v += 6 + readInt(v + 2); - } - - // 2nd phase: visits each instruction - if (stackMap != 0) { - // creates the very first (implicit) frame from the method - // descriptor - frameLocal = new Object[maxLocals]; - frameStack = new Object[maxStack]; - if (unzip) { - int local = 0; - if ((access & Opcodes.ACC_STATIC) == 0) { - if (name.equals("<init>")) { - frameLocal[local++] = Opcodes.UNINITIALIZED_THIS; - } - else { - frameLocal[local++] = readClass(header + 2, c); - } - } - j = 1; - loop: - while (true) { - k = j; - switch (desc.charAt(j++)) { - case 'Z': - case 'C': - case 'B': - case 'S': - case 'I': - frameLocal[local++] = Opcodes.INTEGER; - break; - case 'F': - frameLocal[local++] = Opcodes.FLOAT; - break; - case 'J': - frameLocal[local++] = Opcodes.LONG; - break; - case 'D': - frameLocal[local++] = Opcodes.DOUBLE; - break; - case '[': - while (desc.charAt(j) == '[') { - ++j; - } - if (desc.charAt(j) == 'L') { - ++j; - while (desc.charAt(j) != ';') { - ++j; - } - } - frameLocal[local++] = desc.substring(k, ++j); - break; - case 'L': - while (desc.charAt(j) != ';') { - ++j; - } - frameLocal[local++] = desc.substring(k + 1, - j++); - break; - default: - break loop; - } - } - frameLocalCount = local; - } - /* - * 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 - */ - frameOffset = -1; - } - v = codeStart; - Label l; - while (v < codeEnd) { - w = v - codeStart; - - l = labels[w]; - if (l != null) { - mv.visitLabel(l); - if (!skipDebug && l.line > 0) { - mv.visitLineNumber(l.line, l); - } - } - - while (frameLocal != null - && (frameOffset == w || frameOffset == -1)) { - // if there is a frame for this offset, - // makes the visitor visit it, - // and reads the next frame if there is one. - if (!zip || unzip) { - mv.visitFrame(Opcodes.F_NEW, - frameLocalCount, - frameLocal, - frameStackCount, - frameStack); - } - else if (frameOffset != -1) { - mv.visitFrame(frameMode, - frameLocalDiff, - frameLocal, - frameStackCount, - frameStack); - } - - if (frameCount > 0) { - int tag, delta, n; - if (zip) { - tag = b[stackMap++] & 0xFF; - } - else { - tag = MethodWriter.FULL_FRAME; - frameOffset = -1; - } - frameLocalDiff = 0; - if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME) { - delta = tag; - frameMode = Opcodes.F_SAME; - frameStackCount = 0; - } - else if (tag < MethodWriter.RESERVED) { - delta = tag - - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME; - stackMap = readFrameType(frameStack, - 0, - stackMap, - c, - labels); - frameMode = Opcodes.F_SAME1; - frameStackCount = 1; - } - else { - delta = readUnsignedShort(stackMap); - stackMap += 2; - if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { - stackMap = readFrameType(frameStack, - 0, - stackMap, - c, - labels); - frameMode = Opcodes.F_SAME1; - frameStackCount = 1; - } - else if (tag >= MethodWriter.CHOP_FRAME - && tag < MethodWriter.SAME_FRAME_EXTENDED) { - frameMode = Opcodes.F_CHOP; - frameLocalDiff = MethodWriter.SAME_FRAME_EXTENDED - - tag; - frameLocalCount -= frameLocalDiff; - frameStackCount = 0; - } - else if (tag == MethodWriter.SAME_FRAME_EXTENDED) { - frameMode = Opcodes.F_SAME; - frameStackCount = 0; - } - else if (tag < MethodWriter.FULL_FRAME) { - j = unzip ? frameLocalCount : 0; - for (k = tag - - MethodWriter.SAME_FRAME_EXTENDED; k > 0; k--) { - stackMap = readFrameType(frameLocal, - j++, - stackMap, - c, - labels); - } - frameMode = Opcodes.F_APPEND; - frameLocalDiff = tag - - MethodWriter.SAME_FRAME_EXTENDED; - frameLocalCount += frameLocalDiff; - frameStackCount = 0; - } - else { // if (tag == FULL_FRAME) { - frameMode = Opcodes.F_FULL; - n = frameLocalDiff = frameLocalCount = readUnsignedShort(stackMap); - stackMap += 2; - for (j = 0; n > 0; n--) { - stackMap = readFrameType(frameLocal, - j++, - stackMap, - c, - labels); - } - n = frameStackCount = readUnsignedShort(stackMap); - stackMap += 2; - for (j = 0; n > 0; n--) { - stackMap = readFrameType(frameStack, - j++, - stackMap, - c, - labels); - } - } - } - frameOffset += delta + 1; - if (labels[frameOffset] == null) { - labels[frameOffset] = new Label(); - } - - --frameCount; - } - else { - frameLocal = null; - } - } - - int opcode = b[v] & 0xFF; - switch (ClassWriter.TYPE[opcode]) { - case ClassWriter.NOARG_INSN: - mv.visitInsn(opcode); - v += 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); - } - v += 1; - break; - case ClassWriter.LABEL_INSN: - mv.visitJumpInsn(opcode, labels[w - + readShort(v + 1)]); - v += 3; - break; - case ClassWriter.LABELW_INSN: - mv.visitJumpInsn(opcode - 33, labels[w - + readInt(v + 1)]); - v += 5; - break; - case ClassWriter.WIDE_INSN: - opcode = b[v + 1] & 0xFF; - if (opcode == Opcodes.IINC) { - mv.visitIincInsn(readUnsignedShort(v + 2), - readShort(v + 4)); - v += 6; - } - else { - mv.visitVarInsn(opcode, - readUnsignedShort(v + 2)); - v += 4; - } - break; - case ClassWriter.TABL_INSN: - // skips 0 to 3 padding bytes - v = v + 4 - (w & 3); - // reads instruction - label = w + readInt(v); - int min = readInt(v + 4); - int max = readInt(v + 8); - v += 12; - Label[] table = new Label[max - min + 1]; - for (j = 0; j < table.length; ++j) { - table[j] = labels[w + readInt(v)]; - v += 4; - } - mv.visitTableSwitchInsn(min, - max, - labels[label], - table); - break; - case ClassWriter.LOOK_INSN: - // skips 0 to 3 padding bytes - v = v + 4 - (w & 3); - // reads instruction - label = w + readInt(v); - j = readInt(v + 4); - v += 8; - int[] keys = new int[j]; - Label[] values = new Label[j]; - for (j = 0; j < keys.length; ++j) { - keys[j] = readInt(v); - values[j] = labels[w + readInt(v + 4)]; - v += 8; - } - mv.visitLookupSwitchInsn(labels[label], - keys, - values); - break; - case ClassWriter.VAR_INSN: - mv.visitVarInsn(opcode, b[v + 1] & 0xFF); - v += 2; - break; - case ClassWriter.SBYTE_INSN: - mv.visitIntInsn(opcode, b[v + 1]); - v += 2; - break; - case ClassWriter.SHORT_INSN: - mv.visitIntInsn(opcode, readShort(v + 1)); - v += 3; - break; - case ClassWriter.LDC_INSN: - mv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c)); - v += 2; - break; - case ClassWriter.LDCW_INSN: - mv.visitLdcInsn(readConst(readUnsignedShort(v + 1), - c)); - v += 3; - break; - case ClassWriter.FIELDORMETH_INSN: - case ClassWriter.ITFMETH_INSN: - int cpIndex = items[readUnsignedShort(v + 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) { - v += 5; - } - else { - v += 3; - } - break; - case ClassWriter.TYPE_INSN: - mv.visitTypeInsn(opcode, readClass(v + 1, c)); - v += 3; - break; - case ClassWriter.IINC_INSN: - mv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]); - v += 3; - break; - // case MANA_INSN: - default: - mv.visitMultiANewArrayInsn(readClass(v + 1, c), - b[v + 3] & 0xFF); - v += 4; - break; - } - } - l = labels[codeEnd - codeStart]; - if (l != null) { - mv.visitLabel(l); - } - // visits the local variable tables - if (!skipDebug && varTable != 0) { - int[] typeTable = null; - if (varTypeTable != 0) { - k = readUnsignedShort(varTypeTable) * 3; - w = varTypeTable + 2; - typeTable = new int[k]; - while (k > 0) { - typeTable[--k] = w + 6; // signature - typeTable[--k] = readUnsignedShort(w + 8); // index - typeTable[--k] = readUnsignedShort(w); // start - w += 10; - } - } - k = readUnsignedShort(varTable); - w = varTable + 2; - for (; k > 0; --k) { - int start = readUnsignedShort(w); - int length = readUnsignedShort(w + 2); - int index = readUnsignedShort(w + 8); - String vsignature = null; - if (typeTable != null) { - for (int a = 0; a < typeTable.length; a += 3) { - if (typeTable[a] == start - && typeTable[a + 1] == index) { - vsignature = readUTF8(typeTable[a + 2], c); - break; - } - } - } - mv.visitLocalVariable(readUTF8(w + 4, c), - readUTF8(w + 6, c), - vsignature, - labels[start], - labels[start + length], - index); - w += 10; - } - } - // visits the other attributes - while (cattrs != null) { - attr = cattrs.next; - cattrs.next = null; - mv.visitAttribute(cattrs); - cattrs = attr; - } - // visits the max stack and max locals values - mv.visitMaxs(maxStack, maxLocals); - } - - if (mv != null) { - mv.visitEnd(); - } - } - - // visits the end of the class - classVisitor.visitEnd(); - } - - /** - * 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 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 char[] buf, - final boolean visible, - final MethodVisitor mv) { - int n = b[v++] & 0xFF; - for (int i = 0; i < n; ++i) { - int j = readUnsignedShort(v); - v += 2; - for (; j > 0; --j) { - v = readAnnotationValues(v + 2, - buf, - true, - mv.visitParameterAnnotation(i, - readUTF8(v, buf), - visible)); - } - } - } - - /** - * 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; - } - - 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 - int offset = readUnsignedShort(v); - if (labels[offset] == null) { - labels[offset] = new Label(); - } - frame[index] = labels[offset]; - v += 2; - } - return v; - } - - /** - * 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 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]; - } - - /** - * 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); - 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, d, e; - while (index < endIndex) { - c = b[index++] & 0xFF; - switch (c >> 4) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - // 0xxxxxxx - buf[strLen++] = (char) c; - break; - case 12: - case 13: - // 110x xxxx 10xx xxxx - d = b[index++]; - buf[strLen++] = (char) (((c & 0x1F) << 6) | (d & 0x3F)); - break; - default: - // 1110 xxxx 10xx xxxx 10xx xxxx - d = b[index++]; - e = b[index++]; - buf[strLen++] = (char) (((c & 0x0F) << 12) - | ((d & 0x3F) << 6) | (e & 0x3F)); - 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} or {@link Type} 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: - String s = readUTF8(index, buf); - return s.charAt(0) == '[' - ? Type.getType(s) - : Type.getObjectType(s); - // case ClassWriter.STR: - default: - return readUTF8(index, buf); - } - } -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/ClassVisitor.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/ClassVisitor.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/ClassVisitor.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/ClassVisitor.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,196 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm; - -/** - * A visitor to visit a Java class. The methods of this interface 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 interface ClassVisitor { - - /** - * 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>. - */ - void visit( - int version, - int access, - String name, - String signature, - String superName, - String[] 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>. - */ - void visitSource(String source, String 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. - */ - void visitOuterClass(String owner, String name, String 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. - */ - AnnotationVisitor visitAnnotation(String desc, boolean visible); - - /** - * Visits a non standard attribute of the class. - * - * @param attr an attribute. - */ - void visitAttribute(Attribute 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. - */ - void visitInnerClass( - String name, - String outerName, - String innerName, - int 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. - */ - FieldVisitor visitField( - int access, - String name, - String desc, - String signature, - Object value); - - /** - * 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. - */ - MethodVisitor visitMethod( - int access, - String name, - String desc, - String signature, - String[] exceptions); - - /** - * 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. - */ - void visitEnd(); -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/ClassWriter.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/ClassWriter.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/ClassWriter.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/ClassWriter.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,1342 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.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 implements 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 final static 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 final static int COMPUTE_FRAMES = 2; - - /** - * The type of instructions without any argument. - */ - final static int NOARG_INSN = 0; - - /** - * The type of instructions with an signed byte argument. - */ - final static int SBYTE_INSN = 1; - - /** - * The type of instructions with an signed short argument. - */ - final static int SHORT_INSN = 2; - - /** - * The type of instructions with a local variable index argument. - */ - final static int VAR_INSN = 3; - - /** - * The type of instructions with an implicit local variable index argument. - */ - final static int IMPLVAR_INSN = 4; - - /** - * The type of instructions with a type descriptor argument. - */ - final static int TYPE_INSN = 5; - - /** - * The type of field and method invocations instructions. - */ - final static int FIELDORMETH_INSN = 6; - - /** - * The type of the INVOKEINTERFACE instruction. - */ - final static int ITFMETH_INSN = 7; - - /** - * The type of instructions with a 2 bytes bytecode offset label. - */ - final static int LABEL_INSN = 8; - - /** - * The type of instructions with a 4 bytes bytecode offset label. - */ - final static int LABELW_INSN = 9; - - /** - * The type of the LDC instruction. - */ - final static int LDC_INSN = 10; - - /** - * The type of the LDC_W and LDC2_W instructions. - */ - final static int LDCW_INSN = 11; - - /** - * The type of the IINC instruction. - */ - final static int IINC_INSN = 12; - - /** - * The type of the TABLESWITCH instruction. - */ - final static int TABL_INSN = 13; - - /** - * The type of the LOOKUPSWITCH instruction. - */ - final static int LOOK_INSN = 14; - - /** - * The type of the MULTIANEWARRAY instruction. - */ - final static int MANA_INSN = 15; - - /** - * The type of the WIDE instruction. - */ - final static int WIDE_INSN = 16; - - /** - * The instruction types of all JVM opcodes. - */ - static byte[] TYPE; - - /** - * The type of CONSTANT_Class constant pool items. - */ - final static int CLASS = 7; - - /** - * The type of CONSTANT_Fieldref constant pool items. - */ - final static int FIELD = 9; - - /** - * The type of CONSTANT_Methodref constant pool items. - */ - final static int METH = 10; - - /** - * The type of CONSTANT_InterfaceMethodref constant pool items. - */ - final static int IMETH = 11; - - /** - * The type of CONSTANT_String constant pool items. - */ - final static int STR = 8; - - /** - * The type of CONSTANT_Integer constant pool items. - */ - final static int INT = 3; - - /** - * The type of CONSTANT_Float constant pool items. - */ - final static int FLOAT = 4; - - /** - * The type of CONSTANT_Long constant pool items. - */ - final static int LONG = 5; - - /** - * The type of CONSTANT_Double constant pool items. - */ - final static int DOUBLE = 6; - - /** - * The type of CONSTANT_NameAndType constant pool items. - */ - final static int NAME_TYPE = 12; - - /** - * The type of CONSTANT_Utf8 constant pool items. - */ - final static int UTF8 = 1; - - /** - * 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. - */ - final static int TYPE_NORMAL = 13; - - /** - * 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. - */ - final static int TYPE_UNINIT = 14; - - /** - * 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. - */ - final static int TYPE_MERGED = 15; - - /** - * 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. - */ - 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. - */ - Item key; - - /** - * A reusable key used to look for items in the {@link #items} hash table. - */ - Item key2; - - /** - * A reusable key used to look for items in the {@link #items} hash table. - */ - Item key3; - - /** - * 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, conversly, 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 fields of this class. These fields are stored in a linked list of - * {@link FieldWriter} objects, linked to each other by their - * {@link FieldWriter#next} 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#next} 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#next} 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#next} 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 boolean computeMaxs; - - /** - * <tt>true</tt> if the stack map frames must be recomputed from scratch. - */ - private 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 = "AAAAAAAAAAAAAAAABCKLLDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD" - + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - + "AAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIDNOAA" - + "AAAAGGGGGGGHAFBFAAFFAAQPIIJJIIIIIIIIIIIIIIIIII"; - 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; - // - // // 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) { - index = 1; - pool = new ByteVector(); - items = new Item[256]; - threshold = (int) (0.75d * items.length); - key = new Item(); - key2 = new Item(); - key3 = 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: - * <p/> - * <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 a custom - * {@link ClassAdapter} or 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. 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 interface - // ------------------------------------------------------------------------ - - public 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 (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]); - } - } - } - - public void visitSource(final String file, final String debug) { - if (file != null) { - sourceFile = newUTF8(file); - } - if (debug != null) { - sourceDebug = new ByteVector().putUTF8(debug); - } - } - - public void visitOuterClass( - final String owner, - final String name, - final String desc) { - enclosingMethodOwner = newClass(owner); - if (name != null && desc != null) { - enclosingMethod = newNameType(name, desc); - } - } - - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) { - 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; - } - - public void visitAttribute(final Attribute attr) { - attr.next = attrs; - attrs = attr; - } - - public 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); - } - - public 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); - } - - public 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); - } - - public 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() { - // 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 = fb.next; - } - int nbMethods = 0; - MethodWriter mb = firstMethod; - while (mb != null) { - ++nbMethods; - size += mb.getSize(); - mb = mb.next; - } - int attributeCount = 0; - if (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 - && (version & 0xffff) < Opcodes.V1_5) { - ++attributeCount; - size += 6; - newUTF8("Synthetic"); - } - if (innerClasses != null) { - ++attributeCount; - size += 8 + innerClasses.length; - newUTF8("InnerClasses"); - } - if (anns != null) { - ++attributeCount; - size += 8 + anns.getSize(); - newUTF8("RuntimeVisibleAnnotations"); - } - if (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); - out.putShort(access).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 = fb.next; - } - out.putShort(nbMethods); - mb = firstMethod; - while (mb != null) { - mb.put(out); - mb = mb.next; - } - out.putShort(attributeCount); - if (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 - && (version & 0xffff) < Opcodes.V1_5) { - 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 (anns != null) { - out.putShort(newUTF8("RuntimeVisibleAnnotations")); - anns.put(out); - } - if (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; - return newClassItem(t.getSort() == Type.OBJECT - ? t.getInternalName() - : t.getDescriptor()); - } - 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 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); - put(result); - index += 2; - } - 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); - put(result); - index += 2; - } - 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) { - 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.index; - } - - /** - * 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 - * overriden 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; - try { - c = Thread.currentThread().getContextClassLoader().loadClass(type1.replace('/', '.')); - d = Thread.currentThread().getContextClassLoader().loadClass(type2.replace('/', '.')); - } - catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - 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 && !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 > 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); - } -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/Edge.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/Edge.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/Edge.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/Edge.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,75 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.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. - */ - final static 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. - */ - final static 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 ast 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 ast. 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 ast of the basic ast from which this edge originates. - */ - Label successor; - - /** - * The next edge in the list of successors of the originating basic ast. - * See {@link Label#successors successors}. - */ - Edge next; -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/FieldVisitor.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/FieldVisitor.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/FieldVisitor.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/FieldVisitor.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,64 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm; - -/** - * A visitor to visit a Java field. The methods of this interface must be called - * in the following order: ( <tt>visitAnnotation</tt> | - * <tt>visitAttribute</tt> )* <tt>visitEnd</tt>. - * - * @author Eric Bruneton - */ -public interface FieldVisitor { - - /** - * 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. - */ - AnnotationVisitor visitAnnotation(String desc, boolean visible); - - /** - * Visits a non standard attribute of the field. - * - * @param attr an attribute. - */ - void visitAttribute(Attribute 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. - */ - void visitEnd(); -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/FieldWriter.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/FieldWriter.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/FieldWriter.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/FieldWriter.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,263 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm; - -/** - * An {@link FieldVisitor} that generates Java fields in bytecode form. - * - * @author Eric Bruneton - */ -final class FieldWriter implements FieldVisitor { - - /** - * Next field writer (see {@link ClassWriter#firstField firstField}). - */ - FieldWriter next; - - /** - * The class writer to which this field must be added. - */ - private ClassWriter cw; - - /** - * Access flags of this field. - */ - private int access; - - /** - * The index of the constant pool item that contains the name of this - * method. - */ - private int name; - - /** - * The index of the constant pool item that contains the descriptor of this - * field. - */ - private 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>. - */ - protected FieldWriter( - final ClassWriter cw, - final int access, - final String name, - final String desc, - final String signature, - final Object value) { - if (cw.firstField == null) { - cw.firstField = this; - } - else { - cw.lastField.next = this; - } - cw.lastField = this; - this.cw = cw; - this.access = access; - this.name = cw.newUTF8(name); - this.desc = cw.newUTF8(desc); - if (signature != null) { - this.signature = cw.newUTF8(signature); - } - if (value != null) { - this.value = cw.newConstItem(value).index; - } - } - - // ------------------------------------------------------------------------ - // Implementation of the FieldVisitor interface - // ------------------------------------------------------------------------ - - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) { - 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; - } - - public void visitAttribute(final Attribute attr) { - attr.next = attrs; - attrs = attr; - } - - 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 - && (cw.version & 0xffff) < Opcodes.V1_5) { - cw.newUTF8("Synthetic"); - size += 6; - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - cw.newUTF8("Deprecated"); - size += 6; - } - if (signature != 0) { - cw.newUTF8("Signature"); - size += 8; - } - if (anns != null) { - cw.newUTF8("RuntimeVisibleAnnotations"); - size += 8 + anns.getSize(); - } - if (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) { - out.putShort(access).putShort(name).putShort(desc); - int attributeCount = 0; - if (value != 0) { - ++attributeCount; - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0 - && (cw.version & 0xffff) < Opcodes.V1_5) { - ++attributeCount; - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - ++attributeCount; - } - if (signature != 0) { - ++attributeCount; - } - if (anns != null) { - ++attributeCount; - } - if (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 - && (cw.version & 0xffff) < Opcodes.V1_5) { - out.putShort(cw.newUTF8("Synthetic")).putInt(0); - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - out.putShort(cw.newUTF8("Deprecated")).putInt(0); - } - if (signature != 0) { - out.putShort(cw.newUTF8("Signature")); - out.putInt(2).putShort(signature); - } - if (anns != null) { - out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); - anns.put(out); - } - if (ianns != null) { - out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); - ianns.put(out); - } - if (attrs != null) { - attrs.put(cw, null, 0, -1, -1, out); - } - } -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/Frame.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/Frame.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/Frame.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/Frame.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,1421 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm; - -/** - * Information about the input and output stack map frames of a basic ast. - * - * @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 ast 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 ast, i.e. the stack map - * frame at the begining of the basic ast, starting from the input frame - * of the first basic ast (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. - * - * OutputAppender stack map frames are computed relatively to the input frame of the - * basic ast, 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. - * - * OutputAppender 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. - */ - final static int DIM = 0xF0000000; - - /** - * Constant to be added to a type to get a type with one more dimension. - */ - final static int ARRAY_OF = 0x10000000; - - /** - * Constant to be added to a type to get a type with one less dimension. - */ - final static int ELEMENT_OF = 0xF0000000; - - /** - * Mask to get the kind of a frame type. - * - * @see #BASE - * @see #LOCAL - * @see #STACK - */ - final static int KIND = 0xF000000; - - /** - * Mask to get the value of a frame type. - */ - final static int VALUE = 0xFFFFFF; - - /** - * Mask to get the kind of base types. - */ - final static int BASE_KIND = 0xFF00000; - - /** - * Mask to get the value of base types. - */ - final static int BASE_VALUE = 0xFFFFF; - - /** - * Kind of the types that are not relative to an input stack map frame. - */ - final static int BASE = 0x1000000; - - /** - * Base kind of the base reference types. The BASE_VALUE of such types is an - * index into the type table. - */ - final static 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). - */ - final static 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 final static 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 final static int STACK = 0x3000000; - - /** - * The TOP type. This is a BASE type. - */ - final static int TOP = BASE | 0; - - /** - * The BOOLEAN type. This is a BASE type mainly used for array types. - */ - final static int BOOLEAN = BASE | 9; - - /** - * The BYTE type. This is a BASE type mainly used for array types. - */ - final static int BYTE = BASE | 10; - - /** - * The CHAR type. This is a BASE type mainly used for array types. - */ - final static int CHAR = BASE | 11; - - /** - * The SHORT type. This is a BASE type mainly used for array types. - */ - final static int SHORT = BASE | 12; - - /** - * The INTEGER type. This is a BASE type. - */ - final static int INTEGER = BASE | 1; - - /** - * The FLOAT type. This is a BASE type. - */ - final static int FLOAT = BASE | 2; - - /** - * The DOUBLE type. This is a BASE type. - */ - final static int DOUBLE = BASE | 3; - - /** - * The LONG type. This is a BASE type. - */ - final static int LONG = BASE | 4; - - /** - * The NULL type. This is a BASE type. - */ - final static int NULL = BASE | 5; - - /** - * The UNINITIALIZED_THIS type. This is a BASE type. - */ - final static 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. - */ - final static 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, //UNUSED, // NOT VISITED - // 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 ast) 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. - * <p/> - * 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. - * <p/> - * 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 ast. - * - * @see #initializations - */ - private int initializationCount; - - /** - * The types that are initialized in the basic ast. 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 ast, 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 ast, - // 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 ast, - // 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 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((MethodWriter.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 ast. - * - * @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 ast. - * - * @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 ast, 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 ast 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: - default: - push(OBJECT | cw.addType("java/lang/String")); - } - 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); - } - } - 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); - } - } - 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.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 ast with the input and output - * frames of this basic ast. 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 ast 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 == LOCAL) { - t = dim + inputLocals[s & VALUE]; - } - else if (kind == STACK) { - t = dim + inputStack[nStack - (s & VALUE)]; - } - else { - t = s; - } - } - } - 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 == LOCAL) { - t = dim + inputLocals[s & VALUE]; - } - else if (kind == STACK) { - t = dim + inputStack[nStack - (s & VALUE)]; - } - else { - t = s; - } - 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 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 -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/Handler.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/Handler.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/Handler.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/Handler.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,70 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm; - -/** - * Information about an exception handler ast. - * - * @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 ast info. - */ - Handler next; -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/Item.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/Item.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/Item.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/Item.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,255 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.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}. - * <p/> - * 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.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: - default: - hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() - * strVal2.hashCode() * strVal3.hashCode()); - } - } - - /** - * Indicates if the given item is equal to this one. - * - * @param i the item to be compared to this one. - * @return <tt>true</tt> if the given item if equal to this one, - * <tt>false</tt> otherwise. - */ - boolean isEqualTo(final Item i) { - if (i.type == type) { - switch (type) { - case ClassWriter.INT: - case ClassWriter.FLOAT: - return i.intVal == intVal; - case ClassWriter.TYPE_MERGED: - case ClassWriter.LONG: - case ClassWriter.DOUBLE: - return i.longVal == longVal; - case ClassWriter.UTF8: - case ClassWriter.STR: - case ClassWriter.CLASS: - case ClassWriter.TYPE_NORMAL: - return i.strVal1.equals(strVal1); - 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); - // ClassWriter.FIELD: - // ClassWriter.METH: - // ClassWriter.IMETH: - default: - return i.strVal1.equals(strVal1) - && i.strVal2.equals(strVal2) - && i.strVal3.equals(strVal3); - } - } - return false; - } -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/Label.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/Label.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/Label.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/Label.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,422 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.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. - * - * @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 ast, the target of a jump instruction, or - * an exception handler. It can be safely ignored in control flow graph - * analysis algorithms (for optimization purposes). - */ - final static int DEBUG = 1; - - /** - * Indicates if the position of this label is known. - */ - final static int RESOLVED = 2; - - /** - * Indicates if this label has been updated, after instruction resizing. - */ - final static int RESIZED = 4; - - /** - * Indicates if this basic ast has been pushed in the basic ast stack. - * See {@link MethodWriter#visitMaxs visitMaxs}. - */ - final static int PUSHED = 8; - - /** - * Indicates if this label is the target of a jump instruction, or the start - * of an exception handler. - */ - final static int TARGET = 16; - - /** - * Indicates if a stack map frame must be stored for this label. - */ - final static int STORE = 32; - - /** - * Indicates if this label corresponds to a reachable basic ast. - */ - final static int REACHABLE = 64; - - /** - * Indicates if this basic ast ends with a JSR instruction. - */ - final static int JSR = 128; - - /** - * Indicates if this basic ast ends with a RET instruction. - */ - final static int RET = 256; - - /** - * Field used to associate user information to a label. - */ - 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. - */ - 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 ast", and one edge per "jump" - * from one basic ast to another. Each node (i.e., each basic ast) is - * represented by the Label object that corresponds to the first instruction - * of this basic ast. 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 ast, called the "output frame", <i>relatively</i> to the frame - * state at the beginning of the basic ast, 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 ast, from the - * input state of the first basic ast (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. - * <p/> - * When only the maximum stack size is computed, this field is the number of - * elements in the input stack. - * <p/> - * 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 - * ast. 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 ast in the basic ast 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. - * - * @see MethodWriter#visitMaxs - */ - Label next; - - // ------------------------------------------------------------------------ - // Constructor - // ------------------------------------------------------------------------ - - /** - * Constructs a new label. - */ - public Label() { - } - - /** - * Constructs a new label. - * - * @param debug if this label is only used for debug attributes. - */ - Label(final boolean debug) { - this.status = debug ? DEBUG : 0; - } - - // ------------------------------------------------------------------------ - // 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) { - out.putInt(position - source); - } - else { - out.putShort(position - source); - } - } - else { - if (wideOffset) { - addReference(-1 - source, out.length); - out.putInt(-1); - } - else { - addReference(source, out.length); - out.putShort(-1); - } - } - } - - /** - * 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 frame == null ? this : frame.owner; - } - - // ------------------------------------------------------------------------ - // Overriden Object methods - // ------------------------------------------------------------------------ - - /** - * Returns a string representation of this label. - * - * @return a string representation of this label. - */ - public String toString() { - return "L" + System.identityHashCode(this); - } -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/MethodAdapter.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/MethodAdapter.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/MethodAdapter.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/MethodAdapter.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,186 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm; - -/** - * An empty {@link MethodVisitor} that delegates to another - * {@link MethodVisitor}. This class can be used as a super class to quickly - * implement usefull method adapter classes, just by overriding the necessary - * methods. - * - * @author Eric Bruneton - */ -public class MethodAdapter implements MethodVisitor { - - /** - * The {@link MethodVisitor} to which this adapter delegates calls. - */ - protected MethodVisitor mv; - - /** - * Constructs a new {@link MethodAdapter} object. - * - * @param mv the code visitor to which this adapter must delegate calls. - */ - public MethodAdapter(final MethodVisitor mv) { - this.mv = mv; - } - - public AnnotationVisitor visitAnnotationDefault() { - return mv.visitAnnotationDefault(); - } - - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) { - return mv.visitAnnotation(desc, visible); - } - - public AnnotationVisitor visitParameterAnnotation( - final int parameter, - final String desc, - final boolean visible) { - return mv.visitParameterAnnotation(parameter, desc, visible); - } - - public void visitAttribute(final Attribute attr) { - mv.visitAttribute(attr); - } - - public void visitCode() { - mv.visitCode(); - } - - public void visitFrame( - final int type, - final int nLocal, - final Object[] local, - final int nStack, - final Object[] stack) { - mv.visitFrame(type, nLocal, local, nStack, stack); - } - - public void visitInsn(final int opcode) { - mv.visitInsn(opcode); - } - - public void visitIntInsn(final int opcode, final int operand) { - mv.visitIntInsn(opcode, operand); - } - - public void visitVarInsn(final int opcode, final int var) { - mv.visitVarInsn(opcode, var); - } - - public void visitTypeInsn(final int opcode, final String desc) { - mv.visitTypeInsn(opcode, desc); - } - - public void visitFieldInsn( - final int opcode, - final String owner, - final String name, - final String desc) { - mv.visitFieldInsn(opcode, owner, name, desc); - } - - public void visitMethodInsn( - final int opcode, - final String owner, - final String name, - final String desc) { - mv.visitMethodInsn(opcode, owner, name, desc); - } - - public void visitJumpInsn(final int opcode, final Label label) { - mv.visitJumpInsn(opcode, label); - } - - public void visitLabel(final Label label) { - mv.visitLabel(label); - } - - public void visitLdcInsn(final Object cst) { - mv.visitLdcInsn(cst); - } - - public void visitIincInsn(final int var, final int increment) { - mv.visitIincInsn(var, increment); - } - - public void visitTableSwitchInsn( - final int min, - final int max, - final Label dflt, - final Label labels[]) { - mv.visitTableSwitchInsn(min, max, dflt, labels); - } - - public void visitLookupSwitchInsn( - final Label dflt, - final int keys[], - final Label labels[]) { - mv.visitLookupSwitchInsn(dflt, keys, labels); - } - - public void visitMultiANewArrayInsn(final String desc, final int dims) { - mv.visitMultiANewArrayInsn(desc, dims); - } - - public void visitTryCatchBlock( - final Label start, - final Label end, - final Label handler, - final String type) { - mv.visitTryCatchBlock(start, end, handler, type); - } - - public void visitLocalVariable( - final String name, - final String desc, - final String signature, - final Label start, - final Label end, - final int index) { - mv.visitLocalVariable(name, desc, signature, start, end, index); - } - - public void visitLineNumber(final int line, final Label start) { - mv.visitLineNumber(line, start); - } - - public void visitMaxs(final int maxStack, final int maxLocals) { - mv.visitMaxs(maxStack, maxLocals); - } - - public void visitEnd() { - mv.visitEnd(); - } -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/MethodVisitor.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/MethodVisitor.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/MethodVisitor.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/MethodVisitor.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,396 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm; - -/** - * A visitor to visit a Java method. The methods of this interface 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 interface MethodVisitor { - - // ------------------------------------------------------------------------- - // 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. - */ - AnnotationVisitor visitAnnotationDefault(); - - /** - * 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. - */ - AnnotationVisitor visitAnnotation(String desc, boolean visible); - - /** - * 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. - */ - AnnotationVisitor visitParameterAnnotation( - int parameter, - String desc, - boolean visible); - - /** - * Visits a non standard attribute of this method. - * - * @param attr an attribute. - */ - void visitAttribute(Attribute attr); - - /** - * Starts the visit of the method's code, if any (i.e. non abstract method). - */ - void 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 unconditionnal branch instruction - * such as GOTO or THROW, that is the target of a jump instruction, or that - * starts an exception handler ast. 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> Packed frames are basically - * "deltas" from the state of the previous frame (very first frame is - * implicitly defined by the method's parameters and access flags): <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> - * - * @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, or type - * descriptors for array types), 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. - */ - void visitFrame( - int type, - int nLocal, - Object[] local, - int nStack, - Object[] 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. - */ - void visitInsn(int 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}. - */ - void visitIntInsn(int opcode, int 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. - */ - void visitVarInsn(int opcode, int var); - - /** - * Visits a type instruction. A type instruction is an instruction that - * takes a type descriptor as parameter. - * - * @param opcode the opcode of the type instruction to be visited. This - * opcode is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF. - * @param desc the operand of the instruction to be visited. This operand is - * must be a fully qualified class name in internal form, or the type - * descriptor of an array type (see {@link Type Type}). - */ - void visitTypeInsn(int opcode, String desc); - - /** - * 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}). - */ - void visitFieldInsn(int opcode, String owner, String name, String 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}). - */ - void visitMethodInsn(int opcode, String owner, String name, String desc); - - /** - * 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. - */ - void visitJumpInsn(int opcode, Label label); - - /** - * Visits a label. A label designates the instruction that will be visited - * just after it. - * - * @param label a {@link Label Label} object. - */ - void visitLabel(Label label); - - // ------------------------------------------------------------------------- - // Special instructions - // ------------------------------------------------------------------------- - - /** - * Visits a LDC instruction. - * - * @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} (or a {@link Type} for - * <tt>.class</tt> constants, for classes whose version is 49.0 or - * more). - */ - void visitLdcInsn(Object cst); - - /** - * Visits an IINC instruction. - * - * @param var index of the local variable to be incremented. - * @param increment amount to increment the local variable by. - */ - void visitIincInsn(int var, int increment); - - /** - * Visits a TABLESWITCH instruction. - * - * @param min the minimum key value. - * @param max the maximum key value. - * @param dflt beginning of the default handler ast. - * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is - * the beginning of the handler ast for the <tt>min + i</tt> key. - */ - void visitTableSwitchInsn(int min, int max, Label dflt, Label labels[]); - - /** - * Visits a LOOKUPSWITCH instruction. - * - * @param dflt beginning of the default handler ast. - * @param keys the values of the keys. - * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is - * the beginning of the handler ast for the <tt>keys[i]</tt> key. - */ - void visitLookupSwitchInsn(Label dflt, int keys[], Label 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. - */ - void visitMultiANewArrayInsn(String desc, int dims); - - // ------------------------------------------------------------------------- - // Exceptions table entries, debug information, max stack and max locals - // ------------------------------------------------------------------------- - - /** - * Visits a try catch ast. - * - * @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). - */ - void visitTryCatchBlock(Label start, Label end, Label handler, String 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). - */ - void visitLocalVariable( - String name, - String desc, - String signature, - Label start, - Label end, - int 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). - */ - void visitLineNumber(int line, Label 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. - */ - void visitMaxs(int maxStack, int 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. - */ - void visitEnd(); -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/MethodWriter.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/MethodWriter.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/MethodWriter.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/MethodWriter.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,2691 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.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 implements MethodVisitor { - - /** - * Pseudo access flag used to denote constructors. - */ - final static int ACC_CONSTRUCTOR = 262144; - - /** - * Frame has exactly the same locals as the previous stack map frame and - * number of stack items is zero. - */ - final static 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 - */ - final static int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; // to 127 (40-7f) - - /** - * Reserved for future use - */ - final static 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; - */ - final static 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. - */ - final static 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; - */ - final static 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. - */ - final static int APPEND_FRAME = 252; // to 254 // fc-fe - - /** - * Full frame - */ - final static 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 final static int FRAMES = 0; - - /** - * Indicates that the maximum stack size and number of local variables must - * be automatically computed. - * - * @see #compute - */ - private final static int MAXS = 1; - - /** - * Indicates that nothing must be automatically computed. - * - * @see #compute - */ - private final static int NOTHING = 2; - - /** - * Next method writer (see {@link ClassWriter#firstMethod firstMethod}). - */ - MethodWriter next; - - /** - * The class writer to which this method must be added. - */ - 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 int name; - - /** - * The index of the constant pool item that contains the descriptor of this - * method. - */ - private int desc; - - /** - * The descriptor of this method. - */ - private 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 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 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; - - /** - * Index of the next element to be added in {@link #frame}. - */ - private int frameIndex; - - /** - * 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; - - /** - * Indicates if the instructions contain at least one JSR instruction. - */ - private boolean jsr; - - // ------------------------------------------------------------------------ - - /* - * Fields for the control flow graph analysis algorithm (used to compute the - * maximum stack size). A control flow graph contains one node per "basic - * ast", and one edge per "jump" from one basic ast to another. Each - * node (i.e., each basic ast) is represented by the Label object that - * corresponds to the first instruction of this basic ast. 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. - */ - private 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 - * and starting with the first basic ast. - */ - private Label labels; - - /** - * The previous basic ast. - */ - private Label previousBlock; - - /** - * The current basic ast. - */ - private Label currentBlock; - - /** - * The (relative) stack size after the last visited instruction. This size - * is relative to the beginning of the current basic ast, i.e., the true - * stack size after the last visited instruction is equal to the - * {@link Label#inputStackTop beginStackSize} of the current basic ast - * 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 ast, i.e., - * the true maximum stack size after the last visited instruction is equal - * to the {@link Label#inputStackTop beginStackSize} of the current basic - * ast 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) { - if (cw.firstMethod == null) { - cw.firstMethod = this; - } - else { - cw.lastMethod.next = this; - } - cw.lastMethod = this; - this.cw = cw; - this.access = access; - this.name = cw.newUTF8(name); - this.desc = cw.newUTF8(desc); - this.descriptor = desc; - 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) { - if (computeFrames && name.equals("<init>")) { - this.access |= ACC_CONSTRUCTOR; - } - // updates maxLocals - int size = getArgumentsAndReturnSizes(descriptor) >> 2; - if ((access & Opcodes.ACC_STATIC) != 0) { - --size; - } - maxLocals = size; - // creates and visits the label for the first basic ast - labels = new Label(); - labels.status |= Label.PUSHED; - visitLabel(labels); - } - } - - // ------------------------------------------------------------------------ - // Implementation of the MethodVisitor interface - // ------------------------------------------------------------------------ - - public AnnotationVisitor visitAnnotationDefault() { - annd = new ByteVector(); - return new AnnotationWriter(cw, false, annd, null, 0); - } - - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) { - 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; - } - - public AnnotationVisitor visitParameterAnnotation( - final int parameter, - final String desc, - final boolean visible) { - 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) { - 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; - } - - public void visitAttribute(final Attribute attr) { - if (attr.isCodeAttribute()) { - attr.next = cattrs; - cattrs = attr; - } - else { - attr.next = attrs; - attrs = attr; - } - } - - public void visitCode() { - } - - public void visitFrame( - final int type, - final int nLocal, - final Object[] local, - final int nStack, - final Object[] stack) { - if (compute == FRAMES) { - return; - } - - if (type == Opcodes.F_NEW) { - 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; - } - - switch (type) { - case Opcodes.F_FULL: - 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: - stackMap.putByte(SAME_FRAME_EXTENDED + nLocal) - .putShort(delta); - for (int i = 0; i < nLocal; ++i) { - writeFrameType(local[i]); - } - break; - case Opcodes.F_CHOP: - 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; - } - } - - 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 ast (no successor) - if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) - || opcode == Opcodes.ATHROW) { - noSuccessor(); - } - } - } - - 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); - } - } - - 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 ast (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()); - } - } - - public void visitTypeInsn(final int opcode, final String desc) { - Item i = cw.newClassItem(desc); - // 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); - } - - 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); - } - - 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 = 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 = getArgumentsAndReturnSizes(desc); - i.intVal = argSize; - } - code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0); - } - else { - code.put12(opcode, i.index); - } - } - - 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 ast - addSuccessor(Edge.NORMAL, label); - if (opcode != Opcodes.GOTO) { - // creates a Label for the next basic ast - nextInsn = new Label(); - } - } - else { - if (opcode == Opcodes.JSR) { - jsr = true; - currentBlock.status |= Label.JSR; - addSuccessor(stackSize + 1, label); - // creates a Label for the next basic ast - nextInsn = new Label(); - /* - * note that, by construction in this method, a JSR ast - * 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 ast, and starts a new basic ast - visitLabel(nextInsn); - } - if (opcode == Opcodes.GOTO) { - noSuccessor(); - } - } - } - - 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 ast - currentBlock.status |= (label.status & Label.TARGET); - label.frame = currentBlock.frame; - return; - } - // ends current ast (with one new successor) - addSuccessor(Edge.NORMAL, label); - } - // begins a new current ast - currentBlock = label; - if (label.frame == null) { - label.frame = new Frame(); - label.frame.owner = label; - } - // updates the basic ast 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 ast (with one new successor) - currentBlock.outputStackMax = maxStackSize; - addSuccessor(stackSize, label); - } - // begins a new current ast - currentBlock = label; - // resets the relative current and max stack sizes - stackSize = 0; - maxStackSize = 0; - // updates the basic ast list - if (previousBlock != null) { - previousBlock.successor = label; - } - previousBlock = label; - } - } - - 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); - } - } - - 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); - } - } - - 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.length += (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); - } - - 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.length += (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 ast 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 ast successors - addSuccessor(stackSize, dflt); - for (int i = 0; i < labels.length; ++i) { - addSuccessor(stackSize, labels[i]); - } - } - // ends current ast - noSuccessor(); - } - } - - 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); - } - - 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; - } - - 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; - } - } - } - - public void visitLineNumber(final int line, final Label start) { - if (lineNumber == null) { - lineNumber = new ByteVector(); - } - ++lineNumberCount; - lineNumber.putShort(start.position); - lineNumber.putShort(line); - } - - public void visitMaxs(final int maxStack, final int maxLocals) { - if (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 ast 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 ast from the list of changed basic blocks - Label l = changed; - changed = changed.next; - l.next = null; - f = l.frame; - // a reacheable jump target must be stored in the stack map - if ((l.status & Label.TARGET) != 0) { - l.status |= Label.STORE; - } - // all visited labels are reacheable, 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 ast - 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; - } - } - this.maxStack = max; - - // 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 ast - Label k = l.successor; - int start = l.position; - int end = (k == null ? code.length : k.position) - 1; - // if non empty basic ast - if (end >= start) { - // 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 ast - startFrame(start, 0, 1); - frame[frameIndex++] = Frame.OBJECT - | cw.addType("java/lang/Throwable"); - endFrame(); - } - } - l = l.successor; - } - } - 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) { - // if l is a JSR ast, adds b after the first two edges - // to preserve the hypothesis about JSR ast successors - // order (see {@link #visitJumpInsn}) - b.next = l.successors.next.next; - l.successors.next.next = b; - } - else { - b.next = l.successors; - l.successors = b; - } - // goes to the next label - l = l.successor; - } - handler = handler.next; - } - - if (jsr) { - // completes the control flow graph with the RET successors - /* - * first step: finds the subroutines. This step determines, for - * each basic ast, to which subroutine(s) it belongs, and - * stores this set as a bit set in the {@link Label#status} - * field. Subroutines are numbered with powers of two, from - * 0x1000 to 0x80000000 (so there must be at most 20 subroutines - * in a method). - */ - // finds the basic blocks that belong to the "core" subroutine - int id = 0x1000; - findSubroutine(labels, id); - // 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 does not have an id yet... - if ((subroutine.status & ~0xFFF) == 0) { - // ...assigns it a new id and finds its basic blocks - id = id << 1; - findSubroutine(subroutine, id); - } - } - l = l.successor; - } - // second step: finds the successors of RET blocks - findSubroutineSuccessors(0x1000, new Label[10], 0); - } - - /* - * control flow analysis algorithm: while the ast stack is not - * empty, pop a ast from this stack, update the max stack size, - * compute the true (non relative) begin stack size of the - * successors of this ast, 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 ast stack are the true (non relative) beginning - * stack sizes of these blocks. - */ - int max = 0; - Label stack = labels; - while (stack != null) { - // pops a ast from the stack - Label l = stack; - stack = stack.next; - // computes the true (non relative) max stack size of this ast - int start = l.inputStackTop; - int blockMax = start + l.outputStackMax; - // updates the global max stack size - if (blockMax > max) { - max = blockMax; - } - // analyses the successors of the ast - 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 = max; - } - else { - this.maxStack = maxStack; - this.maxLocals = maxLocals; - } - } - - public void visitEnd() { - } - - // ------------------------------------------------------------------------ - // Utility methods: control flow analysis algorithm - // ------------------------------------------------------------------------ - - /** - * 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>). - */ - 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; - } - } - } - - /** - * Adds a successor to the {@link #currentBlock currentBlock} ast. - * - * @param info information about the control flow edge to be added. - * @param successor the successor ast to be added to the current ast. - */ - 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 ast - b.next = currentBlock.successors; - currentBlock.successors = b; - } - - /** - * Ends the current basic ast. This method must be used in the case where - * the current basic ast 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; - } - - /** - * Finds the basic blocks that belong to a given subroutine, and marks these - * blocks as belonging to this subroutine (by using {@link Label#status} as - * a bit set (see {@link #visitMaxs}). This recursive method follows the - * control flow graph to find all the blocks that are reachable from the - * given ast WITHOUT following any JSR target. - * - * @param block a ast that belongs to the subroutine - * @param id the id of this subroutine - */ - private void findSubroutine(final Label block, final int id) { - // if 'ast' is already marked as belonging to subroutine 'id', returns - if ((block.status & id) != 0) { - return; - } - // marks 'ast' as belonging to subroutine 'id' - block.status |= id; - // calls this method recursively on each successor, except JSR targets - Edge e = block.successors; - while (e != null) { - // if 'ast' is a JSR ast, then 'ast.successors.next' leads - // to the JSR target (see {@link #visitJumpInsn}) and must therefore - // not be followed - if ((block.status & Label.JSR) == 0 || e != block.successors.next) { - findSubroutine(e.successor, id); - } - e = e.next; - } - } - - /** - * Finds the successors of the RET blocks of the specified subroutine, and - * of any nested subroutine it calls. - * - * @param id id of the subroutine whose RET ast successors must be found. - * @param JSRs the JSR blocks that were followed to reach this subroutine. - * @param nJSRs number of JSR blocks in the JSRs array. - */ - private void findSubroutineSuccessors( - final int id, - final Label[] JSRs, - final int nJSRs) { - // iterates over all the basic blocks... - Label l = labels; - while (l != null) { - // for those that belong to subroutine 'id'... - if ((l.status & id) != 0) { - if ((l.status & Label.JSR) != 0) { - // finds the subroutine to which 'l' leads by following the - // second edge of l.successors (see {@link #visitJumpInsn}) - int nId = l.successors.next.successor.status & ~0xFFF; - if (nId != id) { - // calls this method recursively with l pushed onto the - // JSRs stack to find the successors of the RET blocks - // of this nested subroutine 'nId' - JSRs[nJSRs] = l; - findSubroutineSuccessors(nId, JSRs, nJSRs + 1); - } - } - else if ((l.status & Label.RET) != 0) { - /* - * finds the JSR ast in the JSRs stack that corresponds to - * this RET ast, and updates the successors of this RET - * ast accordingly. This corresponding JSR is the one that - * leads to the subroutine to which the RET ast belongs. - * But the RET ast can belong to several subroutines (if a - * nested subroutine returns to its parent subroutine - * implicitely, without a RET). So, in fact, the JSR that - * corresponds to this RET is the first ast in the JSRs - * stack, starting from the bottom of the stack, that leads - * to a subroutine to which the RET ast belongs. - */ - for (int i = 0; i < nJSRs; ++i) { - int JSRstatus = JSRs[i].successors.next.successor.status; - if (((JSRstatus & ~0xFFF) & (l.status & ~0xFFF)) != 0) { - Edge e = new Edge(); - e.info = l.inputStackTop; - e.successor = JSRs[i].successors.successor; - e.next = l.successors; - l.successors = e; - break; - } - } - } - } - l = l.successor; - } - } - - // ------------------------------------------------------------------------ - // 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 - 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(); - } - - /** - * 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. - */ - private void 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; - frameIndex = 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. - resizeInstructions(); - } - int size = 8; - if (code.length > 0) { - 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 - && (cw.version & 0xffff) < Opcodes.V1_5) { - cw.newUTF8("Synthetic"); - size += 6; - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - cw.newUTF8("Deprecated"); - size += 6; - } - if (signature != null) { - cw.newUTF8("Signature"); - cw.newUTF8(signature); - size += 8; - } - if (annd != null) { - cw.newUTF8("AnnotationDefault"); - size += 6 + annd.length; - } - if (anns != null) { - cw.newUTF8("RuntimeVisibleAnnotations"); - size += 8 + anns.getSize(); - } - if (ianns != null) { - cw.newUTF8("RuntimeInvisibleAnnotations"); - size += 8 + ianns.getSize(); - } - if (panns != null) { - cw.newUTF8("RuntimeVisibleParameterAnnotations"); - size += 7 + 2 * panns.length; - for (int i = panns.length - 1; i >= 0; --i) { - size += panns[i] == null ? 0 : panns[i].getSize(); - } - } - if (ipanns != null) { - cw.newUTF8("RuntimeInvisibleParameterAnnotations"); - size += 7 + 2 * ipanns.length; - for (int i = ipanns.length - 1; i >= 0; --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) { - out.putShort(access).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 - && (cw.version & 0xffff) < Opcodes.V1_5) { - ++attributeCount; - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - ++attributeCount; - } - if (signature != null) { - ++attributeCount; - } - if (annd != null) { - ++attributeCount; - } - if (anns != null) { - ++attributeCount; - } - if (ianns != null) { - ++attributeCount; - } - if (panns != null) { - ++attributeCount; - } - if (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 - && (cw.version & 0xffff) < Opcodes.V1_5) { - out.putShort(cw.newUTF8("Synthetic")).putInt(0); - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - out.putShort(cw.newUTF8("Deprecated")).putInt(0); - } - if (signature != null) { - out.putShort(cw.newUTF8("Signature")) - .putInt(2) - .putShort(cw.newUTF8(signature)); - } - if (annd != null) { - out.putShort(cw.newUTF8("AnnotationDefault")); - out.putInt(annd.length); - out.putByteArray(annd.data, 0, annd.length); - } - if (anns != null) { - out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); - anns.put(out); - } - if (ianns != null) { - out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); - ianns.put(out); - } - if (panns != null) { - out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations")); - AnnotationWriter.put(panns, out); - } - if (ipanns != null) { - out.putShort(cw.newUTF8("RuntimeInvisibleParameterAnnotations")); - AnnotationWriter.put(ipanns, 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: - 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.length += (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.length += (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: - 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); - 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 ast 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 -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/Opcodes.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/Opcodes.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/Opcodes.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/Opcodes.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,341 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.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 { - - // 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; - - // 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 = 131072; // 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; - - // 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 UNUSED = 186; // NOT VISITED - 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 -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/package.html mvel-2.0.19-gil/src/main/java/org/mvel2/asm/package.html --- mvel-2.0.19/src/main/java/org/mvel2/asm/package.html 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/package.html 1970-01-01 01:00:00.000000000 +0100 @@ -1,87 +0,0 @@ -<html> -<!-- - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. ---> -<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 org.mvel.asm.ClassVisitor ClassVisitor}, - {@link org.mvel.asm.FieldVisitor FieldVisitor} and - {@link org.mvel.asm.MethodVisitor MethodVisitor} interfaces, which allow - one to visit the fields and methods of a class, including the bytecode - instructions of each method. - -<p> - In addition to these main interfaces, ASM provides a {@link - org.mvel.asm.ClassReader ClassReader} class, that can parse an - existing class and make a given visitor visit it. ASM also provides - a {@link org.mvel.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 - org.mvel.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 - org.mvel.asm.ClassReader ClassReader} class to analyze - the original class, a class modifier, and a {@link org.mvel.asm.ClassWriter - ClassWriter} to construct the modified class. The class modifier - is just a {@link org.mvel.asm.ClassVisitor ClassVisitor} - that delegates most of the work to another {@link org.mvel.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, ASM provides the {@link org.mvel.asm.ClassAdapter - ClassAdapter} and {@link org.mvel.asm.MethodAdapter MethodAdapter} - classes, which implement the {@link org.mvel.asm.ClassVisitor ClassVisitor} - and {@link org.mvel.asm.MethodVisitor MethodVisitor} interfaces by - delegating all work to other visitors. 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 42KB, 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)! - - @since ASM 1.3 -</body> -</html> diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/signature/package.html mvel-2.0.19-gil/src/main/java/org/mvel2/asm/signature/package.html --- mvel-2.0.19/src/main/java/org/mvel2/asm/signature/package.html 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/signature/package.html 1970-01-01 01:00:00.000000000 +0100 @@ -1,36 +0,0 @@ -<html> -<!-- - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. ---> -<body> -Provides support for type signatures. - -@since ASM 2.0 -</body> -</html> diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/signature/SignatureReader.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/signature/SignatureReader.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/signature/SignatureReader.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/signature/SignatureReader.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,233 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm.signature; - -/** - * A type signature parser to make a signature visitor visit an existing - * signature. - * - * @author Thomas Hallgren - * @author Eric Bruneton - */ -public class SignatureReader { - - /** - * The signature to be read. - */ - private final String signature; - - /** - * Constructs a {@link SignatureReader} for the given signature. - * - * @param signature A <i>ClassSignature</i>, <i>MethodTypeSignature</i>, - * or <i>FieldTypeSignature</i>. - */ - public SignatureReader(final String signature) { - this.signature = signature; - } - - /** - * Makes the given visitor visit the signature of this - * {@link SignatureReader}. This signature is the one specified in the - * constructor (see {@link #SignatureReader(String) SignatureReader}). This - * method is intended to be called on a {@link SignatureReader} that was - * created using a <i>ClassSignature</i> (such as the - * <code>signature</code> parameter of the - * {@link org.objectweb.asm.ClassVisitor#visit ClassVisitor.visit} method) - * or a <i>MethodTypeSignature</i> (such as the <code>signature</code> - * parameter of the - * {@link org.objectweb.asm.ClassVisitor#visitMethod ClassVisitor.visitMethod} - * method). - * - * @param v the visitor that must visit this signature. - */ - public void accept(final SignatureVisitor v) { - String signature = this.signature; - int len = signature.length(); - int pos; - char c; - - if (signature.charAt(0) == '<') { - pos = 2; - do { - int end = signature.indexOf(':', pos); - v.visitFormalTypeParameter(signature.substring(pos - 1, end)); - pos = end + 1; - - c = signature.charAt(pos); - if (c == 'L' || c == '[' || c == 'T') { - pos = parseType(signature, pos, v.visitClassBound()); - } - - for (;;) { - if ((c = signature.charAt(pos++)) == ':') { - pos = parseType(signature, pos, v.visitInterfaceBound()); - } else { - break; - } - } - } while (c != '>'); - } else { - pos = 0; - } - - if (signature.charAt(pos) == '(') { - pos = pos + 1; - while (signature.charAt(pos) != ')') { - pos = parseType(signature, pos, v.visitParameterType()); - } - pos = parseType(signature, pos + 1, v.visitReturnType()); - while (pos < len) { - pos = parseType(signature, pos + 1, v.visitExceptionType()); - } - } else { - pos = parseType(signature, pos, v.visitSuperclass()); - while (pos < len) { - pos = parseType(signature, pos, v.visitInterface()); - } - } - } - - /** - * Makes the given visitor visit the signature of this - * {@link SignatureReader}. This signature is the one specified in the - * constructor (see {@link #SignatureReader(String) SignatureReader}). This - * method is intended to be called on a {@link SignatureReader} that was - * created using a <i>FieldTypeSignature</i>, such as the - * <code>signature</code> parameter of the - * {@link org.objectweb.asm.ClassVisitor#visitField - * ClassVisitor.visitField} or {@link - * org.objectweb.asm.MethodVisitor#visitLocalVariable - * MethodVisitor.visitLocalVariable} methods. - * - * @param v the visitor that must visit this signature. - */ - public void acceptType(final SignatureVisitor v) { - parseType(this.signature, 0, v); - } - - /** - * Parses a field type signature and makes the given visitor visit it. - * - * @param signature a string containing the signature that must be parsed. - * @param pos index of the first character of the signature to parsed. - * @param v the visitor that must visit this signature. - * @return the index of the first character after the parsed signature. - */ - private static int parseType( - final String signature, - int pos, - final SignatureVisitor v) - { - char c; - int start, end; - boolean visited, inner; - String name; - - switch (c = signature.charAt(pos++)) { - case 'Z': - case 'C': - case 'B': - case 'S': - case 'I': - case 'F': - case 'J': - case 'D': - case 'V': - v.visitBaseType(c); - return pos; - - case '[': - return parseType(signature, pos, v.visitArrayType()); - - case 'T': - end = signature.indexOf(';', pos); - v.visitTypeVariable(signature.substring(pos, end)); - return end + 1; - - default: // case 'L': - start = pos; - visited = false; - inner = false; - for (;;) { - switch (c = signature.charAt(pos++)) { - case '.': - case ';': - if (!visited) { - name = signature.substring(start, pos - 1); - if (inner) { - v.visitInnerClassType(name); - } else { - v.visitClassType(name); - } - } - if (c == ';') { - v.visitEnd(); - return pos; - } - start = pos; - visited = false; - inner = true; - break; - - case '<': - name = signature.substring(start, pos - 1); - if (inner) { - v.visitInnerClassType(name); - } else { - v.visitClassType(name); - } - visited = true; - top: for (;;) { - switch (c = signature.charAt(pos)) { - case '>': - break top; - case '*': - ++pos; - v.visitTypeArgument(); - break; - case '+': - case '-': - pos = parseType(signature, - pos + 1, - v.visitTypeArgument(c)); - break; - default: - pos = parseType(signature, - pos, - v.visitTypeArgument('=')); - break; - } - } - } - } - } - } -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/signature/SignatureVisitor.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/signature/SignatureVisitor.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/signature/SignatureVisitor.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/signature/SignatureVisitor.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,185 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm.signature; - -/** - * A visitor to visit a generic signature. The methods of this interface must be - * called in one of the three following orders (the last one is the only valid - * order for a {@link SignatureVisitor} that is returned by a method of this - * interface): <ul> <li><i>ClassSignature</i> = ( - * <tt>visitFormalTypeParameter</tt> - * <tt>visitClassBound</tt>? - * <tt>visitInterfaceBound</tt>* )* ( <tt>visitSuperClass</tt> - * <tt>visitInterface</tt>* )</li> - * <li><i>MethodSignature</i> = ( <tt>visitFormalTypeParameter</tt> - * <tt>visitClassBound</tt>? - * <tt>visitInterfaceBound</tt>* )* ( <tt>visitParameterType</tt>* - * <tt>visitReturnType</tt> - * <tt>visitExceptionType</tt>* )</li> <li><i>TypeSignature</i> = - * <tt>visitBaseType</tt> | <tt>visitTypeVariable</tt> | - * <tt>visitArrayType</tt> | ( - * <tt>visitClassType</tt> <tt>visitTypeArgument</tt>* ( - * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )* - * <tt>visitEnd</tt> ) )</li> </ul> - * - * @author Thomas Hallgren - * @author Eric Bruneton - */ -public interface SignatureVisitor { - - /** - * Wildcard for an "extends" type argument. - */ - char EXTENDS = '+'; - - /** - * Wildcard for a "super" type argument. - */ - char SUPER = '-'; - - /** - * Wildcard for a normal type argument. - */ - char INSTANCEOF = '='; - - /** - * Visits a formal type parameter. - * - * @param name the name of the formal parameter. - */ - void visitFormalTypeParameter(String name); - - /** - * Visits the class bound of the last visited formal type parameter. - * - * @return a non null visitor to visit the signature of the class bound. - */ - SignatureVisitor visitClassBound(); - - /** - * Visits an interface bound of the last visited formal type parameter. - * - * @return a non null visitor to visit the signature of the interface bound. - */ - SignatureVisitor visitInterfaceBound(); - - /** - * Visits the type of the super class. - * - * @return a non null visitor to visit the signature of the super class - * type. - */ - SignatureVisitor visitSuperclass(); - - /** - * Visits the type of an interface implemented by the class. - * - * @return a non null visitor to visit the signature of the interface type. - */ - SignatureVisitor visitInterface(); - - /** - * Visits the type of a method parameter. - * - * @return a non null visitor to visit the signature of the parameter type. - */ - SignatureVisitor visitParameterType(); - - /** - * Visits the return type of the method. - * - * @return a non null visitor to visit the signature of the return type. - */ - SignatureVisitor visitReturnType(); - - /** - * Visits the type of a method exception. - * - * @return a non null visitor to visit the signature of the exception type. - */ - SignatureVisitor visitExceptionType(); - - /** - * Visits a signature corresponding to a primitive type. - * - * @param descriptor the descriptor of the primitive type, or 'V' for - * <tt>void</tt>. - */ - void visitBaseType(char descriptor); - - /** - * Visits a signature corresponding to a type variable. - * - * @param name the name of the type variable. - */ - void visitTypeVariable(String name); - - /** - * Visits a signature corresponding to an array type. - * - * @return a non null visitor to visit the signature of the array element - * type. - */ - SignatureVisitor visitArrayType(); - - /** - * Starts the visit of a signature corresponding to a class or interface - * type. - * - * @param name the internal name of the class or interface. - */ - void visitClassType(String name); - - /** - * Visits an inner class. - * - * @param name the local name of the inner class in its enclosing class. - */ - void visitInnerClassType(String name); - - /** - * Visits an unbounded type argument of the last visited class or inner - * class type. - */ - void visitTypeArgument(); - - /** - * Visits a type argument of the last visited class or inner class type. - * - * @param wildcard '+', '-' or '='. - * @return a non null visitor to visit the signature of the type argument. - */ - SignatureVisitor visitTypeArgument(char wildcard); - - /** - * Ends the visit of a signature corresponding to a class or interface type. - */ - void visitEnd(); -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/signature/SignatureWriter.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/signature/SignatureWriter.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/signature/SignatureWriter.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/signature/SignatureWriter.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,207 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm.signature; - -/** - * A signature visitor that generates signatures in string format. - * - * @author Thomas Hallgren - * @author Eric Bruneton - */ -public class SignatureWriter implements SignatureVisitor { - - /** - * Buffer used to construct the signature. - */ - private final StringBuffer buf = new StringBuffer(); - - /** - * Indicates if the signature contains formal type parameters. - */ - private boolean hasFormals; - - /** - * Indicates if the signature contains method parameter types. - */ - private boolean hasParameters; - - /** - * Stack used to keep track of class types that have arguments. Each element - * of this stack is a boolean encoded in one bit. The top of the stack is - * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping = - * /2. - */ - private int argumentStack; - - /** - * Constructs a new {@link SignatureWriter} object. - */ - public SignatureWriter() { - } - - // ------------------------------------------------------------------------ - // Implementation of the SignatureVisitor interface - // ------------------------------------------------------------------------ - - public void visitFormalTypeParameter(final String name) { - if (!hasFormals) { - hasFormals = true; - buf.append('<'); - } - buf.append(name); - buf.append(':'); - } - - public SignatureVisitor visitClassBound() { - return this; - } - - public SignatureVisitor visitInterfaceBound() { - buf.append(':'); - return this; - } - - public SignatureVisitor visitSuperclass() { - endFormals(); - return this; - } - - public SignatureVisitor visitInterface() { - return this; - } - - public SignatureVisitor visitParameterType() { - endFormals(); - if (!hasParameters) { - hasParameters = true; - buf.append('('); - } - return this; - } - - public SignatureVisitor visitReturnType() { - endFormals(); - if (!hasParameters) { - buf.append('('); - } - buf.append(')'); - return this; - } - - public SignatureVisitor visitExceptionType() { - buf.append('^'); - return this; - } - - public void visitBaseType(final char descriptor) { - buf.append(descriptor); - } - - public void visitTypeVariable(final String name) { - buf.append('T'); - buf.append(name); - buf.append(';'); - } - - public SignatureVisitor visitArrayType() { - buf.append('['); - return this; - } - - public void visitClassType(final String name) { - buf.append('L'); - buf.append(name); - argumentStack *= 2; - } - - public void visitInnerClassType(final String name) { - endArguments(); - buf.append('.'); - buf.append(name); - argumentStack *= 2; - } - - public void visitTypeArgument() { - if (argumentStack % 2 == 0) { - ++argumentStack; - buf.append('<'); - } - buf.append('*'); - } - - public SignatureVisitor visitTypeArgument(final char wildcard) { - if (argumentStack % 2 == 0) { - ++argumentStack; - buf.append('<'); - } - if (wildcard != '=') { - buf.append(wildcard); - } - return this; - } - - public void visitEnd() { - endArguments(); - buf.append(';'); - } - - /** - * Returns the signature that was built by this signature writer. - * - * @return the signature that was built by this signature writer. - */ - public String toString() { - return buf.toString(); - } - - // ------------------------------------------------------------------------ - // Utility methods - // ------------------------------------------------------------------------ - - /** - * Ends the formal type parameters section of the signature. - */ - private void endFormals() { - if (hasFormals) { - hasFormals = false; - buf.append('>'); - } - } - - /** - * Ends the type arguments of a class or inner class type. - */ - private void endArguments() { - if (argumentStack % 2 != 0) { - buf.append('>'); - } - argumentStack /= 2; - } -} \ Manca newline alla fine del file diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/Type.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/Type.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/Type.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/Type.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,815 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; - -/** - * A Java 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 final static int VOID = 0; - - /** - * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}. - */ - public final static int BOOLEAN = 1; - - /** - * The sort of the <tt>char</tt> type. See {@link #getSort getSort}. - */ - public final static int CHAR = 2; - - /** - * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}. - */ - public final static int BYTE = 3; - - /** - * The sort of the <tt>short</tt> type. See {@link #getSort getSort}. - */ - public final static int SHORT = 4; - - /** - * The sort of the <tt>int</tt> type. See {@link #getSort getSort}. - */ - public final static int INT = 5; - - /** - * The sort of the <tt>float</tt> type. See {@link #getSort getSort}. - */ - public final static int FLOAT = 6; - - /** - * The sort of the <tt>long</tt> type. See {@link #getSort getSort}. - */ - public final static int LONG = 7; - - /** - * The sort of the <tt>double</tt> type. See {@link #getSort getSort}. - */ - public final static int DOUBLE = 8; - - /** - * The sort of array reference types. See {@link #getSort getSort}. - */ - public final static int ARRAY = 9; - - /** - * The sort of object reference type. See {@link #getSort getSort}. - */ - public final static int OBJECT = 10; - - /** - * The <tt>void</tt> type. - */ - public final static Type VOID_TYPE = new Type(VOID); - - /** - * The <tt>boolean</tt> type. - */ - public final static Type BOOLEAN_TYPE = new Type(BOOLEAN); - - /** - * The <tt>char</tt> type. - */ - public final static Type CHAR_TYPE = new Type(CHAR); - - /** - * The <tt>byte</tt> type. - */ - public final static Type BYTE_TYPE = new Type(BYTE); - - /** - * The <tt>short</tt> type. - */ - public final static Type SHORT_TYPE = new Type(SHORT); - - /** - * The <tt>int</tt> type. - */ - public final static Type INT_TYPE = new Type(INT); - - /** - * The <tt>float</tt> type. - */ - public final static Type FLOAT_TYPE = new Type(FLOAT); - - /** - * The <tt>long</tt> type. - */ - public final static Type LONG_TYPE = new Type(LONG); - - /** - * The <tt>double</tt> type. - */ - public final static Type DOUBLE_TYPE = new Type(DOUBLE); - - // ------------------------------------------------------------------------ - // Fields - // ------------------------------------------------------------------------ - - /** - * The sort of this Java type. - */ - private final int sort; - - /** - * A buffer containing the descriptor of this Java type. This field is only - * used for reference types. - */ - private char[] buf; - - /** - * The offset of the descriptor of this Java type in {@link #buf buf}. This - * field is only used for reference types. - */ - private int off; - - /** - * The length of the descriptor of this Java type. - */ - private int len; - - // ------------------------------------------------------------------------ - // Constructors - // ------------------------------------------------------------------------ - - /** - * Constructs a primitive type. - * - * @param sort the sort of the primitive type to be constructed. - */ - private Type(final int sort) { - this.sort = sort; - this.len = 1; - } - - /** - * 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 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 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 {@link Type#OBJECT} type for the given internal class name. - * This is a shortcut method for <code>Type.getType("L"+name+";")</code>. - * <i>Note that opposed to {@link Type#getType(String)}, this method takes - * internal class names and not class descriptor.</i> - * - * @param name an internal class name. - * @return the the {@link Type#OBJECT} type for the given class name. - */ - public static Type getObjectType(String name) { - int l = name.length(); - char[] buf = new char[l + 2]; - buf[0] = 'L'; - buf[l + 1] = ';'; - name.getChars(0, l, buf, 1); - return new Type(OBJECT, buf, 0, l + 2); - } - - /** - * 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; - 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()); - } - - /** - * Returns the Java type corresponding to the given type descriptor. - * - * @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': - default: - len = 1; - while (buf[off + len] != ';') { - ++len; - } - return new Type(OBJECT, buf, off, len + 1); - } - } - - // ------------------------------------------------------------------------ - // 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} or - * {@link #OBJECT OBJECT}. - */ - 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 name of the class corresponding to this type. - * - * @return the fully qualified 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: - default: - return new String(buf, off + 1, len - 2).replace('/', '.'); - } - } - - /** - * Returns the internal name of the class corresponding to this object type. - * The internal name of a class is its fully qualified name, where '.' are - * replaced by '/'. This method should only be used for an object type. - * - * @return the internal name of the class corresponding to this object type. - */ - public String getInternalName() { - return new String(buf, off + 1, len - 2); - } - - // ------------------------------------------------------------------------ - // 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) { - switch (sort) { - case VOID: - buf.append('V'); - return; - case BOOLEAN: - buf.append('Z'); - return; - case CHAR: - buf.append('C'); - return; - case BYTE: - buf.append('B'); - return; - case SHORT: - buf.append('S'); - return; - case INT: - buf.append('I'); - return; - case FLOAT: - buf.append('F'); - return; - case LONG: - buf.append('J'); - return; - case DOUBLE: - buf.append('D'); - return; - // case ARRAY: - // case OBJECT: - default: - 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, where '.' are replaced by '/'. - * - * @param c an object 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. - * - * @return the size of values of this type, i.e., 2 for <tt>long</tt> and - * <tt>double</tt>, and 1 otherwise. - */ - public int getSize() { - return sort == LONG || sort == DOUBLE ? 2 : 1; - } - - /** - * Returns a JVM instruction opcode adapted to this Java type. - * - * @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) { - switch (sort) { - case BOOLEAN: - case BYTE: - return opcode + 5; - case CHAR: - return opcode + 6; - case SHORT: - return opcode + 7; - case INT: - return opcode; - case FLOAT: - return opcode + 2; - case LONG: - return opcode + 1; - case DOUBLE: - return opcode + 3; - // case ARRAY: - // case OBJECT: - default: - return opcode + 4; - } - } - else { - switch (sort) { - case VOID: - return opcode + 5; - case BOOLEAN: - case CHAR: - case BYTE: - case SHORT: - case INT: - return opcode; - case FLOAT: - return opcode + 2; - case LONG: - return opcode + 1; - case DOUBLE: - return opcode + 3; - // case ARRAY: - // case OBJECT: - default: - return opcode + 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. - */ - 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 == Type.OBJECT || sort == Type.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. - */ - public int hashCode() { - int hc = 13 * sort; - if (sort == Type.OBJECT || sort == Type.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. - */ - public String toString() { - return getDescriptor(); - } -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/util/AbstractVisitor.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/util/AbstractVisitor.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/util/AbstractVisitor.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/util/AbstractVisitor.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,202 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm.util; - -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; - -import org.mvel2.asm.Attribute; - -/** - * An abstract visitor. - * - * @author Eric Bruneton - */ -public abstract class AbstractVisitor { - - /** - * The names of the Java Virtual Machine opcodes. - */ - public final static String[] OPCODES; - /** - * Types for <code>operand</code> parameter of the - * {@link org.objectweb.asm.MethodVisitor#visitIntInsn} method when - * <code>opcode</code> is <code>NEWARRAY</code>. - */ - public final static String[] TYPES; - - static { - String s = "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,BIPUSH,SIPUSH,LDC,,," - + "ILOAD,LLOAD,FLOAD,DLOAD,ALOAD,,,,,,,,,,,,,,,,,,,,,IALOAD," - + "LALOAD,FALOAD,DALOAD,AALOAD,BALOAD,CALOAD,SALOAD,ISTORE," - + "LSTORE,FSTORE,DSTORE,ASTORE,,,,,,,,,,,,,,,,,,,,,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,IINC,I2L," - + "I2F,I2D,L2I,L2F,L2D,F2I,F2L,F2D,D2I,D2L,D2F,I2B,I2C,I2S,LCMP," - + "FCMPL,FCMPG,DCMPL,DCMPG,IFEQ,IFNE,IFLT,IFGE,IFGT,IFLE," - + "IF_ICMPEQ,IF_ICMPNE,IF_ICMPLT,IF_ICMPGE,IF_ICMPGT,IF_ICMPLE," - + "IF_ACMPEQ,IF_ACMPNE,GOTO,JSR,RET,TABLESWITCH,LOOKUPSWITCH," - + "IRETURN,LRETURN,FRETURN,DRETURN,ARETURN,RETURN,GETSTATIC," - + "PUTSTATIC,GETFIELD,PUTFIELD,INVOKEVIRTUAL,INVOKESPECIAL," - + "INVOKESTATIC,INVOKEINTERFACE,,NEW,NEWARRAY,ANEWARRAY," - + "ARRAYLENGTH,ATHROW,CHECKCAST,INSTANCEOF,MONITORENTER," - + "MONITOREXIT,,MULTIANEWARRAY,IFNULL,IFNONNULL,"; - OPCODES = new String[200]; - int i = 0; - int j = 0; - int l; - while ((l = s.indexOf(',', j)) > 0) { - OPCODES[i++] = j + 1 == l ? null : s.substring(j, l); - j = l + 1; - } - - s = "T_BOOLEAN,T_CHAR,T_FLOAT,T_DOUBLE,T_BYTE,T_SHORT,T_INT,T_LONG,"; - TYPES = new String[12]; - j = 0; - i = 4; - while ((l = s.indexOf(',', j)) > 0) { - TYPES[i++] = s.substring(j, l); - j = l + 1; - } - } - - /** - * The text to be printed. Since the code of methods is not necessarily - * visited in sequential order, one method after the other, but can be - * interlaced (some instructions from method one, then some instructions - * from method two, then some instructions from method one again...), it is - * not possible to print the visited instructions directly to a sequential - * stream. A class is therefore printed in a two steps process: a string - * tree is constructed during the visit, and printed to a sequential stream - * at the end of the visit. This string tree is stored in this field, as a - * string list that can contain other string lists, which can themselves - * contain other string lists, and so on. - */ - public final List text; - - /** - * A buffer that can be used to create strings. - */ - protected final StringBuffer buf; - - /** - * Constructs a new {@link AbstractVisitor}. - */ - protected AbstractVisitor() { - this.text = new ArrayList(); - this.buf = new StringBuffer(); - } - - /** - * Returns the text constructed by this visitor. - * - * @return the text constructed by this visitor. - */ - public List getText() { - return text; - } - - /** - * Prints the text constructed by this visitor. - * - * @param pw the print writer to be used. - */ - public void print(final PrintWriter pw) { - printList(pw, text); - } - - /** - * Appends a quoted string to a given buffer. - * - * @param buf the buffer where the string must be added. - * @param s the string to be added. - */ - public static void appendString(final StringBuffer buf, final String s) { - buf.append('\"'); - for (int i = 0; i < s.length(); ++i) { - char c = s.charAt(i); - if (c == '\n') { - buf.append("\\n"); - } else if (c == '\r') { - buf.append("\\r"); - } else if (c == '\\') { - buf.append("\\\\"); - } else if (c == '"') { - buf.append("\\\""); - } else if (c < 0x20 || c > 0x7f) { - buf.append("\\u"); - if (c < 0x10) { - buf.append("000"); - } else if (c < 0x100) { - buf.append("00"); - } else if (c < 0x1000) { - buf.append('0'); - } - buf.append(Integer.toString(c, 16)); - } else { - buf.append(c); - } - } - buf.append('\"'); - } - - /** - * Prints the given string tree. - * - * @param pw the writer to be used to print the tree. - * @param l a string tree, i.e., a string list that can contain other string - * lists, and so on recursively. - */ - void printList(final PrintWriter pw, final List l) { - for (int i = 0; i < l.size(); ++i) { - Object o = l.get(i); - if (o instanceof List) { - printList(pw, (List) o); - } else { - pw.print(o.toString()); - } - } - } - - /** - * Returns the default {@link ASMifiable} prototypes. - * - * @return the default {@link ASMifiable} prototypes. - */ - public static Attribute[] getDefaultAttributes() { - return new Attribute[0]; - } -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/util/Traceable.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/util/Traceable.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/util/Traceable.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/util/Traceable.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,52 +0,0 @@ -/** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm.util; - -import java.util.Map; - -/** - * An attribute that can print eadable representation of the attribute. - * - * Implementation should construct readable output from an attribute data - * structures for current attribute state. Such representation could be used in - * unit test assertions. - * - * @author Eugene Kuleshov - */ -public interface Traceable { - - /** - * Build a human readable representation of the attribute. - * - * @param buf A buffer used for printing Java code. - * @param labelNames map of label instances to their names. - */ - void trace(StringBuffer buf, Map labelNames); -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/util/TraceAbstractVisitor.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/util/TraceAbstractVisitor.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/util/TraceAbstractVisitor.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/util/TraceAbstractVisitor.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,179 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm.util; - -import org.mvel2.asm.AnnotationVisitor; -import org.mvel2.asm.Attribute; - -/** - * An abstract trace visitor. - * - * @author Eric Bruneton - */ -public abstract class TraceAbstractVisitor extends AbstractVisitor { - - /** - * Constant used in {@link #appendDescriptor appendDescriptor} for internal - * type names in bytecode notation. - */ - public final static int INTERNAL_NAME = 0; - - /** - * Constant used in {@link #appendDescriptor appendDescriptor} for field - * descriptors, formatted in bytecode notation - */ - public final static int FIELD_DESCRIPTOR = 1; - - /** - * Constant used in {@link #appendDescriptor appendDescriptor} for field - * signatures, formatted in bytecode notation - */ - public final static int FIELD_SIGNATURE = 2; - - /** - * Constant used in {@link #appendDescriptor appendDescriptor} for method - * descriptors, formatted in bytecode notation - */ - public final static int METHOD_DESCRIPTOR = 3; - - /** - * Constant used in {@link #appendDescriptor appendDescriptor} for method - * signatures, formatted in bytecode notation - */ - public final static int METHOD_SIGNATURE = 4; - - /** - * Constant used in {@link #appendDescriptor appendDescriptor} for class - * signatures, formatted in bytecode notation - */ - public final static int CLASS_SIGNATURE = 5; - - /** - * Constant used in {@link #appendDescriptor appendDescriptor} for field or - * method return value signatures, formatted in default Java notation - * (non-bytecode) - */ - public final static int TYPE_DECLARATION = 6; - - /** - * Constant used in {@link #appendDescriptor appendDescriptor} for class - * signatures, formatted in default Java notation (non-bytecode) - */ - public final static int CLASS_DECLARATION = 7; - - /** - * Constant used in {@link #appendDescriptor appendDescriptor} for method - * parameter signatures, formatted in default Java notation (non-bytecode) - */ - public final static int PARAMETERS_DECLARATION = 8; - - /** - * Tab for class members. - */ - protected String tab = " "; - - /** - * Prints a disassembled view of the given annotation. - * - * @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. - */ - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) - { - buf.setLength(0); - buf.append(tab).append('@'); - appendDescriptor(FIELD_DESCRIPTOR, desc); - buf.append('('); - text.add(buf.toString()); - TraceAnnotationVisitor tav = createTraceAnnotationVisitor(); - text.add(tav.getText()); - text.add(visible ? ")\n" : ") // invisible\n"); - return tav; - } - - /** - * Prints a disassembled view of the given attribute. - * - * @param attr an attribute. - */ - public void visitAttribute(final Attribute attr) { - buf.setLength(0); - buf.append(tab).append("ATTRIBUTE "); - appendDescriptor(-1, attr.type); - - if (attr instanceof Traceable) { - ((Traceable) attr).trace(buf, null); - } else { - buf.append(" : unknown\n"); - } - - text.add(buf.toString()); - } - - /** - * Does nothing. - */ - public void visitEnd() { - // does nothing - } - - // ------------------------------------------------------------------------ - // Utility methods - // ------------------------------------------------------------------------ - - protected TraceAnnotationVisitor createTraceAnnotationVisitor() { - return new TraceAnnotationVisitor(); - } - - /** - * Appends an internal name, a type descriptor or a type signature to - * {@link #buf buf}. - * - * @param type indicates if desc is an internal name, a field descriptor, a - * method descriptor, a class signature, ... - * @param desc an internal name, type descriptor, or type signature. May be - * <tt>null</tt>. - */ - protected void appendDescriptor(final int type, final String desc) { - if (type == CLASS_SIGNATURE || type == FIELD_SIGNATURE - || type == METHOD_SIGNATURE) - { - if (desc != null) { - buf.append("// signature ").append(desc).append('\n'); - } - } else { - buf.append(desc); - } - } - -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/util/TraceAnnotationVisitor.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/util/TraceAnnotationVisitor.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/util/TraceAnnotationVisitor.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/util/TraceAnnotationVisitor.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,266 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm.util; - -import org.mvel2.asm.AnnotationVisitor; -import org.mvel2.asm.Type; - -/** - * An {@link AnnotationVisitor} that prints a disassembled view of the - * annotations it visits. - * - * @author Eric Bruneton - */ -public class TraceAnnotationVisitor extends TraceAbstractVisitor implements - AnnotationVisitor -{ - - /** - * The {@link AnnotationVisitor} to which this visitor delegates calls. May - * be <tt>null</tt>. - */ - protected AnnotationVisitor av; - - private int valueNumber = 0; - - /** - * Constructs a new {@link TraceAnnotationVisitor}. - */ - public TraceAnnotationVisitor() { - // ignore - } - - // ------------------------------------------------------------------------ - // Implementation of the AnnotationVisitor interface - // ------------------------------------------------------------------------ - - public void visit(final String name, final Object value) { - buf.setLength(0); - appendComa(valueNumber++); - - if (name != null) { - buf.append(name).append('='); - } - - if (value instanceof String) { - visitString((String) value); - } else if (value instanceof Type) { - visitType((Type) value); - } else if (value instanceof Byte) { - visitByte(((Byte) value).byteValue()); - } else if (value instanceof Boolean) { - visitBoolean(((Boolean) value).booleanValue()); - } else if (value instanceof Short) { - visitShort(((Short) value).shortValue()); - } else if (value instanceof Character) { - visitChar(((Character) value).charValue()); - } else if (value instanceof Integer) { - visitInt(((Integer) value).intValue()); - } else if (value instanceof Float) { - visitFloat(((Float) value).floatValue()); - } else if (value instanceof Long) { - visitLong(((Long) value).longValue()); - } else if (value instanceof Double) { - visitDouble(((Double) value).doubleValue()); - } else if (value.getClass().isArray()) { - buf.append('{'); - if (value instanceof byte[]) { - byte[] v = (byte[]) value; - for (int i = 0; i < v.length; i++) { - appendComa(i); - visitByte(v[i]); - } - } else if (value instanceof boolean[]) { - boolean[] v = (boolean[]) value; - for (int i = 0; i < v.length; i++) { - appendComa(i); - visitBoolean(v[i]); - } - } else if (value instanceof short[]) { - short[] v = (short[]) value; - for (int i = 0; i < v.length; i++) { - appendComa(i); - visitShort(v[i]); - } - } else if (value instanceof char[]) { - char[] v = (char[]) value; - for (int i = 0; i < v.length; i++) { - appendComa(i); - visitChar(v[i]); - } - } else if (value instanceof int[]) { - int[] v = (int[]) value; - for (int i = 0; i < v.length; i++) { - appendComa(i); - visitInt(v[i]); - } - } else if (value instanceof long[]) { - long[] v = (long[]) value; - for (int i = 0; i < v.length; i++) { - appendComa(i); - visitLong(v[i]); - } - } else if (value instanceof float[]) { - float[] v = (float[]) value; - for (int i = 0; i < v.length; i++) { - appendComa(i); - visitFloat(v[i]); - } - } else if (value instanceof double[]) { - double[] v = (double[]) value; - for (int i = 0; i < v.length; i++) { - appendComa(i); - visitDouble(v[i]); - } - } - buf.append('}'); - } - - text.add(buf.toString()); - - if (av != null) { - av.visit(name, value); - } - } - - private void visitInt(final int value) { - buf.append(value); - } - - private void visitLong(final long value) { - buf.append(value).append('L'); - } - - private void visitFloat(final float value) { - buf.append(value).append('F'); - } - - private void visitDouble(final double value) { - buf.append(value).append('D'); - } - - private void visitChar(final char value) { - buf.append("(char)").append((int) value); - } - - private void visitShort(final short value) { - buf.append("(short)").append(value); - } - - private void visitByte(final byte value) { - buf.append("(byte)").append(value); - } - - private void visitBoolean(final boolean value) { - buf.append(value); - } - - private void visitString(final String value) { - appendString(buf, value); - } - - private void visitType(final Type value) { - buf.append(value.getClassName()).append(".class"); - } - - public void visitEnum( - final String name, - final String desc, - final String value) - { - buf.setLength(0); - appendComa(valueNumber++); - if (name != null) { - buf.append(name).append('='); - } - appendDescriptor(FIELD_DESCRIPTOR, desc); - buf.append('.').append(value); - text.add(buf.toString()); - - if (av != null) { - av.visitEnum(name, desc, value); - } - } - - public AnnotationVisitor visitAnnotation( - final String name, - final String desc) - { - buf.setLength(0); - appendComa(valueNumber++); - if (name != null) { - buf.append(name).append('='); - } - buf.append('@'); - appendDescriptor(FIELD_DESCRIPTOR, desc); - buf.append('('); - text.add(buf.toString()); - TraceAnnotationVisitor tav = createTraceAnnotationVisitor(); - text.add(tav.getText()); - text.add(")"); - if (av != null) { - tav.av = av.visitAnnotation(name, desc); - } - return tav; - } - - public AnnotationVisitor visitArray(final String name) { - buf.setLength(0); - appendComa(valueNumber++); - if (name != null) { - buf.append(name).append('='); - } - buf.append('{'); - text.add(buf.toString()); - TraceAnnotationVisitor tav = createTraceAnnotationVisitor(); - text.add(tav.getText()); - text.add("}"); - if (av != null) { - tav.av = av.visitArray(name); - } - return tav; - } - - public void visitEnd() { - if (av != null) { - av.visitEnd(); - } - } - - // ------------------------------------------------------------------------ - // Utility methods - // ------------------------------------------------------------------------ - - private void appendComa(final int i) { - if (i != 0) { - buf.append(", "); - } - } -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/util/TraceClassVisitor.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/util/TraceClassVisitor.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/util/TraceClassVisitor.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/util/TraceClassVisitor.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,523 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm.util; - -import java.io.FileInputStream; -import java.io.PrintWriter; - -import org.mvel2.asm.AnnotationVisitor; -import org.mvel2.asm.Attribute; -import org.mvel2.asm.ClassReader; -import org.mvel2.asm.ClassVisitor; -import org.mvel2.asm.FieldVisitor; -import org.mvel2.asm.MethodVisitor; -import org.mvel2.asm.Opcodes; -import org.mvel2.asm.signature.SignatureReader; - -/** - * A {@link ClassVisitor} that prints a disassembled view of the classes it - * visits. This class visitor can be used alone (see the {@link #main main} - * method) to disassemble a class. It can also be used in the middle of class - * visitor chain to trace the class that is visited at a given point in this - * chain. This may be uselful for debugging purposes. <p> The trace printed when - * visiting the <tt>Hello</tt> class is the following: <p> <blockquote> - * - * <pre> - * // class version 49.0 (49) - * // access flags 33 - * public class Hello { - * - * // compiled from: Hello.java - * - * // access flags 1 - * public <init> ()V - * ALOAD 0 - * INVOKESPECIAL java/lang/Object <init> ()V - * RETURN - * MAXSTACK = 1 - * MAXLOCALS = 1 - * - * // access flags 9 - * public static main ([Ljava/lang/String;)V - * GETSTATIC java/lang/System out Ljava/io/PrintStream; - * LDC "hello" - * INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V - * RETURN - * MAXSTACK = 2 - * MAXLOCALS = 1 - * } - * </pre> - * - * </blockquote> where <tt>Hello</tt> is defined by: <p> <blockquote> - * - * <pre> - * public class Hello { - * - * public static void main(String[] args) { - * System.out.println("hello"); - * } - * } - * </pre> - * - * </blockquote> - * - * @author Eric Bruneton - * @author Eugene Kuleshov - */ -public class TraceClassVisitor extends TraceAbstractVisitor implements - ClassVisitor -{ - - /** - * The {@link ClassVisitor} to which this visitor delegates calls. May be - * <tt>null</tt>. - */ - protected final ClassVisitor cv; - - /** - * The print writer to be used to print the class. - */ - protected final PrintWriter pw; - - /** - * Prints a disassembled view of the given class to the standard output. <p> - * Usage: TraceClassVisitor [-debug] <fully qualified class name or class - * file name > - * - * @param args the command line arguments. - * - * @throws Exception if the class cannot be found, or if an IO exception - * occurs. - */ - public static void main(final String[] args) throws Exception { - int i = 0; - int flags = ClassReader.SKIP_DEBUG; - - boolean ok = true; - if (args.length < 1 || args.length > 2) { - ok = false; - } - if (ok && args[0].equals("-debug")) { - i = 1; - flags = 0; - if (args.length != 2) { - ok = false; - } - } - if (!ok) { - System.err.println("Prints a disassembled view of the given class."); - System.err.println("Usage: TraceClassVisitor [-debug] " - + "<fully qualified class name or class file name>"); - return; - } - ClassReader cr; - if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1 - || args[i].indexOf('/') > -1) - { - cr = new ClassReader(new FileInputStream(args[i])); - } else { - cr = new ClassReader(args[i]); - } - cr.accept(new TraceClassVisitor(new PrintWriter(System.out)), - getDefaultAttributes(), - flags); - } - - /** - * Constructs a new {@link TraceClassVisitor}. - * - * @param pw the print writer to be used to print the class. - */ - public TraceClassVisitor(final PrintWriter pw) { - this(null, pw); - } - - /** - * Constructs a new {@link TraceClassVisitor}. - * - * @param cv the {@link ClassVisitor} to which this visitor delegates calls. - * May be <tt>null</tt>. - * @param pw the print writer to be used to print the class. - */ - public TraceClassVisitor(final ClassVisitor cv, final PrintWriter pw) { - this.cv = cv; - this.pw = pw; - } - - // ------------------------------------------------------------------------ - // Implementation of the ClassVisitor interface - // ------------------------------------------------------------------------ - - public void visit( - final int version, - final int access, - final String name, - final String signature, - final String superName, - final String[] interfaces) - { - int major = version & 0xFFFF; - int minor = version >>> 16; - buf.setLength(0); - buf.append("// class version ") - .append(major) - .append('.') - .append(minor) - .append(" (") - .append(version) - .append(")\n"); - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - buf.append("// DEPRECATED\n"); - } - buf.append("// access flags ").append(access).append('\n'); - - appendDescriptor(CLASS_SIGNATURE, signature); - if (signature != null) { - TraceSignatureVisitor sv = new TraceSignatureVisitor(access); - SignatureReader r = new SignatureReader(signature); - r.accept(sv); - buf.append("// declaration: ") - .append(name) - .append(sv.getDeclaration()) - .append('\n'); - } - - appendAccess(access & ~Opcodes.ACC_SUPER); - if ((access & Opcodes.ACC_ANNOTATION) != 0) { - buf.append("@interface "); - } else if ((access & Opcodes.ACC_INTERFACE) != 0) { - buf.append("interface "); - } else if ((access & Opcodes.ACC_ENUM) == 0) { - buf.append("class "); - } - appendDescriptor(INTERNAL_NAME, name); - - if (superName != null && !superName.equals("java/lang/Object")) { - buf.append(" extends "); - appendDescriptor(INTERNAL_NAME, superName); - buf.append(' '); - } - if (interfaces != null && interfaces.length > 0) { - buf.append(" implements "); - for (int i = 0; i < interfaces.length; ++i) { - appendDescriptor(INTERNAL_NAME, interfaces[i]); - buf.append(' '); - } - } - buf.append(" {\n\n"); - - text.add(buf.toString()); - - if (cv != null) { - cv.visit(version, access, name, signature, superName, interfaces); - } - } - - public void visitSource(final String file, final String debug) { - buf.setLength(0); - if (file != null) { - buf.append(tab) - .append("// compiled from: ") - .append(file) - .append('\n'); - } - if (debug != null) { - buf.append(tab) - .append("// debug info: ") - .append(debug) - .append('\n'); - } - if (buf.length() > 0) { - text.add(buf.toString()); - } - - if (cv != null) { - cv.visitSource(file, debug); - } - } - - public void visitOuterClass( - final String owner, - final String name, - final String desc) - { - buf.setLength(0); - buf.append(tab).append("OUTERCLASS "); - appendDescriptor(INTERNAL_NAME, owner); - buf.append(' '); - if (name != null) { - buf.append(name).append(' '); - } - appendDescriptor(METHOD_DESCRIPTOR, desc); - buf.append('\n'); - text.add(buf.toString()); - - if (cv != null) { - cv.visitOuterClass(owner, name, desc); - } - } - - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) - { - text.add("\n"); - AnnotationVisitor tav = super.visitAnnotation(desc, visible); - if (cv != null) { - ((TraceAnnotationVisitor) tav).av = cv.visitAnnotation(desc, - visible); - } - return tav; - } - - public void visitAttribute(final Attribute attr) { - text.add("\n"); - super.visitAttribute(attr); - - if (cv != null) { - cv.visitAttribute(attr); - } - } - - public void visitInnerClass( - final String name, - final String outerName, - final String innerName, - final int access) - { - buf.setLength(0); - buf.append(tab).append("// access flags "); - buf.append(access & ~Opcodes.ACC_SUPER).append('\n'); - buf.append(tab); - appendAccess(access); - buf.append("INNERCLASS "); - appendDescriptor(INTERNAL_NAME, name); - buf.append(' '); - appendDescriptor(INTERNAL_NAME, outerName); - buf.append(' '); - appendDescriptor(INTERNAL_NAME, innerName); - buf.append('\n'); - text.add(buf.toString()); - - if (cv != null) { - cv.visitInnerClass(name, outerName, innerName, access); - } - } - - public FieldVisitor visitField( - final int access, - final String name, - final String desc, - final String signature, - final Object value) - { - buf.setLength(0); - buf.append('\n'); - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - buf.append(tab).append("// DEPRECATED\n"); - } - buf.append(tab).append("// access flags ").append(access).append('\n'); - if (signature != null) { - buf.append(tab); - appendDescriptor(FIELD_SIGNATURE, signature); - - TraceSignatureVisitor sv = new TraceSignatureVisitor(0); - SignatureReader r = new SignatureReader(signature); - r.acceptType(sv); - buf.append(tab) - .append("// declaration: ") - .append(sv.getDeclaration()) - .append('\n'); - } - - buf.append(tab); - appendAccess(access); - - appendDescriptor(FIELD_DESCRIPTOR, desc); - buf.append(' ').append(name); - if (value != null) { - buf.append(" = "); - if (value instanceof String) { - buf.append("\"").append(value).append("\""); - } else { - buf.append(value); - } - } - - buf.append('\n'); - text.add(buf.toString()); - - TraceFieldVisitor tav = createTraceFieldVisitor(); - text.add(tav.getText()); - - if (cv != null) { - tav.fv = cv.visitField(access, name, desc, signature, value); - } - - return tav; - } - - public MethodVisitor visitMethod( - final int access, - final String name, - final String desc, - final String signature, - final String[] exceptions) - { - buf.setLength(0); - buf.append('\n'); - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - buf.append(tab).append("// DEPRECATED\n"); - } - buf.append(tab).append("// access flags ").append(access).append('\n'); - - if (signature != null) { - buf.append(tab); - appendDescriptor(METHOD_SIGNATURE, signature); - - TraceSignatureVisitor v = new TraceSignatureVisitor(0); - SignatureReader r = new SignatureReader(signature); - r.accept(v); - String genericDecl = v.getDeclaration(); - String genericReturn = v.getReturnType(); - String genericExceptions = v.getExceptions(); - - buf.append(tab) - .append("// declaration: ") - .append(genericReturn) - .append(' ') - .append(name) - .append(genericDecl); - if (genericExceptions != null) { - buf.append(" throws ").append(genericExceptions); - } - buf.append('\n'); - } - - buf.append(tab); - appendAccess(access); - if ((access & Opcodes.ACC_NATIVE) != 0) { - buf.append("native "); - } - if ((access & Opcodes.ACC_VARARGS) != 0) { - buf.append("varargs "); - } - if ((access & Opcodes.ACC_BRIDGE) != 0) { - buf.append("bridge "); - } - - buf.append(name); - appendDescriptor(METHOD_DESCRIPTOR, desc); - if (exceptions != null && exceptions.length > 0) { - buf.append(" throws "); - for (int i = 0; i < exceptions.length; ++i) { - appendDescriptor(INTERNAL_NAME, exceptions[i]); - buf.append(' '); - } - } - - buf.append('\n'); - text.add(buf.toString()); - - TraceMethodVisitor tcv = createTraceMethodVisitor(); - text.add(tcv.getText()); - - if (cv != null) { - tcv.mv = cv.visitMethod(access, name, desc, signature, exceptions); - } - - return tcv; - } - - public void visitEnd() { - text.add("}\n"); - - print(pw); - pw.flush(); - - if (cv != null) { - cv.visitEnd(); - } - } - - // ------------------------------------------------------------------------ - // Utility methods - // ------------------------------------------------------------------------ - - protected TraceFieldVisitor createTraceFieldVisitor() { - return new TraceFieldVisitor(); - } - - protected TraceMethodVisitor createTraceMethodVisitor() { - return new TraceMethodVisitor(); - } - - /** - * Appends a string representation of the given access modifiers to {@link - * #buf buf}. - * - * @param access some access modifiers. - */ - private void appendAccess(final int access) { - if ((access & Opcodes.ACC_PUBLIC) != 0) { - buf.append("public "); - } - if ((access & Opcodes.ACC_PRIVATE) != 0) { - buf.append("private "); - } - if ((access & Opcodes.ACC_PROTECTED) != 0) { - buf.append("protected "); - } - if ((access & Opcodes.ACC_FINAL) != 0) { - buf.append("final "); - } - if ((access & Opcodes.ACC_STATIC) != 0) { - buf.append("static "); - } - if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) { - buf.append("synchronized "); - } - if ((access & Opcodes.ACC_VOLATILE) != 0) { - buf.append("volatile "); - } - if ((access & Opcodes.ACC_TRANSIENT) != 0) { - buf.append("transient "); - } - if ((access & Opcodes.ACC_ABSTRACT) != 0) { - buf.append("abstract "); - } - if ((access & Opcodes.ACC_STRICT) != 0) { - buf.append("strictfp "); - } - if ((access & Opcodes.ACC_ENUM) != 0) { - buf.append("enum "); - } - } -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/util/TraceFieldVisitor.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/util/TraceFieldVisitor.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/util/TraceFieldVisitor.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/util/TraceFieldVisitor.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,78 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm.util; - -import org.mvel2.asm.AnnotationVisitor; -import org.mvel2.asm.Attribute; -import org.mvel2.asm.FieldVisitor; - -/** - * A {@link FieldVisitor} that prints a disassembled view of the fields it - * visits. - * - * @author Eric Bruneton - */ -public class TraceFieldVisitor extends TraceAbstractVisitor implements - FieldVisitor -{ - - /** - * The {@link FieldVisitor} to which this visitor delegates calls. May be - * <tt>null</tt>. - */ - protected FieldVisitor fv; - - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) - { - AnnotationVisitor av = super.visitAnnotation(desc, visible); - if (fv != null) { - ((TraceAnnotationVisitor) av).av = fv.visitAnnotation(desc, visible); - } - return av; - } - - public void visitAttribute(final Attribute attr) { - super.visitAttribute(attr); - - if (fv != null) { - fv.visitAttribute(attr); - } - } - - public void visitEnd() { - super.visitEnd(); - - if (fv != null) { - fv.visitEnd(); - } - } -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/util/TraceMethodVisitor.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/util/TraceMethodVisitor.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/util/TraceMethodVisitor.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/util/TraceMethodVisitor.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,570 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm.util; - -import org.mvel2.asm.AnnotationVisitor; -import org.mvel2.asm.Attribute; -import org.mvel2.asm.MethodVisitor; -import org.mvel2.asm.Label; -import org.mvel2.asm.Opcodes; -import org.mvel2.asm.Type; -import org.mvel2.asm.signature.SignatureReader; - -import java.util.HashMap; - -/** - * A {@link MethodVisitor} that prints a disassembled view of the methods it - * visits. - * - * @author Eric Bruneton - */ -public class TraceMethodVisitor extends TraceAbstractVisitor implements - MethodVisitor -{ - - /** - * The {@link MethodVisitor} to which this visitor delegates calls. May be - * <tt>null</tt>. - */ - protected MethodVisitor mv; - - /** - * Tab for bytecode instructions. - */ - protected String tab2 = " "; - - /** - * Tab for table and lookup switch instructions. - */ - protected String tab3 = " "; - - /** - * Tab for labels. - */ - protected String ltab = " "; - - /** - * The label names. This map associate String values to Label keys. - */ - protected final HashMap labelNames; - - /** - * Constructs a new {@link TraceMethodVisitor}. - */ - public TraceMethodVisitor() { - this(null); - } - - /** - * Constructs a new {@link TraceMethodVisitor}. - * - * @param mv the {@link MethodVisitor} to which this visitor delegates - * calls. May be <tt>null</tt>. - */ - public TraceMethodVisitor(final MethodVisitor mv) { - this.labelNames = new HashMap(); - this.mv = mv; - } - - // ------------------------------------------------------------------------ - // Implementation of the MethodVisitor interface - // ------------------------------------------------------------------------ - - public AnnotationVisitor visitAnnotation( - final String desc, - final boolean visible) - { - AnnotationVisitor av = super.visitAnnotation(desc, visible); - if (mv != null) { - ((TraceAnnotationVisitor) av).av = mv.visitAnnotation(desc, visible); - } - return av; - } - - public void visitAttribute(final Attribute attr) { - buf.setLength(0); - buf.append(tab).append("ATTRIBUTE "); - appendDescriptor(-1, attr.type); - - if (attr instanceof Traceable) { - ((Traceable) attr).trace(buf, labelNames); - } else { - buf.append(" : unknown\n"); - } - - text.add(buf.toString()); - if (mv != null) { - mv.visitAttribute(attr); - } - } - - public AnnotationVisitor visitAnnotationDefault() { - text.add(tab2 + "default="); - TraceAnnotationVisitor tav = createTraceAnnotationVisitor(); - text.add(tav.getText()); - text.add("\n"); - if (mv != null) { - tav.av = mv.visitAnnotationDefault(); - } - return tav; - } - - public AnnotationVisitor visitParameterAnnotation( - final int parameter, - final String desc, - final boolean visible) - { - buf.setLength(0); - buf.append(tab2).append('@'); - appendDescriptor(FIELD_DESCRIPTOR, desc); - buf.append('('); - text.add(buf.toString()); - TraceAnnotationVisitor tav = createTraceAnnotationVisitor(); - text.add(tav.getText()); - text.add(visible ? ") // parameter " : ") // invisible, parameter "); - text.add(new Integer(parameter)); - text.add("\n"); - if (mv != null) { - tav.av = mv.visitParameterAnnotation(parameter, desc, visible); - } - return tav; - } - - public void visitCode() { - if (mv != null) { - mv.visitCode(); - } - } - - public void visitFrame( - final int type, - final int nLocal, - final Object[] local, - final int nStack, - final Object[] stack) - { - buf.setLength(0); - buf.append(ltab); - buf.append("FRAME "); - switch (type) { - case Opcodes.F_NEW: - case Opcodes.F_FULL: - buf.append("FULL ["); - appendFrameTypes(nLocal, local); - buf.append("] ["); - appendFrameTypes(nStack, stack); - buf.append("]"); - break; - case Opcodes.F_APPEND: - buf.append("APPEND ["); - appendFrameTypes(nLocal, local); - buf.append("]"); - break; - case Opcodes.F_CHOP: - buf.append("CHOP ").append(nLocal); - break; - case Opcodes.F_SAME: - buf.append("SAME"); - break; - case Opcodes.F_SAME1: - buf.append("SAME1 "); - appendFrameTypes(1, stack); - break; - } - buf.append("\n"); - text.add(buf.toString()); - - if (mv != null) { - mv.visitFrame(type, nLocal, local, nStack, stack); - } - } - - public void visitInsn(final int opcode) { - buf.setLength(0); - buf.append(tab2).append(OPCODES[opcode]).append('\n'); - text.add(buf.toString()); - - if (mv != null) { - mv.visitInsn(opcode); - } - } - - public void visitIntInsn(final int opcode, final int operand) { - buf.setLength(0); - buf.append(tab2) - .append(OPCODES[opcode]) - .append(' ') - .append(opcode == Opcodes.NEWARRAY - ? TYPES[operand] - : Integer.toString(operand)) - .append('\n'); - text.add(buf.toString()); - - if (mv != null) { - mv.visitIntInsn(opcode, operand); - } - } - - public void visitVarInsn(final int opcode, final int var) { - buf.setLength(0); - buf.append(tab2) - .append(OPCODES[opcode]) - .append(' ') - .append(var) - .append('\n'); - text.add(buf.toString()); - - if (mv != null) { - mv.visitVarInsn(opcode, var); - } - } - - public void visitTypeInsn(final int opcode, final String desc) { - buf.setLength(0); - buf.append(tab2).append(OPCODES[opcode]).append(' '); - if (desc.startsWith("[")) { - appendDescriptor(FIELD_DESCRIPTOR, desc); - } else { - appendDescriptor(INTERNAL_NAME, desc); - } - buf.append('\n'); - text.add(buf.toString()); - - if (mv != null) { - mv.visitTypeInsn(opcode, desc); - } - } - - public void visitFieldInsn( - final int opcode, - final String owner, - final String name, - final String desc) - { - buf.setLength(0); - buf.append(tab2).append(OPCODES[opcode]).append(' '); - appendDescriptor(INTERNAL_NAME, owner); - buf.append('.').append(name).append(" : "); - appendDescriptor(FIELD_DESCRIPTOR, desc); - buf.append('\n'); - text.add(buf.toString()); - - if (mv != null) { - mv.visitFieldInsn(opcode, owner, name, desc); - } - } - - public void visitMethodInsn( - final int opcode, - final String owner, - final String name, - final String desc) - { - buf.setLength(0); - buf.append(tab2).append(OPCODES[opcode]).append(' '); - appendDescriptor(INTERNAL_NAME, owner); - buf.append('.').append(name).append(' '); - appendDescriptor(METHOD_DESCRIPTOR, desc); - buf.append('\n'); - text.add(buf.toString()); - - if (mv != null) { - mv.visitMethodInsn(opcode, owner, name, desc); - } - } - - public void visitJumpInsn(final int opcode, final Label label) { - buf.setLength(0); - buf.append(tab2).append(OPCODES[opcode]).append(' '); - appendLabel(label); - buf.append('\n'); - text.add(buf.toString()); - - if (mv != null) { - mv.visitJumpInsn(opcode, label); - } - } - - public void visitLabel(final Label label) { - buf.setLength(0); - buf.append(ltab); - appendLabel(label); - buf.append('\n'); - text.add(buf.toString()); - - if (mv != null) { - mv.visitLabel(label); - } - } - - public void visitLdcInsn(final Object cst) { - buf.setLength(0); - buf.append(tab2).append("LDC "); - if (cst instanceof String) { - AbstractVisitor.appendString(buf, (String) cst); - } else if (cst instanceof Type) { - buf.append(((Type) cst).getDescriptor() + ".class"); - } else { - buf.append(cst); - } - buf.append('\n'); - text.add(buf.toString()); - - if (mv != null) { - mv.visitLdcInsn(cst); - } - } - - public void visitIincInsn(final int var, final int increment) { - buf.setLength(0); - buf.append(tab2) - .append("IINC ") - .append(var) - .append(' ') - .append(increment) - .append('\n'); - text.add(buf.toString()); - - if (mv != null) { - mv.visitIincInsn(var, increment); - } - } - - public void visitTableSwitchInsn( - final int min, - final int max, - final Label dflt, - final Label labels[]) - { - buf.setLength(0); - buf.append(tab2).append("TABLESWITCH\n"); - for (int i = 0; i < labels.length; ++i) { - buf.append(tab3).append(min + i).append(": "); - appendLabel(labels[i]); - buf.append('\n'); - } - buf.append(tab3).append("default: "); - appendLabel(dflt); - buf.append('\n'); - text.add(buf.toString()); - - if (mv != null) { - mv.visitTableSwitchInsn(min, max, dflt, labels); - } - } - - public void visitLookupSwitchInsn( - final Label dflt, - final int keys[], - final Label labels[]) - { - buf.setLength(0); - buf.append(tab2).append("LOOKUPSWITCH\n"); - for (int i = 0; i < labels.length; ++i) { - buf.append(tab3).append(keys[i]).append(": "); - appendLabel(labels[i]); - buf.append('\n'); - } - buf.append(tab3).append("default: "); - appendLabel(dflt); - buf.append('\n'); - text.add(buf.toString()); - - if (mv != null) { - mv.visitLookupSwitchInsn(dflt, keys, labels); - } - } - - public void visitMultiANewArrayInsn(final String desc, final int dims) { - buf.setLength(0); - buf.append(tab2).append("MULTIANEWARRAY "); - appendDescriptor(FIELD_DESCRIPTOR, desc); - buf.append(' ').append(dims).append('\n'); - text.add(buf.toString()); - - if (mv != null) { - mv.visitMultiANewArrayInsn(desc, dims); - } - } - - public void visitTryCatchBlock( - final Label start, - final Label end, - final Label handler, - final String type) - { - buf.setLength(0); - buf.append(tab2).append("TRYCATCHBLOCK "); - appendLabel(start); - buf.append(' '); - appendLabel(end); - buf.append(' '); - appendLabel(handler); - buf.append(' '); - appendDescriptor(INTERNAL_NAME, type); - buf.append('\n'); - text.add(buf.toString()); - - if (mv != null) { - mv.visitTryCatchBlock(start, end, handler, type); - } - } - - public void visitLocalVariable( - final String name, - final String desc, - final String signature, - final Label start, - final Label end, - final int index) - { - buf.setLength(0); - buf.append(tab2).append("LOCALVARIABLE ").append(name).append(' '); - appendDescriptor(FIELD_DESCRIPTOR, desc); - buf.append(' '); - appendLabel(start); - buf.append(' '); - appendLabel(end); - buf.append(' ').append(index).append('\n'); - - if (signature != null) { - buf.append(tab2); - appendDescriptor(FIELD_SIGNATURE, signature); - - TraceSignatureVisitor sv = new TraceSignatureVisitor(0); - SignatureReader r = new SignatureReader(signature); - r.acceptType(sv); - buf.append(tab2) - .append("// declaration: ") - .append(sv.getDeclaration()) - .append('\n'); - } - text.add(buf.toString()); - - if (mv != null) { - mv.visitLocalVariable(name, desc, signature, start, end, index); - } - } - - public void visitLineNumber(final int line, final Label start) { - buf.setLength(0); - buf.append(tab2).append("LINENUMBER ").append(line).append(' '); - appendLabel(start); - buf.append('\n'); - text.add(buf.toString()); - - if (mv != null) { - mv.visitLineNumber(line, start); - } - } - - public void visitMaxs(final int maxStack, final int maxLocals) { - buf.setLength(0); - buf.append(tab2).append("MAXSTACK = ").append(maxStack).append('\n'); - text.add(buf.toString()); - - buf.setLength(0); - buf.append(tab2).append("MAXLOCALS = ").append(maxLocals).append('\n'); - text.add(buf.toString()); - - if (mv != null) { - mv.visitMaxs(maxStack, maxLocals); - } - } - - public void visitEnd() { - super.visitEnd(); - - if (mv != null) { - mv.visitEnd(); - } - } - - // ------------------------------------------------------------------------ - // Utility methods - // ------------------------------------------------------------------------ - - private void appendFrameTypes(final int n, final Object[] o) { - for (int i = 0; i < n; ++i) { - if (i > 0) { - buf.append(' '); - } - if (o[i] instanceof String) { - String desc = (String) o[i]; - if (desc.startsWith("[")) { - appendDescriptor(FIELD_DESCRIPTOR, desc); - } else { - appendDescriptor(INTERNAL_NAME, desc); - } - } else if (o[i] instanceof Integer) { - switch (((Integer) o[i]).intValue()) { - case 0: - appendDescriptor(FIELD_DESCRIPTOR, "T"); - break; - case 1: - appendDescriptor(FIELD_DESCRIPTOR, "I"); - break; - case 2: - appendDescriptor(FIELD_DESCRIPTOR, "F"); - break; - case 3: - appendDescriptor(FIELD_DESCRIPTOR, "D"); - break; - case 4: - appendDescriptor(FIELD_DESCRIPTOR, "J"); - break; - case 5: - appendDescriptor(FIELD_DESCRIPTOR, "N"); - break; - case 6: - appendDescriptor(FIELD_DESCRIPTOR, "U"); - break; - } - } else { - appendLabel((Label) o[i]); - } - } - } - - /** - * Appends the name of the given label to {@link #buf buf}. Creates a new - * label name if the given label does not yet have one. - * - * @param l a label. - */ - protected void appendLabel(final Label l) { - String name = (String) labelNames.get(l); - if (name == null) { - name = "L" + labelNames.size(); - labelNames.put(l, name); - } - buf.append(name); - } -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/asm/util/TraceSignatureVisitor.java mvel-2.0.19-gil/src/main/java/org/mvel2/asm/util/TraceSignatureVisitor.java --- mvel-2.0.19/src/main/java/org/mvel2/asm/util/TraceSignatureVisitor.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/asm/util/TraceSignatureVisitor.java 1970-01-01 01:00:00.000000000 +0100 @@ -1,300 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2005 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.mvel2.asm.util; - -import org.mvel2.asm.Opcodes; -import org.mvel2.asm.signature.SignatureVisitor; - -/** - * A {@link SignatureVisitor} that prints a disassembled view of the signature - * it visits. - * - * @author Eugene Kuleshov - * @author Eric Bruneton - */ -public class TraceSignatureVisitor implements SignatureVisitor { - - private StringBuffer declaration; - - private boolean isInterface; - - private boolean seenFormalParameter; - - private boolean seenInterfaceBound; - - private boolean seenParameter; - - private boolean seenInterface; - - private StringBuffer returnType; - - private StringBuffer exceptions; - - /** - * Stack used to keep track of class types that have arguments. Each element - * of this stack is a boolean encoded in one bit. The top of the stack is - * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping = - * /2. - */ - private int argumentStack; - - /** - * Stack used to keep track of array class types. Each element of this stack - * is a boolean encoded in one bit. The top of the stack is the lowest order - * bit. Pushing false = *2, pushing true = *2+1, popping = /2. - */ - private int arrayStack; - - private String separator = ""; - - public TraceSignatureVisitor(final int access) { - isInterface = (access & Opcodes.ACC_INTERFACE) != 0; - this.declaration = new StringBuffer(); - } - - private TraceSignatureVisitor(final StringBuffer buf) { - this.declaration = buf; - } - - public void visitFormalTypeParameter(final String name) { - declaration.append(seenFormalParameter ? ", " : "<").append(name); - seenFormalParameter = true; - seenInterfaceBound = false; - } - - public SignatureVisitor visitClassBound() { - separator = " extends "; - startType(); - return this; - } - - public SignatureVisitor visitInterfaceBound() { - separator = seenInterfaceBound ? ", " : " extends "; - seenInterfaceBound = true; - startType(); - return this; - } - - public SignatureVisitor visitSuperclass() { - endFormals(); - separator = " extends "; - startType(); - return this; - } - - public SignatureVisitor visitInterface() { - separator = seenInterface ? ", " : isInterface - ? " extends " - : " implements "; - seenInterface = true; - startType(); - return this; - } - - public SignatureVisitor visitParameterType() { - endFormals(); - if (!seenParameter) { - seenParameter = true; - declaration.append('('); - } else { - declaration.append(", "); - } - startType(); - return this; - } - - public SignatureVisitor visitReturnType() { - endFormals(); - if (!seenParameter) { - declaration.append('('); - } else { - seenParameter = false; - } - declaration.append(')'); - returnType = new StringBuffer(); - return new TraceSignatureVisitor(returnType); - } - - public SignatureVisitor visitExceptionType() { - if (exceptions == null) { - exceptions = new StringBuffer(); - } else { - exceptions.append(", "); - } - // startType(); - return new TraceSignatureVisitor(exceptions); - } - - public void visitBaseType(final char descriptor) { - switch (descriptor) { - case 'V': - declaration.append("void"); - break; - case 'B': - declaration.append("byte"); - break; - case 'J': - declaration.append("long"); - break; - case 'Z': - declaration.append("boolean"); - break; - case 'I': - declaration.append("int"); - break; - case 'S': - declaration.append("short"); - break; - case 'C': - declaration.append("char"); - break; - case 'F': - declaration.append("float"); - break; - // case 'D': - default: - declaration.append("double"); - break; - } - endType(); - } - - public void visitTypeVariable(final String name) { - declaration.append(name); - endType(); - } - - public SignatureVisitor visitArrayType() { - startType(); - arrayStack |= 1; - return this; - } - - public void visitClassType(final String name) { - if (!"java/lang/Object".equals(name)) { - declaration.append(separator).append(name.replace('/', '.')); - } else { - // Map<java.lang.Object,java.util.List> - // or - // abstract public V get(Object key); (seen in Dictionary.class) - // should have Object - // but java.lang.String extends java.lang.Object is unnecessary - boolean needObjectClass = argumentStack % 2 != 0 || seenParameter; - if (needObjectClass) { - declaration.append(separator).append(name.replace('/', '.')); - } - } - separator = ""; - argumentStack *= 2; - } - - public void visitInnerClassType(final String name) { - if (argumentStack % 2 != 0) { - declaration.append('>'); - } - argumentStack /= 2; - declaration.append('.'); - declaration.append(separator).append(name.replace('/', '.')); - separator = ""; - argumentStack *= 2; - } - - public void visitTypeArgument() { - if (argumentStack % 2 == 0) { - ++argumentStack; - declaration.append('<'); - } else { - declaration.append(", "); - } - declaration.append('?'); - } - - public SignatureVisitor visitTypeArgument(final char tag) { - if (argumentStack % 2 == 0) { - ++argumentStack; - declaration.append('<'); - } else { - declaration.append(", "); - } - - if (tag == SignatureVisitor.EXTENDS) { - declaration.append("? extends "); - } else if (tag == SignatureVisitor.SUPER) { - declaration.append("? super "); - } - - startType(); - return this; - } - - public void visitEnd() { - if (argumentStack % 2 != 0) { - declaration.append('>'); - } - argumentStack /= 2; - endType(); - } - - public String getDeclaration() { - return declaration.toString(); - } - - public String getReturnType() { - return returnType == null ? null : returnType.toString(); - } - - public String getExceptions() { - return exceptions == null ? null : exceptions.toString(); - } - - // ----------------------------------------------- - - private void endFormals() { - if (seenFormalParameter) { - declaration.append('>'); - seenFormalParameter = false; - } - } - - private void startType() { - arrayStack *= 2; - } - - private void endType() { - if (arrayStack % 2 != 0) { - while (arrayStack % 2 != 0) { - arrayStack /= 2; - declaration.append("[]"); - } - } else { - arrayStack /= 2; - } - } -} diff -Nru mvel-2.0.19/src/main/java/org/mvel2/optimizers/impl/asm/ASMAccessorOptimizer.java mvel-2.0.19-gil/src/main/java/org/mvel2/optimizers/impl/asm/ASMAccessorOptimizer.java --- mvel-2.0.19/src/main/java/org/mvel2/optimizers/impl/asm/ASMAccessorOptimizer.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/optimizers/impl/asm/ASMAccessorOptimizer.java 2012-05-26 19:29:36.893461371 +0200 @@ -18,10 +18,10 @@ package org.mvel2.optimizers.impl.asm; import org.mvel2.*; -import org.mvel2.asm.ClassWriter; -import org.mvel2.asm.Label; -import org.mvel2.asm.MethodVisitor; -import org.mvel2.asm.Opcodes; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; import org.mvel2.ast.Function; import org.mvel2.ast.TypeDescriptor; import org.mvel2.ast.WithNode; @@ -53,8 +53,8 @@ import static org.mvel2.DataConversion.convert; import static org.mvel2.MVEL.eval; import static org.mvel2.MVEL.isAdvancedDebugging; -import static org.mvel2.asm.Opcodes.*; -import static org.mvel2.asm.Type.*; +import static org.objectweb.asm.Opcodes.*; +import static org.objectweb.asm.Type.*; import static org.mvel2.ast.TypeDescriptor.getClassReference; import static org.mvel2.integration.GlobalListenerFactory.hasGetListeners; import static org.mvel2.integration.GlobalListenerFactory.notifyGetListeners; @@ -648,7 +648,7 @@ mv = cw.visitMethod(ACC_PUBLIC, "getKnownEgressType", "()Ljava/lang/Class;", null, null); mv.visitCode(); - mv.visitLdcInsn(org.mvel2.asm.Type.getType(returnType != null ? returnType : Object.class)); + mv.visitLdcInsn(org.objectweb.asm.Type.getType(returnType != null ? returnType : Object.class)); mv.visitInsn(ARETURN); mv.visitMaxs(1, 1); diff -Nru mvel-2.0.19/src/main/java/org/mvel2/optimizers/impl/asm/ProducesBytecode.java mvel-2.0.19-gil/src/main/java/org/mvel2/optimizers/impl/asm/ProducesBytecode.java --- mvel-2.0.19/src/main/java/org/mvel2/optimizers/impl/asm/ProducesBytecode.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/optimizers/impl/asm/ProducesBytecode.java 2012-05-26 19:29:36.894461371 +0200 @@ -18,7 +18,7 @@ package org.mvel2.optimizers.impl.asm; -import org.mvel2.asm.MethodVisitor; +import org.objectweb.asm.MethodVisitor; import org.mvel2.integration.VariableResolverFactory; /** diff -Nru mvel-2.0.19/src/main/java/org/mvel2/optimizers/OptimizerFactory.java mvel-2.0.19-gil/src/main/java/org/mvel2/optimizers/OptimizerFactory.java --- mvel-2.0.19/src/main/java/org/mvel2/optimizers/OptimizerFactory.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/main/java/org/mvel2/optimizers/OptimizerFactory.java 2012-05-26 19:29:36.908461371 +0200 @@ -45,7 +45,7 @@ * By default, activate the JIT if ASM is present in the classpath */ try { - currentThread().getContextClassLoader().loadClass("org.mvel2.asm.ClassWriter"); + currentThread().getContextClassLoader().loadClass("org.objectweb.asm.ClassWriter"); accessorCompilers.put("ASM", new ASMAccessorOptimizer()); } diff -Nru mvel-2.0.19/src/test/java/org/mvel2/tests/core/PropertyHandlerTests.java mvel-2.0.19-gil/src/test/java/org/mvel2/tests/core/PropertyHandlerTests.java --- mvel-2.0.19/src/test/java/org/mvel2/tests/core/PropertyHandlerTests.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/test/java/org/mvel2/tests/core/PropertyHandlerTests.java 2012-05-26 19:29:36.954461371 +0200 @@ -3,8 +3,8 @@ import junit.framework.TestCase; import org.mvel2.MVEL; import org.mvel2.PropertyAccessor; -import org.mvel2.asm.MethodVisitor; -import static org.mvel2.asm.Opcodes.*; +import org.objectweb.asm.MethodVisitor; +import static org.objectweb.asm.Opcodes.*; import org.mvel2.integration.*; import org.mvel2.optimizers.OptimizerFactory; import org.mvel2.optimizers.impl.asm.ProducesBytecode; diff -Nru mvel-2.0.19/src/test/java/org/mvel2/tests/core/res/SampleBeanAccessor.java mvel-2.0.19-gil/src/test/java/org/mvel2/tests/core/res/SampleBeanAccessor.java --- mvel-2.0.19/src/test/java/org/mvel2/tests/core/res/SampleBeanAccessor.java 2010-11-19 20:22:46.000000000 +0100 +++ mvel-2.0.19-gil/src/test/java/org/mvel2/tests/core/res/SampleBeanAccessor.java 2012-05-26 19:29:36.951461371 +0200 @@ -1,8 +1,8 @@ package org.mvel2.tests.core.res; -import org.mvel2.asm.MethodVisitor; -import static org.mvel2.asm.Opcodes.CHECKCAST; -import static org.mvel2.asm.Opcodes.INVOKEVIRTUAL; +import org.objectweb.asm.MethodVisitor; +import static org.objectweb.asm.Opcodes.CHECKCAST; +import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL; import org.mvel2.integration.PropertyHandler; import org.mvel2.integration.VariableResolverFactory; import org.mvel2.optimizers.impl.asm.ProducesBytecode;