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);
+  }
 }