You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by th...@apache.org on 2018/11/29 00:34:18 UTC
[31/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
old mode 100644
new mode 100755
index 5ff7100..b541ecd
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
@@ -1,39 +1,37 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-
+import org.apache.tapestry5.internal.plastic.asm.ConstantDynamic;
import org.apache.tapestry5.internal.plastic.asm.Handle;
import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
@@ -41,909 +39,899 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.Type;
/**
- * A {@link MethodVisitor} that keeps track of stack map frame changes between
- * {@link #visitFrame(int, int, Object[], int, Object[]) visitFrame} calls. This
- * adapter must be used with the
- * {@link org.objectweb.asm.ClassReader#EXPAND_FRAMES} option. Each
- * visit<i>X</i> instruction delegates to the next visitor in the chain, if any,
- * and then simulates the effect of this instruction on the stack map frame,
- * represented by {@link #locals} and {@link #stack}. The next visitor in the
- * chain can get the state of the stack map frame <i>before</i> each instruction
- * by reading the value of these fields in its visit<i>X</i> methods (this
- * requires a reference to the AnalyzerAdapter that is before it in the chain).
- * If this adapter is used with a class that does not contain stack map table
- * attributes (i.e., pre Java 6 classes) then this adapter may not be able to
- * compute the stack map frame for each instruction. In this case no exception
- * is thrown but the {@link #locals} and {@link #stack} fields will be null for
- * these instructions.
- *
+ * A {@link MethodVisitor} that keeps track of stack map frame changes between {@link
+ * #visitFrame(int, int, Object[], int, Object[])} calls. This adapter must be used with the {@link
+ * org.apache.tapestry5.internal.plastic.asm.ClassReader#EXPAND_FRAMES} option. Each visit<i>X</i> instruction delegates to
+ * the next visitor in the chain, if any, and then simulates the effect of this instruction on the
+ * stack map frame, represented by {@link #locals} and {@link #stack}. The next visitor in the chain
+ * can get the state of the stack map frame <i>before</i> each instruction by reading the value of
+ * these fields in its visit<i>X</i> methods (this requires a reference to the AnalyzerAdapter that
+ * is before it in the chain). If this adapter is used with a class that does not contain stack map
+ * table attributes (i.e., pre Java 6 classes) then this adapter may not be able to compute the
+ * stack map frame for each instruction. In this case no exception is thrown but the {@link #locals}
+ * and {@link #stack} fields will be null for these instructions.
+ *
* @author Eric Bruneton
*/
public class AnalyzerAdapter extends MethodVisitor {
- /**
- * <code>List</code> of the local variable slots for current execution
- * frame. Primitive types are represented by {@link Opcodes#TOP},
- * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
- * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
- * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by
- * two elements, the second one being TOP). Reference types are represented
- * by String objects (representing internal names), and uninitialized types
- * by Label objects (this label designates the NEW instruction that created
- * this uninitialized value). This field is <tt>null</tt> for unreachable
- * instructions.
- */
- public List<Object> locals;
-
- /**
- * <code>List</code> of the operand stack slots for current execution frame.
- * Primitive types are represented by {@link Opcodes#TOP},
- * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
- * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
- * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by
- * two elements, the second one being TOP). Reference types are represented
- * by String objects (representing internal names), and uninitialized types
- * by Label objects (this label designates the NEW instruction that created
- * this uninitialized value). This field is <tt>null</tt> for unreachable
- * instructions.
- */
- public List<Object> stack;
-
- /**
- * The labels that designate the next instruction to be visited. May be
- * <tt>null</tt>.
- */
- private List<Label> labels;
-
- /**
- * Information about uninitialized types in the current execution frame.
- * This map associates internal names to Label objects. Each label
- * designates a NEW instruction that created the currently uninitialized
- * types, and the associated internal name represents the NEW operand, i.e.
- * the final, initialized type value.
- */
- public Map<Object, Object> uninitializedTypes;
-
- /**
- * The maximum stack size of this method.
- */
- private int maxStack;
-
- /**
- * The maximum number of local variables of this method.
- */
- private int maxLocals;
-
- /**
- * The owner's class name.
- */
- private String owner;
-
- /**
- * Creates a new {@link AnalyzerAdapter}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #AnalyzerAdapter(int, String, int, String, String, MethodVisitor)}
- * version.
- *
- * @param owner
- * the owner's class name.
- * @param access
- * the method's access flags (see {@link Opcodes}).
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- * @param mv
- * the method visitor to which this adapter delegates calls. May
- * be <tt>null</tt>.
- * @throws IllegalStateException
- * If a subclass calls this constructor.
- */
- public AnalyzerAdapter(final String owner, final int access,
- final String name, final String desc, final MethodVisitor mv) {
- this(Opcodes.ASM6, owner, access, name, desc, mv);
- if (getClass() != AnalyzerAdapter.class) {
- throw new IllegalStateException();
- }
+ /**
+ * The local variable slots for the current execution frame. Primitive types are represented by
+ * {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+ * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or {@link Opcodes#UNINITIALIZED_THIS} (long and
+ * double are represented by two elements, the second one being TOP). Reference types are
+ * represented by String objects (representing internal names), and uninitialized types by Label
+ * objects (this label designates the NEW instruction that created this uninitialized value). This
+ * field is {@literal null} for unreachable instructions.
+ */
+ public List<Object> locals;
+
+ /**
+ * The operand stack slots for the current execution frame. Primitive types are represented by
+ * {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+ * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or {@link Opcodes#UNINITIALIZED_THIS} (long and
+ * double are represented by two elements, the second one being TOP). Reference types are
+ * represented by String objects (representing internal names), and uninitialized types by Label
+ * objects (this label designates the NEW instruction that created this uninitialized value). This
+ * field is {@literal null} for unreachable instructions.
+ */
+ public List<Object> stack;
+
+ /** The labels that designate the next instruction to be visited. May be {@literal null}. */
+ private List<Label> labels;
+
+ /**
+ * The uninitialized types in the current execution frame. This map associates internal names to
+ * Label objects. Each label designates a NEW instruction that created the currently uninitialized
+ * types, and the associated internal name represents the NEW operand, i.e. the final, initialized
+ * type value.
+ */
+ public Map<Object, Object> uninitializedTypes;
+
+ /** The maximum stack size of this method. */
+ private int maxStack;
+
+ /** The maximum number of local variables of this method. */
+ private int maxLocals;
+
+ /** The owner's class name. */
+ private String owner;
+
+ /**
+ * Constructs a new {@link AnalyzerAdapter}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #AnalyzerAdapter(int, String, int, String, String,
+ * MethodVisitor)} version.
+ *
+ * @param owner the owner's class name.
+ * @param access the method's access flags (see {@link Opcodes}).
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @param methodVisitor the method visitor to which this adapter delegates calls. May be {@literal
+ * null}.
+ * @throws IllegalStateException If a subclass calls this constructor.
+ */
+ public AnalyzerAdapter(
+ final String owner,
+ final int access,
+ final String name,
+ final String descriptor,
+ final MethodVisitor methodVisitor) {
+ this(Opcodes.ASM7, owner, access, name, descriptor, methodVisitor);
+ if (getClass() != AnalyzerAdapter.class) {
+ throw new IllegalStateException();
}
-
- /**
- * Creates a new {@link AnalyzerAdapter}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param owner
- * the owner's class name.
- * @param access
- * the method's access flags (see {@link Opcodes}).
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- * @param mv
- * the method visitor to which this adapter delegates calls. May
- * be <tt>null</tt>.
- */
- protected AnalyzerAdapter(final int api, final String owner,
- final int access, final String name, final String desc,
- final MethodVisitor mv) {
- super(api, mv);
- this.owner = owner;
- locals = new ArrayList<Object>();
- stack = new ArrayList<Object>();
- uninitializedTypes = new HashMap<Object, Object>();
-
- if ((access & Opcodes.ACC_STATIC) == 0) {
- if ("<init>".equals(name)) {
- locals.add(Opcodes.UNINITIALIZED_THIS);
- } else {
- locals.add(owner);
- }
- }
- Type[] types = Type.getArgumentTypes(desc);
- for (int i = 0; i < types.length; ++i) {
- Type type = types[i];
- switch (type.getSort()) {
- case Type.BOOLEAN:
- case Type.CHAR:
- case Type.BYTE:
- case Type.SHORT:
- case Type.INT:
- locals.add(Opcodes.INTEGER);
- break;
- case Type.FLOAT:
- locals.add(Opcodes.FLOAT);
- break;
- case Type.LONG:
- locals.add(Opcodes.LONG);
- locals.add(Opcodes.TOP);
- break;
- case Type.DOUBLE:
- locals.add(Opcodes.DOUBLE);
- locals.add(Opcodes.TOP);
- break;
- case Type.ARRAY:
- locals.add(types[i].getDescriptor());
- break;
- // case Type.OBJECT:
- default:
- locals.add(types[i].getInternalName());
- }
- }
- maxLocals = locals.size();
+ }
+
+ /**
+ * Constructs a new {@link AnalyzerAdapter}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param owner the owner's class name.
+ * @param access the method's access flags (see {@link Opcodes}).
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @param methodVisitor the method visitor to which this adapter delegates calls. May be {@literal
+ * null}.
+ */
+ protected AnalyzerAdapter(
+ final int api,
+ final String owner,
+ final int access,
+ final String name,
+ final String descriptor,
+ final MethodVisitor methodVisitor) {
+ super(api, methodVisitor);
+ this.owner = owner;
+ locals = new ArrayList<Object>();
+ stack = new ArrayList<Object>();
+ uninitializedTypes = new HashMap<Object, Object>();
+
+ if ((access & Opcodes.ACC_STATIC) == 0) {
+ if ("<init>".equals(name)) {
+ locals.add(Opcodes.UNINITIALIZED_THIS);
+ } else {
+ locals.add(owner);
+ }
}
-
- @Override
- public void visitFrame(final int type, final int nLocal,
- final Object[] local, final int nStack, final Object[] stack) {
- if (type != Opcodes.F_NEW) { // uncompressed frame
- throw new IllegalStateException(
- "ClassReader.accept() should be called with EXPAND_FRAMES flag");
- }
-
- if (mv != null) {
- mv.visitFrame(type, nLocal, local, nStack, stack);
- }
-
- if (this.locals != null) {
- this.locals.clear();
- this.stack.clear();
- } else {
- this.locals = new ArrayList<Object>();
- this.stack = new ArrayList<Object>();
- }
- visitFrameTypes(nLocal, local, this.locals);
- visitFrameTypes(nStack, stack, this.stack);
- maxStack = Math.max(maxStack, this.stack.size());
+ for (Type argumentType : Type.getArgumentTypes(descriptor)) {
+ switch (argumentType.getSort()) {
+ case Type.BOOLEAN:
+ case Type.CHAR:
+ case Type.BYTE:
+ case Type.SHORT:
+ case Type.INT:
+ locals.add(Opcodes.INTEGER);
+ break;
+ case Type.FLOAT:
+ locals.add(Opcodes.FLOAT);
+ break;
+ case Type.LONG:
+ locals.add(Opcodes.LONG);
+ locals.add(Opcodes.TOP);
+ break;
+ case Type.DOUBLE:
+ locals.add(Opcodes.DOUBLE);
+ locals.add(Opcodes.TOP);
+ break;
+ case Type.ARRAY:
+ locals.add(argumentType.getDescriptor());
+ break;
+ case Type.OBJECT:
+ locals.add(argumentType.getInternalName());
+ break;
+ default:
+ throw new AssertionError();
+ }
}
-
- private static void visitFrameTypes(final int n, final Object[] types,
- final List<Object> result) {
- for (int i = 0; i < n; ++i) {
- Object type = types[i];
- result.add(type);
- if (type == Opcodes.LONG || type == Opcodes.DOUBLE) {
- result.add(Opcodes.TOP);
- }
- }
+ maxLocals = locals.size();
+ }
+
+ @Override
+ public void visitFrame(
+ final int type,
+ final int numLocal,
+ final Object[] local,
+ final int numStack,
+ final Object[] stack) {
+ if (type != Opcodes.F_NEW) { // Uncompressed frame.
+ throw new IllegalArgumentException(
+ "AnalyzerAdapter only accepts expanded frames (see ClassReader.EXPAND_FRAMES)");
}
- @Override
- public void visitInsn(final int opcode) {
- if (mv != null) {
- mv.visitInsn(opcode);
- }
- execute(opcode, 0, null);
- if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
- || opcode == Opcodes.ATHROW) {
- this.locals = null;
- this.stack = null;
- }
- }
+ super.visitFrame(type, numLocal, local, numStack, stack);
- @Override
- public void visitIntInsn(final int opcode, final int operand) {
- if (mv != null) {
- mv.visitIntInsn(opcode, operand);
- }
- execute(opcode, operand, null);
+ if (this.locals != null) {
+ this.locals.clear();
+ this.stack.clear();
+ } else {
+ this.locals = new ArrayList<Object>();
+ this.stack = new ArrayList<Object>();
}
-
- @Override
- public void visitVarInsn(final int opcode, final int var) {
- if (mv != null) {
- mv.visitVarInsn(opcode, var);
- }
- execute(opcode, var, null);
+ visitFrameTypes(numLocal, local, this.locals);
+ visitFrameTypes(numStack, stack, this.stack);
+ maxLocals = Math.max(maxLocals, this.locals.size());
+ maxStack = Math.max(maxStack, this.stack.size());
+ }
+
+ private static void visitFrameTypes(
+ final int numTypes, final Object[] frameTypes, final List<Object> result) {
+ for (int i = 0; i < numTypes; ++i) {
+ Object frameType = frameTypes[i];
+ result.add(frameType);
+ if (frameType == Opcodes.LONG || frameType == Opcodes.DOUBLE) {
+ result.add(Opcodes.TOP);
+ }
}
-
- @Override
- public void visitTypeInsn(final int opcode, final String type) {
- if (opcode == Opcodes.NEW) {
- if (labels == null) {
- Label l = new Label();
- labels = new ArrayList<Label>(3);
- labels.add(l);
- if (mv != null) {
- mv.visitLabel(l);
- }
- }
- for (int i = 0; i < labels.size(); ++i) {
- uninitializedTypes.put(labels.get(i), type);
- }
- }
- if (mv != null) {
- mv.visitTypeInsn(opcode, type);
- }
- execute(opcode, 0, type);
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ super.visitInsn(opcode);
+ execute(opcode, 0, null);
+ if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) || opcode == Opcodes.ATHROW) {
+ this.locals = null;
+ this.stack = null;
}
-
- @Override
- public void visitFieldInsn(final int opcode, final String owner,
- final String name, final String desc) {
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ super.visitIntInsn(opcode, operand);
+ execute(opcode, operand, null);
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ super.visitVarInsn(opcode, var);
+ boolean isLongOrDouble =
+ opcode == Opcodes.LLOAD
+ || opcode == Opcodes.DLOAD
+ || opcode == Opcodes.LSTORE
+ || opcode == Opcodes.DSTORE;
+ maxLocals = Math.max(maxLocals, var + (isLongOrDouble ? 2 : 1));
+ execute(opcode, var, null);
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ if (opcode == Opcodes.NEW) {
+ if (labels == null) {
+ Label label = new Label();
+ labels = new ArrayList<Label>(3);
+ labels.add(label);
if (mv != null) {
- mv.visitFieldInsn(opcode, owner, name, desc);
+ mv.visitLabel(label);
}
- execute(opcode, 0, desc);
+ }
+ for (Label label : labels) {
+ uninitializedTypes.put(label, type);
+ }
}
-
- @Deprecated
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc) {
- if (api >= Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc,
- opcode == Opcodes.INVOKEINTERFACE);
+ super.visitTypeInsn(opcode, type);
+ execute(opcode, 0, type);
+ }
+
+ @Override
+ public void visitFieldInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ super.visitFieldInsn(opcode, owner, name, descriptor);
+ execute(opcode, 0, descriptor);
+ }
+
+ /**
+ * Deprecated.
+ *
+ * @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead.
+ */
+ @Deprecated
+ @Override
+ public void visitMethodInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ if (api >= Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor);
+ return;
}
-
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- if (api < Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc, itf);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc, itf);
+ doVisitMethodInsn(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE);
+ }
+
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ return;
}
-
- private void doVisitMethodInsn(int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- if (mv != null) {
- mv.visitMethodInsn(opcode, owner, name, desc, itf);
- }
- if (this.locals == null) {
- labels = null;
- return;
- }
- pop(desc);
- if (opcode != Opcodes.INVOKESTATIC) {
- Object t = pop();
- if (opcode == Opcodes.INVOKESPECIAL && name.charAt(0) == '<') {
- Object u;
- if (t == Opcodes.UNINITIALIZED_THIS) {
- u = this.owner;
- } else {
- u = uninitializedTypes.get(t);
- }
- for (int i = 0; i < locals.size(); ++i) {
- if (locals.get(i) == t) {
- locals.set(i, u);
- }
- }
- for (int i = 0; i < stack.size(); ++i) {
- if (stack.get(i) == t) {
- stack.set(i, u);
- }
- }
- }
- }
- pushDesc(desc);
- labels = null;
+ doVisitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ }
+
+ private void doVisitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
}
-
- @Override
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- if (mv != null) {
- mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
- }
- if (this.locals == null) {
- labels = null;
- return;
- }
- pop(desc);
- pushDesc(desc);
- labels = null;
+ if (this.locals == null) {
+ labels = null;
+ return;
}
-
- @Override
- public void visitJumpInsn(final int opcode, final Label label) {
- if (mv != null) {
- mv.visitJumpInsn(opcode, label);
+ pop(descriptor);
+ if (opcode != Opcodes.INVOKESTATIC) {
+ Object value = pop();
+ if (opcode == Opcodes.INVOKESPECIAL && name.equals("<init>")) {
+ Object initializedValue;
+ if (value == Opcodes.UNINITIALIZED_THIS) {
+ initializedValue = this.owner;
+ } else {
+ initializedValue = uninitializedTypes.get(value);
}
- execute(opcode, 0, null);
- if (opcode == Opcodes.GOTO) {
- this.locals = null;
- this.stack = null;
+ for (int i = 0; i < locals.size(); ++i) {
+ if (locals.get(i) == value) {
+ locals.set(i, initializedValue);
+ }
}
- }
-
- @Override
- public void visitLabel(final Label label) {
- if (mv != null) {
- mv.visitLabel(label);
- }
- if (labels == null) {
- labels = new ArrayList<Label>(3);
+ for (int i = 0; i < stack.size(); ++i) {
+ if (stack.get(i) == value) {
+ stack.set(i, initializedValue);
+ }
}
- labels.add(label);
+ }
}
-
- @Override
- public void visitLdcInsn(final Object cst) {
- if (mv != null) {
- mv.visitLdcInsn(cst);
- }
- if (this.locals == null) {
- labels = null;
- return;
- }
- if (cst instanceof Integer) {
- push(Opcodes.INTEGER);
- } else if (cst instanceof Long) {
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- } else if (cst instanceof Float) {
- push(Opcodes.FLOAT);
- } else if (cst instanceof Double) {
- push(Opcodes.DOUBLE);
- push(Opcodes.TOP);
- } else if (cst instanceof String) {
- push("java/lang/String");
- } else if (cst instanceof Type) {
- int sort = ((Type) cst).getSort();
- if (sort == Type.OBJECT || sort == Type.ARRAY) {
- push("java/lang/Class");
- } else if (sort == Type.METHOD) {
- push("java/lang/invoke/MethodType");
- } else {
- throw new IllegalArgumentException();
- }
- } else if (cst instanceof Handle) {
- push("java/lang/invoke/MethodHandle");
- } else {
- throw new IllegalArgumentException();
- }
- labels = null;
+ pushDescriptor(descriptor);
+ labels = null;
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethodHandle,
+ final Object... bootstrapMethodArguments) {
+ super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
+ if (this.locals == null) {
+ labels = null;
+ return;
}
-
- @Override
- public void visitIincInsn(final int var, final int increment) {
- if (mv != null) {
- mv.visitIincInsn(var, increment);
- }
- execute(Opcodes.IINC, var, null);
+ pop(descriptor);
+ pushDescriptor(descriptor);
+ labels = null;
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ super.visitJumpInsn(opcode, label);
+ execute(opcode, 0, null);
+ if (opcode == Opcodes.GOTO) {
+ this.locals = null;
+ this.stack = null;
}
+ }
- @Override
- public void visitTableSwitchInsn(final int min, final int max,
- final Label dflt, final Label... labels) {
- if (mv != null) {
- mv.visitTableSwitchInsn(min, max, dflt, labels);
- }
- execute(Opcodes.TABLESWITCH, 0, null);
- this.locals = null;
- this.stack = null;
+ @Override
+ public void visitLabel(final Label label) {
+ super.visitLabel(label);
+ if (labels == null) {
+ labels = new ArrayList<Label>(3);
}
-
- @Override
- public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
- final Label[] labels) {
- if (mv != null) {
- mv.visitLookupSwitchInsn(dflt, keys, labels);
- }
- execute(Opcodes.LOOKUPSWITCH, 0, null);
- this.locals = null;
- this.stack = null;
+ labels.add(label);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object value) {
+ super.visitLdcInsn(value);
+ if (this.locals == null) {
+ labels = null;
+ return;
}
-
- @Override
- public void visitMultiANewArrayInsn(final String desc, final int dims) {
- if (mv != null) {
- mv.visitMultiANewArrayInsn(desc, dims);
- }
- execute(Opcodes.MULTIANEWARRAY, dims, desc);
+ if (value instanceof Integer) {
+ push(Opcodes.INTEGER);
+ } else if (value instanceof Long) {
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ } else if (value instanceof Float) {
+ push(Opcodes.FLOAT);
+ } else if (value instanceof Double) {
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ } else if (value instanceof String) {
+ push("java/lang/String");
+ } else if (value instanceof Type) {
+ int sort = ((Type) value).getSort();
+ if (sort == Type.OBJECT || sort == Type.ARRAY) {
+ push("java/lang/Class");
+ } else if (sort == Type.METHOD) {
+ push("java/lang/invoke/MethodType");
+ } else {
+ throw new IllegalArgumentException();
+ }
+ } else if (value instanceof Handle) {
+ push("java/lang/invoke/MethodHandle");
+ } else if (value instanceof ConstantDynamic) {
+ pushDescriptor(((ConstantDynamic) value).getDescriptor());
+ } else {
+ throw new IllegalArgumentException();
}
-
- @Override
- public void visitMaxs(final int maxStack, final int maxLocals) {
- if (mv != null) {
- this.maxStack = Math.max(this.maxStack, maxStack);
- this.maxLocals = Math.max(this.maxLocals, maxLocals);
- mv.visitMaxs(this.maxStack, this.maxLocals);
- }
+ labels = null;
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ super.visitIincInsn(var, increment);
+ maxLocals = Math.max(maxLocals, var + 1);
+ execute(Opcodes.IINC, var, null);
+ }
+
+ @Override
+ public void visitTableSwitchInsn(
+ final int min, final int max, final Label dflt, final Label... labels) {
+ super.visitTableSwitchInsn(min, max, dflt, labels);
+ execute(Opcodes.TABLESWITCH, 0, null);
+ this.locals = null;
+ this.stack = null;
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
+ super.visitLookupSwitchInsn(dflt, keys, labels);
+ execute(Opcodes.LOOKUPSWITCH, 0, null);
+ this.locals = null;
+ this.stack = null;
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
+ super.visitMultiANewArrayInsn(descriptor, numDimensions);
+ execute(Opcodes.MULTIANEWARRAY, numDimensions, descriptor);
+ }
+
+ @Override
+ public void visitLocalVariable(
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index) {
+ char firstDescriptorChar = descriptor.charAt(0);
+ maxLocals =
+ Math.max(
+ maxLocals, index + (firstDescriptorChar == 'J' || firstDescriptorChar == 'D' ? 2 : 1));
+ super.visitLocalVariable(name, descriptor, signature, start, end, index);
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ if (mv != null) {
+ this.maxStack = Math.max(this.maxStack, maxStack);
+ this.maxLocals = Math.max(this.maxLocals, maxLocals);
+ mv.visitMaxs(this.maxStack, this.maxLocals);
}
+ }
- // ------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
- private Object get(final int local) {
- maxLocals = Math.max(maxLocals, local + 1);
- return local < locals.size() ? locals.get(local) : Opcodes.TOP;
- }
+ private Object get(final int local) {
+ maxLocals = Math.max(maxLocals, local + 1);
+ return local < locals.size() ? locals.get(local) : Opcodes.TOP;
+ }
- private void set(final int local, final Object type) {
- maxLocals = Math.max(maxLocals, local + 1);
- while (local >= locals.size()) {
- locals.add(Opcodes.TOP);
+ private void set(final int local, final Object type) {
+ maxLocals = Math.max(maxLocals, local + 1);
+ while (local >= locals.size()) {
+ locals.add(Opcodes.TOP);
+ }
+ locals.set(local, type);
+ }
+
+ private void push(final Object type) {
+ stack.add(type);
+ maxStack = Math.max(maxStack, stack.size());
+ }
+
+ private void pushDescriptor(final String descriptor) {
+ int index = descriptor.charAt(0) == '(' ? descriptor.indexOf(')') + 1 : 0;
+ switch (descriptor.charAt(index)) {
+ case 'V':
+ return;
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ push(Opcodes.INTEGER);
+ return;
+ case 'F':
+ push(Opcodes.FLOAT);
+ return;
+ case 'J':
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ return;
+ case 'D':
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ return;
+ case '[':
+ if (index == 0) {
+ push(descriptor);
+ } else {
+ push(descriptor.substring(index, descriptor.length()));
}
- locals.set(local, type);
+ break;
+ case 'L':
+ if (index == 0) {
+ push(descriptor.substring(1, descriptor.length() - 1));
+ } else {
+ push(descriptor.substring(index + 1, descriptor.length() - 1));
+ }
+ break;
+ default:
+ throw new AssertionError();
}
+ }
- private void push(final Object type) {
- stack.add(type);
- maxStack = Math.max(maxStack, stack.size());
- }
+ private Object pop() {
+ return stack.remove(stack.size() - 1);
+ }
- private void pushDesc(final String desc) {
- int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
- switch (desc.charAt(index)) {
- case 'V':
- return;
- case 'Z':
- case 'C':
- case 'B':
- case 'S':
- case 'I':
- push(Opcodes.INTEGER);
- return;
- case 'F':
- push(Opcodes.FLOAT);
- return;
- case 'J':
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- return;
- case 'D':
- push(Opcodes.DOUBLE);
- push(Opcodes.TOP);
- return;
- case '[':
- if (index == 0) {
- push(desc);
- } else {
- push(desc.substring(index, desc.length()));
- }
- break;
- // case 'L':
- default:
- if (index == 0) {
- push(desc.substring(1, desc.length() - 1));
- } else {
- push(desc.substring(index + 1, desc.length() - 1));
- }
- }
+ private void pop(final int numSlots) {
+ int size = stack.size();
+ int end = size - numSlots;
+ for (int i = size - 1; i >= end; --i) {
+ stack.remove(i);
}
-
- private Object pop() {
- return stack.remove(stack.size() - 1);
+ }
+
+ private void pop(final String descriptor) {
+ char firstDescriptorChar = descriptor.charAt(0);
+ if (firstDescriptorChar == '(') {
+ int numSlots = 0;
+ Type[] types = Type.getArgumentTypes(descriptor);
+ for (Type type : types) {
+ numSlots += type.getSize();
+ }
+ pop(numSlots);
+ } else if (firstDescriptorChar == 'J' || firstDescriptorChar == 'D') {
+ pop(2);
+ } else {
+ pop(1);
}
+ }
- private void pop(final int n) {
- int size = stack.size();
- int end = size - n;
- for (int i = size - 1; i >= end; --i) {
- stack.remove(i);
- }
+ private void execute(final int opcode, final int intArg, final String stringArg) {
+ if (this.locals == null) {
+ labels = null;
+ return;
}
-
- private void pop(final String desc) {
- char c = desc.charAt(0);
- if (c == '(') {
- int n = 0;
- Type[] types = Type.getArgumentTypes(desc);
- for (int i = 0; i < types.length; ++i) {
- n += types[i].getSize();
- }
- pop(n);
- } else if (c == 'J' || c == 'D') {
- pop(2);
+ Object value1;
+ Object value2;
+ Object value3;
+ Object t4;
+ switch (opcode) {
+ case Opcodes.NOP:
+ case Opcodes.INEG:
+ case Opcodes.LNEG:
+ case Opcodes.FNEG:
+ case Opcodes.DNEG:
+ case Opcodes.I2B:
+ case Opcodes.I2C:
+ case Opcodes.I2S:
+ case Opcodes.GOTO:
+ case Opcodes.RETURN:
+ break;
+ case Opcodes.ACONST_NULL:
+ push(Opcodes.NULL);
+ break;
+ case Opcodes.ICONST_M1:
+ case Opcodes.ICONST_0:
+ case Opcodes.ICONST_1:
+ case Opcodes.ICONST_2:
+ case Opcodes.ICONST_3:
+ case Opcodes.ICONST_4:
+ case Opcodes.ICONST_5:
+ case Opcodes.BIPUSH:
+ case Opcodes.SIPUSH:
+ push(Opcodes.INTEGER);
+ break;
+ case Opcodes.LCONST_0:
+ case Opcodes.LCONST_1:
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.FCONST_0:
+ case Opcodes.FCONST_1:
+ case Opcodes.FCONST_2:
+ push(Opcodes.FLOAT);
+ break;
+ case Opcodes.DCONST_0:
+ case Opcodes.DCONST_1:
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.ILOAD:
+ case Opcodes.FLOAD:
+ case Opcodes.ALOAD:
+ push(get(intArg));
+ break;
+ case Opcodes.LLOAD:
+ case Opcodes.DLOAD:
+ push(get(intArg));
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.LALOAD:
+ case Opcodes.D2L:
+ pop(2);
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.DALOAD:
+ case Opcodes.L2D:
+ pop(2);
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.AALOAD:
+ pop(1);
+ value1 = pop();
+ if (value1 instanceof String) {
+ pushDescriptor(((String) value1).substring(1));
+ } else if (value1 == Opcodes.NULL) {
+ push(value1);
} else {
- pop(1);
- }
- }
-
- private void execute(final int opcode, final int iarg, final String sarg) {
- if (this.locals == null) {
- labels = null;
- return;
- }
- Object t1, t2, t3, t4;
- switch (opcode) {
- case Opcodes.NOP:
- case Opcodes.INEG:
- case Opcodes.LNEG:
- case Opcodes.FNEG:
- case Opcodes.DNEG:
- case Opcodes.I2B:
- case Opcodes.I2C:
- case Opcodes.I2S:
- case Opcodes.GOTO:
- case Opcodes.RETURN:
- break;
- case Opcodes.ACONST_NULL:
- push(Opcodes.NULL);
- break;
- case Opcodes.ICONST_M1:
- case Opcodes.ICONST_0:
- case Opcodes.ICONST_1:
- case Opcodes.ICONST_2:
- case Opcodes.ICONST_3:
- case Opcodes.ICONST_4:
- case Opcodes.ICONST_5:
- case Opcodes.BIPUSH:
- case Opcodes.SIPUSH:
- push(Opcodes.INTEGER);
- break;
- case Opcodes.LCONST_0:
- case Opcodes.LCONST_1:
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- break;
- case Opcodes.FCONST_0:
- case Opcodes.FCONST_1:
- case Opcodes.FCONST_2:
- push(Opcodes.FLOAT);
- break;
- case Opcodes.DCONST_0:
- case Opcodes.DCONST_1:
- push(Opcodes.DOUBLE);
- push(Opcodes.TOP);
- break;
- case Opcodes.ILOAD:
- case Opcodes.FLOAD:
- case Opcodes.ALOAD:
- push(get(iarg));
- break;
- case Opcodes.LLOAD:
- case Opcodes.DLOAD:
- push(get(iarg));
- push(Opcodes.TOP);
- break;
- case Opcodes.IALOAD:
- case Opcodes.BALOAD:
- case Opcodes.CALOAD:
- case Opcodes.SALOAD:
- pop(2);
- push(Opcodes.INTEGER);
- break;
- case Opcodes.LALOAD:
- case Opcodes.D2L:
- pop(2);
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- break;
- case Opcodes.FALOAD:
- pop(2);
- push(Opcodes.FLOAT);
- break;
- case Opcodes.DALOAD:
- case Opcodes.L2D:
- pop(2);
- push(Opcodes.DOUBLE);
- push(Opcodes.TOP);
- break;
- case Opcodes.AALOAD:
- pop(1);
- t1 = pop();
- if (t1 instanceof String) {
- pushDesc(((String) t1).substring(1));
- } else if (t1 == Opcodes.NULL) {
- push(t1);
- } else {
- push("java/lang/Object");
- }
- break;
- case Opcodes.ISTORE:
- case Opcodes.FSTORE:
- case Opcodes.ASTORE:
- t1 = pop();
- set(iarg, t1);
- if (iarg > 0) {
- t2 = get(iarg - 1);
- if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) {
- set(iarg - 1, Opcodes.TOP);
- }
- }
- break;
- case Opcodes.LSTORE:
- case Opcodes.DSTORE:
- pop(1);
- t1 = pop();
- set(iarg, t1);
- set(iarg + 1, Opcodes.TOP);
- if (iarg > 0) {
- t2 = get(iarg - 1);
- if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) {
- set(iarg - 1, Opcodes.TOP);
- }
- }
- break;
- case Opcodes.IASTORE:
- case Opcodes.BASTORE:
- case Opcodes.CASTORE:
- case Opcodes.SASTORE:
- case Opcodes.FASTORE:
- case Opcodes.AASTORE:
- pop(3);
- break;
- case Opcodes.LASTORE:
- case Opcodes.DASTORE:
- pop(4);
- break;
- case Opcodes.POP:
- case Opcodes.IFEQ:
- case Opcodes.IFNE:
- case Opcodes.IFLT:
- case Opcodes.IFGE:
- case Opcodes.IFGT:
- case Opcodes.IFLE:
- case Opcodes.IRETURN:
- case Opcodes.FRETURN:
- case Opcodes.ARETURN:
- case Opcodes.TABLESWITCH:
- case Opcodes.LOOKUPSWITCH:
- case Opcodes.ATHROW:
- case Opcodes.MONITORENTER:
- case Opcodes.MONITOREXIT:
- case Opcodes.IFNULL:
- case Opcodes.IFNONNULL:
- pop(1);
- break;
- case Opcodes.POP2:
- case Opcodes.IF_ICMPEQ:
- case Opcodes.IF_ICMPNE:
- case Opcodes.IF_ICMPLT:
- case Opcodes.IF_ICMPGE:
- case Opcodes.IF_ICMPGT:
- case Opcodes.IF_ICMPLE:
- case Opcodes.IF_ACMPEQ:
- case Opcodes.IF_ACMPNE:
- case Opcodes.LRETURN:
- case Opcodes.DRETURN:
- pop(2);
- break;
- case Opcodes.DUP:
- t1 = pop();
- push(t1);
- push(t1);
- break;
- case Opcodes.DUP_X1:
- t1 = pop();
- t2 = pop();
- push(t1);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP_X2:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- push(t1);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2:
- t1 = pop();
- t2 = pop();
- push(t2);
- push(t1);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2_X1:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- push(t2);
- push(t1);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2_X2:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- t4 = pop();
- push(t2);
- push(t1);
- push(t4);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.SWAP:
- t1 = pop();
- t2 = pop();
- push(t1);
- push(t2);
- break;
- case Opcodes.IADD:
- case Opcodes.ISUB:
- case Opcodes.IMUL:
- case Opcodes.IDIV:
- case Opcodes.IREM:
- case Opcodes.IAND:
- case Opcodes.IOR:
- case Opcodes.IXOR:
- case Opcodes.ISHL:
- case Opcodes.ISHR:
- case Opcodes.IUSHR:
- case Opcodes.L2I:
- case Opcodes.D2I:
- case Opcodes.FCMPL:
- case Opcodes.FCMPG:
- pop(2);
- push(Opcodes.INTEGER);
- break;
- case Opcodes.LADD:
- case Opcodes.LSUB:
- case Opcodes.LMUL:
- case Opcodes.LDIV:
- case Opcodes.LREM:
- case Opcodes.LAND:
- case Opcodes.LOR:
- case Opcodes.LXOR:
- pop(4);
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- break;
- case Opcodes.FADD:
- case Opcodes.FSUB:
- case Opcodes.FMUL:
- case Opcodes.FDIV:
- case Opcodes.FREM:
- case Opcodes.L2F:
- case Opcodes.D2F:
- pop(2);
- push(Opcodes.FLOAT);
- break;
- case Opcodes.DADD:
- case Opcodes.DSUB:
- case Opcodes.DMUL:
- case Opcodes.DDIV:
- case Opcodes.DREM:
- pop(4);
- push(Opcodes.DOUBLE);
- push(Opcodes.TOP);
- break;
- case Opcodes.LSHL:
- case Opcodes.LSHR:
- case Opcodes.LUSHR:
- pop(3);
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- break;
- case Opcodes.IINC:
- set(iarg, Opcodes.INTEGER);
- break;
- case Opcodes.I2L:
- case Opcodes.F2L:
- pop(1);
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- break;
- case Opcodes.I2F:
- pop(1);
- push(Opcodes.FLOAT);
- break;
- case Opcodes.I2D:
- case Opcodes.F2D:
- pop(1);
- push(Opcodes.DOUBLE);
- push(Opcodes.TOP);
- break;
- case Opcodes.F2I:
- case Opcodes.ARRAYLENGTH:
- case Opcodes.INSTANCEOF:
- pop(1);
- push(Opcodes.INTEGER);
- break;
- case Opcodes.LCMP:
- case Opcodes.DCMPL:
- case Opcodes.DCMPG:
- pop(4);
- push(Opcodes.INTEGER);
- break;
- case Opcodes.JSR:
- case Opcodes.RET:
- throw new RuntimeException("JSR/RET are not supported");
- case Opcodes.GETSTATIC:
- pushDesc(sarg);
- break;
- case Opcodes.PUTSTATIC:
- pop(sarg);
- break;
- case Opcodes.GETFIELD:
- pop(1);
- pushDesc(sarg);
- break;
- case Opcodes.PUTFIELD:
- pop(sarg);
- pop();
- break;
- case Opcodes.NEW:
- push(labels.get(0));
- break;
- case Opcodes.NEWARRAY:
- pop();
- switch (iarg) {
- case Opcodes.T_BOOLEAN:
- pushDesc("[Z");
- break;
- case Opcodes.T_CHAR:
- pushDesc("[C");
- break;
- case Opcodes.T_BYTE:
- pushDesc("[B");
- break;
- case Opcodes.T_SHORT:
- pushDesc("[S");
- break;
- case Opcodes.T_INT:
- pushDesc("[I");
- break;
- case Opcodes.T_FLOAT:
- pushDesc("[F");
- break;
- case Opcodes.T_DOUBLE:
- pushDesc("[D");
- break;
- // case Opcodes.T_LONG:
- default:
- pushDesc("[J");
- break;
- }
- break;
- case Opcodes.ANEWARRAY:
- pop();
- pushDesc("[" + Type.getObjectType(sarg));
- break;
- case Opcodes.CHECKCAST:
- pop();
- pushDesc(Type.getObjectType(sarg).getDescriptor());
- break;
- // case Opcodes.MULTIANEWARRAY:
- default:
- pop(iarg);
- pushDesc(sarg);
- break;
- }
- labels = null;
+ push("java/lang/Object");
+ }
+ break;
+ case Opcodes.ISTORE:
+ case Opcodes.FSTORE:
+ case Opcodes.ASTORE:
+ value1 = pop();
+ set(intArg, value1);
+ if (intArg > 0) {
+ value2 = get(intArg - 1);
+ if (value2 == Opcodes.LONG || value2 == Opcodes.DOUBLE) {
+ set(intArg - 1, Opcodes.TOP);
+ }
+ }
+ break;
+ case Opcodes.LSTORE:
+ case Opcodes.DSTORE:
+ pop(1);
+ value1 = pop();
+ set(intArg, value1);
+ set(intArg + 1, Opcodes.TOP);
+ if (intArg > 0) {
+ value2 = get(intArg - 1);
+ if (value2 == Opcodes.LONG || value2 == Opcodes.DOUBLE) {
+ set(intArg - 1, Opcodes.TOP);
+ }
+ }
+ break;
+ case Opcodes.IASTORE:
+ case Opcodes.BASTORE:
+ case Opcodes.CASTORE:
+ case Opcodes.SASTORE:
+ case Opcodes.FASTORE:
+ case Opcodes.AASTORE:
+ pop(3);
+ break;
+ case Opcodes.LASTORE:
+ case Opcodes.DASTORE:
+ pop(4);
+ break;
+ case Opcodes.POP:
+ case Opcodes.IFEQ:
+ case Opcodes.IFNE:
+ case Opcodes.IFLT:
+ case Opcodes.IFGE:
+ case Opcodes.IFGT:
+ case Opcodes.IFLE:
+ case Opcodes.IRETURN:
+ case Opcodes.FRETURN:
+ case Opcodes.ARETURN:
+ case Opcodes.TABLESWITCH:
+ case Opcodes.LOOKUPSWITCH:
+ case Opcodes.ATHROW:
+ case Opcodes.MONITORENTER:
+ case Opcodes.MONITOREXIT:
+ case Opcodes.IFNULL:
+ case Opcodes.IFNONNULL:
+ pop(1);
+ break;
+ case Opcodes.POP2:
+ case Opcodes.IF_ICMPEQ:
+ case Opcodes.IF_ICMPNE:
+ case Opcodes.IF_ICMPLT:
+ case Opcodes.IF_ICMPGE:
+ case Opcodes.IF_ICMPGT:
+ case Opcodes.IF_ICMPLE:
+ case Opcodes.IF_ACMPEQ:
+ case Opcodes.IF_ACMPNE:
+ case Opcodes.LRETURN:
+ case Opcodes.DRETURN:
+ pop(2);
+ break;
+ case Opcodes.DUP:
+ value1 = pop();
+ push(value1);
+ push(value1);
+ break;
+ case Opcodes.DUP_X1:
+ value1 = pop();
+ value2 = pop();
+ push(value1);
+ push(value2);
+ push(value1);
+ break;
+ case Opcodes.DUP_X2:
+ value1 = pop();
+ value2 = pop();
+ value3 = pop();
+ push(value1);
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ case Opcodes.DUP2:
+ value1 = pop();
+ value2 = pop();
+ push(value2);
+ push(value1);
+ push(value2);
+ push(value1);
+ break;
+ case Opcodes.DUP2_X1:
+ value1 = pop();
+ value2 = pop();
+ value3 = pop();
+ push(value2);
+ push(value1);
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ case Opcodes.DUP2_X2:
+ value1 = pop();
+ value2 = pop();
+ value3 = pop();
+ t4 = pop();
+ push(value2);
+ push(value1);
+ push(t4);
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ case Opcodes.SWAP:
+ value1 = pop();
+ value2 = pop();
+ push(value1);
+ push(value2);
+ break;
+ case Opcodes.IALOAD:
+ case Opcodes.BALOAD:
+ case Opcodes.CALOAD:
+ case Opcodes.SALOAD:
+ case Opcodes.IADD:
+ case Opcodes.ISUB:
+ case Opcodes.IMUL:
+ case Opcodes.IDIV:
+ case Opcodes.IREM:
+ case Opcodes.IAND:
+ case Opcodes.IOR:
+ case Opcodes.IXOR:
+ case Opcodes.ISHL:
+ case Opcodes.ISHR:
+ case Opcodes.IUSHR:
+ case Opcodes.L2I:
+ case Opcodes.D2I:
+ case Opcodes.FCMPL:
+ case Opcodes.FCMPG:
+ pop(2);
+ push(Opcodes.INTEGER);
+ break;
+ case Opcodes.LADD:
+ case Opcodes.LSUB:
+ case Opcodes.LMUL:
+ case Opcodes.LDIV:
+ case Opcodes.LREM:
+ case Opcodes.LAND:
+ case Opcodes.LOR:
+ case Opcodes.LXOR:
+ pop(4);
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.FALOAD:
+ case Opcodes.FADD:
+ case Opcodes.FSUB:
+ case Opcodes.FMUL:
+ case Opcodes.FDIV:
+ case Opcodes.FREM:
+ case Opcodes.L2F:
+ case Opcodes.D2F:
+ pop(2);
+ push(Opcodes.FLOAT);
+ break;
+ case Opcodes.DADD:
+ case Opcodes.DSUB:
+ case Opcodes.DMUL:
+ case Opcodes.DDIV:
+ case Opcodes.DREM:
+ pop(4);
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.LSHL:
+ case Opcodes.LSHR:
+ case Opcodes.LUSHR:
+ pop(3);
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.IINC:
+ set(intArg, Opcodes.INTEGER);
+ break;
+ case Opcodes.I2L:
+ case Opcodes.F2L:
+ pop(1);
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.I2F:
+ pop(1);
+ push(Opcodes.FLOAT);
+ break;
+ case Opcodes.I2D:
+ case Opcodes.F2D:
+ pop(1);
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.F2I:
+ case Opcodes.ARRAYLENGTH:
+ case Opcodes.INSTANCEOF:
+ pop(1);
+ push(Opcodes.INTEGER);
+ break;
+ case Opcodes.LCMP:
+ case Opcodes.DCMPL:
+ case Opcodes.DCMPG:
+ pop(4);
+ push(Opcodes.INTEGER);
+ break;
+ case Opcodes.JSR:
+ case Opcodes.RET:
+ throw new IllegalArgumentException("JSR/RET are not supported");
+ case Opcodes.GETSTATIC:
+ pushDescriptor(stringArg);
+ break;
+ case Opcodes.PUTSTATIC:
+ pop(stringArg);
+ break;
+ case Opcodes.GETFIELD:
+ pop(1);
+ pushDescriptor(stringArg);
+ break;
+ case Opcodes.PUTFIELD:
+ pop(stringArg);
+ pop();
+ break;
+ case Opcodes.NEW:
+ push(labels.get(0));
+ break;
+ case Opcodes.NEWARRAY:
+ pop();
+ switch (intArg) {
+ case Opcodes.T_BOOLEAN:
+ pushDescriptor("[Z");
+ break;
+ case Opcodes.T_CHAR:
+ pushDescriptor("[C");
+ break;
+ case Opcodes.T_BYTE:
+ pushDescriptor("[B");
+ break;
+ case Opcodes.T_SHORT:
+ pushDescriptor("[S");
+ break;
+ case Opcodes.T_INT:
+ pushDescriptor("[I");
+ break;
+ case Opcodes.T_FLOAT:
+ pushDescriptor("[F");
+ break;
+ case Opcodes.T_DOUBLE:
+ pushDescriptor("[D");
+ break;
+ case Opcodes.T_LONG:
+ pushDescriptor("[J");
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid array type " + intArg);
+ }
+ break;
+ case Opcodes.ANEWARRAY:
+ pop();
+ pushDescriptor("[" + Type.getObjectType(stringArg));
+ break;
+ case Opcodes.CHECKCAST:
+ pop();
+ pushDescriptor(Type.getObjectType(stringArg).getDescriptor());
+ break;
+ case Opcodes.MULTIANEWARRAY:
+ pop(intArg);
+ pushDescriptor(stringArg);
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid opcode " + opcode);
}
+ labels = null;
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnnotationRemapper.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnnotationRemapper.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnnotationRemapper.java
old mode 100644
new mode 100755
index 74dded8..24a2de5
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnnotationRemapper.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnnotationRemapper.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
@@ -34,46 +32,72 @@ import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
- * An {@link AnnotationVisitor} adapter for type remapping.
- *
+ * An {@link AnnotationVisitor} that remaps types with a {@link Remapper}.
+ *
* @author Eugene Kuleshov
*/
public class AnnotationRemapper extends AnnotationVisitor {
- protected final Remapper remapper;
+ /** The remapper used to remap the types in the visited annotation. */
+ protected final Remapper remapper;
- public AnnotationRemapper(final AnnotationVisitor av,
- final Remapper remapper) {
- this(Opcodes.ASM6, av, remapper);
- }
+ /**
+ * Constructs a new {@link AnnotationRemapper}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #AnnotationRemapper(int,AnnotationVisitor,Remapper)} version.
+ *
+ * @param annotationVisitor the annotation visitor this remapper must deleted to.
+ * @param remapper the remapper to use to remap the types in the visited annotation.
+ */
+ public AnnotationRemapper(final AnnotationVisitor annotationVisitor, final Remapper remapper) {
+ this(Opcodes.ASM7, annotationVisitor, remapper);
+ }
- protected AnnotationRemapper(final int api, final AnnotationVisitor av,
- final Remapper remapper) {
- super(api, av);
- this.remapper = remapper;
- }
+ /**
+ * Constructs a new {@link AnnotationRemapper}.
+ *
+ * @param api the ASM API version supported by this remapper. Must be one of {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM4}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM5} or {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM6}.
+ * @param annotationVisitor the annotation visitor this remapper must deleted to.
+ * @param remapper the remapper to use to remap the types in the visited annotation.
+ */
+ protected AnnotationRemapper(
+ final int api, final AnnotationVisitor annotationVisitor, final Remapper remapper) {
+ super(api, annotationVisitor);
+ this.remapper = remapper;
+ }
- @Override
- public void visit(String name, Object value) {
- av.visit(name, remapper.mapValue(value));
- }
+ @Override
+ public void visit(final String name, final Object value) {
+ super.visit(name, remapper.mapValue(value));
+ }
- @Override
- public void visitEnum(String name, String desc, String value) {
- av.visitEnum(name, remapper.mapDesc(desc), value);
- }
+ @Override
+ public void visitEnum(final String name, final String descriptor, final String value) {
+ super.visitEnum(name, remapper.mapDesc(descriptor), value);
+ }
- @Override
- public AnnotationVisitor visitAnnotation(String name, String desc) {
- AnnotationVisitor v = av.visitAnnotation(name, remapper.mapDesc(desc));
- return v == null ? null : (v == av ? this : new AnnotationRemapper(v,
- remapper));
+ @Override
+ public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
+ AnnotationVisitor annotationVisitor = super.visitAnnotation(name, remapper.mapDesc(descriptor));
+ if (annotationVisitor == null) {
+ return null;
+ } else {
+ return annotationVisitor == av
+ ? this
+ : new AnnotationRemapper(api, annotationVisitor, remapper);
}
+ }
- @Override
- public AnnotationVisitor visitArray(String name) {
- AnnotationVisitor v = av.visitArray(name);
- return v == null ? null : (v == av ? this : new AnnotationRemapper(v,
- remapper));
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ AnnotationVisitor annotationVisitor = super.visitArray(name);
+ if (annotationVisitor == null) {
+ return null;
+ } else {
+ return annotationVisitor == av
+ ? this
+ : new AnnotationRemapper(api, annotationVisitor, remapper);
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ClassRemapper.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ClassRemapper.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ClassRemapper.java
old mode 100644
new mode 100755
index 8090c0d..f837457
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ClassRemapper.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ClassRemapper.java
@@ -1,37 +1,34 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
import java.util.List;
-
import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
import org.apache.tapestry5.internal.plastic.asm.Attribute;
import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
@@ -42,117 +39,198 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
- * A {@link ClassVisitor} for type remapping.
- *
+ * A {@link ClassVisitor} that remaps types with a {@link Remapper}.
+ *
* @author Eugene Kuleshov
*/
public class ClassRemapper extends ClassVisitor {
- protected final Remapper remapper;
-
- protected String className;
-
- public ClassRemapper(final ClassVisitor cv, final Remapper remapper) {
- this(Opcodes.ASM6, cv, remapper);
- }
-
- protected ClassRemapper(final int api, final ClassVisitor cv,
- final Remapper remapper) {
- super(api, cv);
- this.remapper = remapper;
- }
-
- @Override
- public void visit(int version, int access, String name, String signature,
- String superName, String[] interfaces) {
- this.className = name;
- super.visit(version, access, remapper.mapType(name), remapper
- .mapSignature(signature, false), remapper.mapType(superName),
- interfaces == null ? null : remapper.mapTypes(interfaces));
- }
-
- @Override
- public ModuleVisitor visitModule(String name, int flags, String version) {
- ModuleVisitor mv = super.visitModule(remapper.mapModuleName(name), flags, version);
- return mv == null ? null : createModuleRemapper(mv);
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
- visible);
- return av == null ? null : createAnnotationRemapper(av);
- }
-
- @Override
- public AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
- remapper.mapDesc(desc), visible);
- return av == null ? null : createAnnotationRemapper(av);
- }
-
- @Override
- public void visitAttribute(Attribute attr) {
- if (attr instanceof ModuleHashesAttribute) {
- ModuleHashesAttribute hashesAttr = new ModuleHashesAttribute();
- List<String> modules = hashesAttr.modules;
- for(int i = 0; i < modules.size(); i++) {
- modules.set(i, remapper.mapModuleName(modules.get(i)));
- }
- }
- super.visitAttribute(attr);
- }
-
- @Override
- public FieldVisitor visitField(int access, String name, String desc,
- String signature, Object value) {
- FieldVisitor fv = super.visitField(access,
- remapper.mapFieldName(className, name, desc),
- remapper.mapDesc(desc), remapper.mapSignature(signature, true),
- remapper.mapValue(value));
- return fv == null ? null : createFieldRemapper(fv);
- }
-
- @Override
- public MethodVisitor visitMethod(int access, String name, String desc,
- String signature, String[] exceptions) {
- String newDesc = remapper.mapMethodDesc(desc);
- MethodVisitor mv = super.visitMethod(access, remapper.mapMethodName(
- className, name, desc), newDesc, remapper.mapSignature(
- signature, false),
- exceptions == null ? null : remapper.mapTypes(exceptions));
- return mv == null ? null : createMethodRemapper(mv);
- }
-
- @Override
- public void visitInnerClass(String name, String outerName,
- String innerName, int access) {
- // TODO should innerName be changed?
- super.visitInnerClass(remapper.mapType(name), outerName == null ? null
- : remapper.mapType(outerName), innerName, access);
- }
-
- @Override
- public void visitOuterClass(String owner, String name, String desc) {
- super.visitOuterClass(remapper.mapType(owner), name == null ? null
- : remapper.mapMethodName(owner, name, desc),
- desc == null ? null : remapper.mapMethodDesc(desc));
- }
-
- protected FieldVisitor createFieldRemapper(FieldVisitor fv) {
- return new FieldRemapper(fv, remapper);
- }
-
- protected MethodVisitor createMethodRemapper(MethodVisitor mv) {
- return new MethodRemapper(mv, remapper);
- }
-
- protected AnnotationVisitor createAnnotationRemapper(AnnotationVisitor av) {
- return new AnnotationRemapper(av, remapper);
- }
-
- protected ModuleVisitor createModuleRemapper(ModuleVisitor mv) {
- return new ModuleRemapper(mv, remapper);
+ /** The remapper used to remap the types in the visited class. */
+ protected final Remapper remapper;
+
+ /** The internal name of the visited class. */
+ protected String className;
+
+ /**
+ * Constructs a new {@link ClassRemapper}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #ClassRemapper(int,ClassVisitor,Remapper)} version.
+ *
+ * @param classVisitor the class visitor this remapper must deleted to.
+ * @param remapper the remapper to use to remap the types in the visited class.
+ */
+ public ClassRemapper(final ClassVisitor classVisitor, final Remapper remapper) {
+ this(Opcodes.ASM7, classVisitor, remapper);
+ }
+
+ /**
+ * Constructs a new {@link ClassRemapper}.
+ *
+ * @param api the ASM API version supported by this remapper. Must be one of {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM4}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM5}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM6} or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM7}.
+ * @param classVisitor the class visitor this remapper must deleted to.
+ * @param remapper the remapper to use to remap the types in the visited class.
+ */
+ protected ClassRemapper(final int api, final ClassVisitor classVisitor, final Remapper remapper) {
+ super(api, classVisitor);
+ this.remapper = remapper;
+ }
+
+ @Override
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces) {
+ this.className = name;
+ super.visit(
+ version,
+ access,
+ remapper.mapType(name),
+ remapper.mapSignature(signature, false),
+ remapper.mapType(superName),
+ interfaces == null ? null : remapper.mapTypes(interfaces));
+ }
+
+ @Override
+ public ModuleVisitor visitModule(final String name, final int flags, final String version) {
+ ModuleVisitor moduleVisitor = super.visitModule(remapper.mapModuleName(name), flags, version);
+ return moduleVisitor == null ? null : createModuleRemapper(moduleVisitor);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitAnnotation(remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null ? null : createAnnotationRemapper(annotationVisitor);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null ? null : createAnnotationRemapper(annotationVisitor);
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attribute) {
+ if (attribute instanceof ModuleHashesAttribute) {
+ ModuleHashesAttribute moduleHashesAttribute = (ModuleHashesAttribute) attribute;
+ List<String> modules = moduleHashesAttribute.modules;
+ for (int i = 0; i < modules.size(); ++i) {
+ modules.set(i, remapper.mapModuleName(modules.get(i)));
+ }
}
+ super.visitAttribute(attribute);
+ }
+
+ @Override
+ public FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Object value) {
+ FieldVisitor fieldVisitor =
+ super.visitField(
+ access,
+ remapper.mapFieldName(className, name, descriptor),
+ remapper.mapDesc(descriptor),
+ remapper.mapSignature(signature, true),
+ (value == null) ? null : remapper.mapValue(value));
+ return fieldVisitor == null ? null : createFieldRemapper(fieldVisitor);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ String remappedDescriptor = remapper.mapMethodDesc(descriptor);
+ MethodVisitor methodVisitor =
+ super.visitMethod(
+ access,
+ remapper.mapMethodName(className, name, descriptor),
+ remappedDescriptor,
+ remapper.mapSignature(signature, false),
+ exceptions == null ? null : remapper.mapTypes(exceptions));
+ return methodVisitor == null ? null : createMethodRemapper(methodVisitor);
+ }
+
+ @Override
+ public void visitInnerClass(
+ final String name, final String outerName, final String innerName, final int access) {
+ super.visitInnerClass(
+ remapper.mapType(name),
+ outerName == null ? null : remapper.mapType(outerName),
+ innerName == null ? null : remapper.mapInnerClassName(name, outerName, innerName),
+ access);
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name, final String descriptor) {
+ super.visitOuterClass(
+ remapper.mapType(owner),
+ name == null ? null : remapper.mapMethodName(owner, name, descriptor),
+ descriptor == null ? null : remapper.mapMethodDesc(descriptor));
+ }
+
+ @Override
+ public void visitNestHost(final String nestHost) {
+ super.visitNestHost(remapper.mapType(nestHost));
+ }
+
+ @Override
+ public void visitNestMember(final String nestMember) {
+ super.visitNestMember(remapper.mapType(nestMember));
+ }
+
+ /**
+ * Constructs a new remapper for fields. The default implementation of this method returns a new
+ * {@link FieldRemapper}.
+ *
+ * @param fieldVisitor the FieldVisitor the remapper must delegate to.
+ * @return the newly created remapper.
+ */
+ protected FieldVisitor createFieldRemapper(final FieldVisitor fieldVisitor) {
+ return new FieldRemapper(api, fieldVisitor, remapper);
+ }
+
+ /**
+ * Constructs a new remapper for methods. The default implementation of this method returns a new
+ * {@link MethodRemapper}.
+ *
+ * @param methodVisitor the MethodVisitor the remapper must delegate to.
+ * @return the newly created remapper.
+ */
+ protected MethodVisitor createMethodRemapper(final MethodVisitor methodVisitor) {
+ return new MethodRemapper(api, methodVisitor, remapper);
+ }
+
+ /**
+ * Constructs a new remapper for annotations. The default implementation of this method returns a
+ * new {@link AnnotationRemapper}.
+ *
+ * @param annotationVisitor the AnnotationVisitor the remapper must delegate to.
+ * @return the newly created remapper.
+ */
+ protected AnnotationVisitor createAnnotationRemapper(final AnnotationVisitor annotationVisitor) {
+ return new AnnotationRemapper(api, annotationVisitor, remapper);
+ }
+
+ /**
+ * Constructs a new remapper for modules. The default implementation of this method returns a new
+ * {@link ModuleRemapper}.
+ *
+ * @param moduleVisitor the ModuleVisitor the remapper must delegate to.
+ * @return the newly created remapper.
+ */
+ protected ModuleVisitor createModuleRemapper(final ModuleVisitor moduleVisitor) {
+ return new ModuleRemapper(api, moduleVisitor, remapper);
+ }
}