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:19 UTC

[32/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/TypeReference.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java
old mode 100644
new mode 100755
index d518864..96bfe33
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java
@@ -1,452 +1,436 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2013 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;
-
-/**
- * A reference to a type appearing in a class, field or method declaration, or
- * on an instruction. Such a reference designates the part of the class where
- * the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws'
- * clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable
- * declaration, etc).
- * 
- * @author Eric Bruneton
- */
-public class TypeReference {
-
-    /**
-     * The sort of type references that target a type parameter of a generic
-     * class. See {@link #getSort getSort}.
-     */
-    public final static int CLASS_TYPE_PARAMETER = 0x00;
-
-    /**
-     * The sort of type references that target a type parameter of a generic
-     * method. See {@link #getSort getSort}.
-     */
-    public final static int METHOD_TYPE_PARAMETER = 0x01;
-
-    /**
-     * The sort of type references that target the super class of a class or one
-     * of the interfaces it implements. See {@link #getSort getSort}.
-     */
-    public final static int CLASS_EXTENDS = 0x10;
-
-    /**
-     * The sort of type references that target a bound of a type parameter of a
-     * generic class. See {@link #getSort getSort}.
-     */
-    public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11;
-
-    /**
-     * The sort of type references that target a bound of a type parameter of a
-     * generic method. See {@link #getSort getSort}.
-     */
-    public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12;
-
-    /**
-     * The sort of type references that target the type of a field. See
-     * {@link #getSort getSort}.
-     */
-    public final static int FIELD = 0x13;
-
-    /**
-     * The sort of type references that target the return type of a method. See
-     * {@link #getSort getSort}.
-     */
-    public final static int METHOD_RETURN = 0x14;
-
-    /**
-     * The sort of type references that target the receiver type of a method.
-     * See {@link #getSort getSort}.
-     */
-    public final static int METHOD_RECEIVER = 0x15;
-
-    /**
-     * The sort of type references that target the type of a formal parameter of
-     * a method. See {@link #getSort getSort}.
-     */
-    public final static int METHOD_FORMAL_PARAMETER = 0x16;
-
-    /**
-     * The sort of type references that target the type of an exception declared
-     * in the throws clause of a method. See {@link #getSort getSort}.
-     */
-    public final static int THROWS = 0x17;
-
-    /**
-     * The sort of type references that target the type of a local variable in a
-     * method. See {@link #getSort getSort}.
-     */
-    public final static int LOCAL_VARIABLE = 0x40;
-
-    /**
-     * The sort of type references that target the type of a resource variable
-     * in a method. See {@link #getSort getSort}.
-     */
-    public final static int RESOURCE_VARIABLE = 0x41;
-
-    /**
-     * The sort of type references that target the type of the exception of a
-     * 'catch' clause in a method. See {@link #getSort getSort}.
-     */
-    public final static int EXCEPTION_PARAMETER = 0x42;
-
-    /**
-     * The sort of type references that target the type declared in an
-     * 'instanceof' instruction. See {@link #getSort getSort}.
-     */
-    public final static int INSTANCEOF = 0x43;
-
-    /**
-     * The sort of type references that target the type of the object created by
-     * a 'new' instruction. See {@link #getSort getSort}.
-     */
-    public final static int NEW = 0x44;
-
-    /**
-     * The sort of type references that target the receiver type of a
-     * constructor reference. See {@link #getSort getSort}.
-     */
-    public final static int CONSTRUCTOR_REFERENCE = 0x45;
-
-    /**
-     * The sort of type references that target the receiver type of a method
-     * reference. See {@link #getSort getSort}.
-     */
-    public final static int METHOD_REFERENCE = 0x46;
-
-    /**
-     * The sort of type references that target the type declared in an explicit
-     * or implicit cast instruction. See {@link #getSort getSort}.
-     */
-    public final static int CAST = 0x47;
-
-    /**
-     * The sort of type references that target a type parameter of a generic
-     * constructor in a constructor call. See {@link #getSort getSort}.
-     */
-    public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
-
-    /**
-     * The sort of type references that target a type parameter of a generic
-     * method in a method call. See {@link #getSort getSort}.
-     */
-    public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
-
-    /**
-     * The sort of type references that target a type parameter of a generic
-     * constructor in a constructor reference. See {@link #getSort getSort}.
-     */
-    public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
-
-    /**
-     * The sort of type references that target a type parameter of a generic
-     * method in a method reference. See {@link #getSort getSort}.
-     */
-    public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
-
-    /**
-     * The type reference value in Java class file format.
-     */
-    private int value;
-
-    /**
-     * Creates a new TypeReference.
-     * 
-     * @param typeRef
-     *            the int encoded value of the type reference, as received in a
-     *            visit method related to type annotations, like
-     *            visitTypeAnnotation.
-     */
-    public TypeReference(int typeRef) {
-        this.value = typeRef;
-    }
-
-    /**
-     * Returns a type reference of the given sort.
-     * 
-     * @param sort
-     *            {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
-     *            {@link #METHOD_RECEIVER METHOD_RECEIVER},
-     *            {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
-     *            {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
-     *            {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
-     *            {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or
-     *            {@link #METHOD_REFERENCE METHOD_REFERENCE}.
-     * @return a type reference of the given sort.
-     */
-    public static TypeReference newTypeReference(int sort) {
-        return new TypeReference(sort << 24);
-    }
-
-    /**
-     * Returns a reference to a type parameter of a generic class or method.
-     * 
-     * @param sort
-     *            {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
-     *            {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
-     * @param paramIndex
-     *            the type parameter index.
-     * @return a reference to the given generic class or method type parameter.
-     */
-    public static TypeReference newTypeParameterReference(int sort,
-            int paramIndex) {
-        return new TypeReference((sort << 24) | (paramIndex << 16));
-    }
-
-    /**
-     * Returns a reference to a type parameter bound of a generic class or
-     * method.
-     * 
-     * @param sort
-     *            {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
-     *            {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
-     * @param paramIndex
-     *            the type parameter index.
-     * @param boundIndex
-     *            the type bound index within the above type parameters.
-     * @return a reference to the given generic class or method type parameter
-     *         bound.
-     */
-    public static TypeReference newTypeParameterBoundReference(int sort,
-            int paramIndex, int boundIndex) {
-        return new TypeReference((sort << 24) | (paramIndex << 16)
-                | (boundIndex << 8));
-    }
-
-    /**
-     * Returns a reference to the super class or to an interface of the
-     * 'implements' clause of a class.
-     * 
-     * @param itfIndex
-     *            the index of an interface in the 'implements' clause of a
-     *            class, or -1 to reference the super class of the class.
-     * @return a reference to the given super type of a class.
-     */
-    public static TypeReference newSuperTypeReference(int itfIndex) {
-        itfIndex &= 0xFFFF;
-        return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8));
-    }
-
-    /**
-     * Returns a reference to the type of a formal parameter of a method.
-     * 
-     * @param paramIndex
-     *            the formal parameter index.
-     * 
-     * @return a reference to the type of the given method formal parameter.
-     */
-    public static TypeReference newFormalParameterReference(int paramIndex) {
-        return new TypeReference((METHOD_FORMAL_PARAMETER << 24)
-                | (paramIndex << 16));
-    }
-
-    /**
-     * Returns a reference to the type of an exception, in a 'throws' clause of
-     * a method.
-     * 
-     * @param exceptionIndex
-     *            the index of an exception in a 'throws' clause of a method.
-     * 
-     * @return a reference to the type of the given exception.
-     */
-    public static TypeReference newExceptionReference(int exceptionIndex) {
-        return new TypeReference((THROWS << 24) | (exceptionIndex << 8));
-    }
-
-    /**
-     * Returns a reference to the type of the exception declared in a 'catch'
-     * clause of a method.
-     * 
-     * @param tryCatchBlockIndex
-     *            the index of a try catch block (using the order in which they
-     *            are visited with visitTryCatchBlock).
-     * 
-     * @return a reference to the type of the given exception.
-     */
-    public static TypeReference newTryCatchReference(int tryCatchBlockIndex) {
-        return new TypeReference((EXCEPTION_PARAMETER << 24)
-                | (tryCatchBlockIndex << 8));
-    }
-
-    /**
-     * Returns a reference to the type of a type argument in a constructor or
-     * method call or reference.
-     * 
-     * @param sort
-     *            {@link #CAST CAST},
-     *            {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
-     *            CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
-     *            {@link #METHOD_INVOCATION_TYPE_ARGUMENT
-     *            METHOD_INVOCATION_TYPE_ARGUMENT},
-     *            {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
-     *            CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
-     *            {@link #METHOD_REFERENCE_TYPE_ARGUMENT
-     *            METHOD_REFERENCE_TYPE_ARGUMENT}.
-     * @param argIndex
-     *            the type argument index.
-     * 
-     * @return a reference to the type of the given type argument.
-     */
-    public static TypeReference newTypeArgumentReference(int sort, int argIndex) {
-        return new TypeReference((sort << 24) | argIndex);
-    }
-
-    /**
-     * Returns the sort of this type reference.
-     * 
-     * @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
-     *         {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
-     *         {@link #CLASS_EXTENDS CLASS_EXTENDS},
-     *         {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND},
-     *         {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND},
-     *         {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
-     *         {@link #METHOD_RECEIVER METHOD_RECEIVER},
-     *         {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER},
-     *         {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
-     *         {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
-     *         {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER},
-     *         {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
-     *         {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE},
-     *         {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST},
-     *         {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
-     *         CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
-     *         {@link #METHOD_INVOCATION_TYPE_ARGUMENT
-     *         METHOD_INVOCATION_TYPE_ARGUMENT},
-     *         {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
-     *         CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
-     *         {@link #METHOD_REFERENCE_TYPE_ARGUMENT
-     *         METHOD_REFERENCE_TYPE_ARGUMENT}.
-     */
-    public int getSort() {
-        return value >>> 24;
-    }
-
-    /**
-     * Returns the index of the type parameter referenced by this type
-     * reference. This method must only be used for type references whose sort
-     * is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
-     * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
-     * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
-     * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
-     * 
-     * @return a type parameter index.
-     */
-    public int getTypeParameterIndex() {
-        return (value & 0x00FF0000) >> 16;
-    }
-
-    /**
-     * Returns the index of the type parameter bound, within the type parameter
-     * {@link #getTypeParameterIndex}, referenced by this type reference. This
-     * method must only be used for type references whose sort is
-     * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
-     * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
-     * 
-     * @return a type parameter bound index.
-     */
-    public int getTypeParameterBoundIndex() {
-        return (value & 0x0000FF00) >> 8;
-    }
-
-    /**
-     * Returns the index of the "super type" of a class that is referenced by
-     * this type reference. This method must only be used for type references
-     * whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}.
-     * 
-     * @return the index of an interface in the 'implements' clause of a class,
-     *         or -1 if this type reference references the type of the super
-     *         class.
-     */
-    public int getSuperTypeIndex() {
-        return (short) ((value & 0x00FFFF00) >> 8);
-    }
-
-    /**
-     * Returns the index of the formal parameter whose type is referenced by
-     * this type reference. This method must only be used for type references
-     * whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}.
-     * 
-     * @return a formal parameter index.
-     */
-    public int getFormalParameterIndex() {
-        return (value & 0x00FF0000) >> 16;
-    }
-
-    /**
-     * Returns the index of the exception, in a 'throws' clause of a method,
-     * whose type is referenced by this type reference. This method must only be
-     * used for type references whose sort is {@link #THROWS THROWS}.
-     * 
-     * @return the index of an exception in the 'throws' clause of a method.
-     */
-    public int getExceptionIndex() {
-        return (value & 0x00FFFF00) >> 8;
-    }
-
-    /**
-     * Returns the index of the try catch block (using the order in which they
-     * are visited with visitTryCatchBlock), whose 'catch' type is referenced by
-     * this type reference. This method must only be used for type references
-     * whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} .
-     * 
-     * @return the index of an exception in the 'throws' clause of a method.
-     */
-    public int getTryCatchBlockIndex() {
-        return (value & 0x00FFFF00) >> 8;
-    }
-
-    /**
-     * Returns the index of the type argument referenced by this type reference.
-     * This method must only be used for type references whose sort is
-     * {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
-     * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
-     * {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT},
-     * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
-     * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
-     * {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}.
-     * 
-     * @return a type parameter index.
-     */
-    public int getTypeArgumentIndex() {
-        return value & 0xFF;
-    }
-
-    /**
-     * Returns the int encoded value of this type reference, suitable for use in
-     * visit methods related to type annotations, like visitTypeAnnotation.
-     * 
-     * @return the int encoded value of this type reference.
-     */
-    public int getValue() {
-        return value;
-    }
-}
+// 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;
+
+/**
+ * A reference to a type appearing in a class, field or method declaration, or on an instruction.
+ * Such a reference designates the part of the class where the referenced type is appearing (e.g. an
+ * 'extends', 'implements' or 'throws' clause, a 'new' instruction, a 'catch' clause, a type cast, a
+ * local variable declaration, etc).
+ *
+ * @author Eric Bruneton
+ */
+public class TypeReference {
+
+  /**
+   * The sort of type references that target a type parameter of a generic class. See {@link
+   * #getSort}.
+   */
+  public static final int CLASS_TYPE_PARAMETER = 0x00;
+
+  /**
+   * The sort of type references that target a type parameter of a generic method. See {@link
+   * #getSort}.
+   */
+  public static final int METHOD_TYPE_PARAMETER = 0x01;
+
+  /**
+   * The sort of type references that target the super class of a class or one of the interfaces it
+   * implements. See {@link #getSort}.
+   */
+  public static final int CLASS_EXTENDS = 0x10;
+
+  /**
+   * The sort of type references that target a bound of a type parameter of a generic class. See
+   * {@link #getSort}.
+   */
+  public static final int CLASS_TYPE_PARAMETER_BOUND = 0x11;
+
+  /**
+   * The sort of type references that target a bound of a type parameter of a generic method. See
+   * {@link #getSort}.
+   */
+  public static final int METHOD_TYPE_PARAMETER_BOUND = 0x12;
+
+  /** The sort of type references that target the type of a field. See {@link #getSort}. */
+  public static final int FIELD = 0x13;
+
+  /** The sort of type references that target the return type of a method. See {@link #getSort}. */
+  public static final int METHOD_RETURN = 0x14;
+
+  /**
+   * The sort of type references that target the receiver type of a method. See {@link #getSort}.
+   */
+  public static final int METHOD_RECEIVER = 0x15;
+
+  /**
+   * The sort of type references that target the type of a formal parameter of a method. See {@link
+   * #getSort}.
+   */
+  public static final int METHOD_FORMAL_PARAMETER = 0x16;
+
+  /**
+   * The sort of type references that target the type of an exception declared in the throws clause
+   * of a method. See {@link #getSort}.
+   */
+  public static final int THROWS = 0x17;
+
+  /**
+   * The sort of type references that target the type of a local variable in a method. See {@link
+   * #getSort}.
+   */
+  public static final int LOCAL_VARIABLE = 0x40;
+
+  /**
+   * The sort of type references that target the type of a resource variable in a method. See {@link
+   * #getSort}.
+   */
+  public static final int RESOURCE_VARIABLE = 0x41;
+
+  /**
+   * The sort of type references that target the type of the exception of a 'catch' clause in a
+   * method. See {@link #getSort}.
+   */
+  public static final int EXCEPTION_PARAMETER = 0x42;
+
+  /**
+   * The sort of type references that target the type declared in an 'instanceof' instruction. See
+   * {@link #getSort}.
+   */
+  public static final int INSTANCEOF = 0x43;
+
+  /**
+   * The sort of type references that target the type of the object created by a 'new' instruction.
+   * See {@link #getSort}.
+   */
+  public static final int NEW = 0x44;
+
+  /**
+   * The sort of type references that target the receiver type of a constructor reference. See
+   * {@link #getSort}.
+   */
+  public static final int CONSTRUCTOR_REFERENCE = 0x45;
+
+  /**
+   * The sort of type references that target the receiver type of a method reference. See {@link
+   * #getSort}.
+   */
+  public static final int METHOD_REFERENCE = 0x46;
+
+  /**
+   * The sort of type references that target the type declared in an explicit or implicit cast
+   * instruction. See {@link #getSort}.
+   */
+  public static final int CAST = 0x47;
+
+  /**
+   * The sort of type references that target a type parameter of a generic constructor in a
+   * constructor call. See {@link #getSort}.
+   */
+  public static final int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
+
+  /**
+   * The sort of type references that target a type parameter of a generic method in a method call.
+   * See {@link #getSort}.
+   */
+  public static final int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
+
+  /**
+   * The sort of type references that target a type parameter of a generic constructor in a
+   * constructor reference. See {@link #getSort}.
+   */
+  public static final int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
+
+  /**
+   * The sort of type references that target a type parameter of a generic method in a method
+   * reference. See {@link #getSort}.
+   */
+  public static final int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
+
+  /**
+   * The target_type and target_info structures - as defined in the Java Virtual Machine
+   * Specification (JVMS) - corresponding to this type reference. target_type uses one byte, and all
+   * the target_info union fields use up to 3 bytes (except localvar_target, handled with the
+   * specific method {@link MethodVisitor#visitLocalVariableAnnotation}). Thus, both structures can
+   * be stored in an int.
+   *
+   * <p>This int field stores target_type (called the TypeReference 'sort' in the public API of this
+   * class) in its most significant byte, followed by the target_info fields. Depending on
+   * target_type, 1, 2 or even 3 least significant bytes of this field are unused. target_info
+   * fields which reference bytecode offsets are set to 0 (these offsets are ignored in ClassReader,
+   * and recomputed in MethodWriter).
+   *
+   * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20">JVMS
+   *     4.7.20</a>
+   * @see <a
+   *     href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20.1">JVMS
+   *     4.7.20.1</a>
+   */
+  private final int targetTypeAndInfo;
+
+  /**
+   * Constructs a new TypeReference.
+   *
+   * @param typeRef the int encoded value of the type reference, as received in a visit method
+   *     related to type annotations, such as {@link ClassVisitor#visitTypeAnnotation}.
+   */
+  public TypeReference(final int typeRef) {
+    this.targetTypeAndInfo = typeRef;
+  }
+
+  /**
+   * Returns a type reference of the given sort.
+   *
+   * @param sort one of {@link #FIELD}, {@link #METHOD_RETURN}, {@link #METHOD_RECEIVER}, {@link
+   *     #LOCAL_VARIABLE}, {@link #RESOURCE_VARIABLE}, {@link #INSTANCEOF}, {@link #NEW}, {@link
+   *     #CONSTRUCTOR_REFERENCE}, or {@link #METHOD_REFERENCE}.
+   * @return a type reference of the given sort.
+   */
+  public static TypeReference newTypeReference(final int sort) {
+    return new TypeReference(sort << 24);
+  }
+
+  /**
+   * Returns a reference to a type parameter of a generic class or method.
+   *
+   * @param sort one of {@link #CLASS_TYPE_PARAMETER} or {@link #METHOD_TYPE_PARAMETER}.
+   * @param paramIndex the type parameter index.
+   * @return a reference to the given generic class or method type parameter.
+   */
+  public static TypeReference newTypeParameterReference(final int sort, final int paramIndex) {
+    return new TypeReference((sort << 24) | (paramIndex << 16));
+  }
+
+  /**
+   * Returns a reference to a type parameter bound of a generic class or method.
+   *
+   * @param sort one of {@link #CLASS_TYPE_PARAMETER} or {@link #METHOD_TYPE_PARAMETER}.
+   * @param paramIndex the type parameter index.
+   * @param boundIndex the type bound index within the above type parameters.
+   * @return a reference to the given generic class or method type parameter bound.
+   */
+  public static TypeReference newTypeParameterBoundReference(
+      final int sort, final int paramIndex, final int boundIndex) {
+    return new TypeReference((sort << 24) | (paramIndex << 16) | (boundIndex << 8));
+  }
+
+  /**
+   * Returns a reference to the super class or to an interface of the 'implements' clause of a
+   * class.
+   *
+   * @param itfIndex the index of an interface in the 'implements' clause of a class, or -1 to
+   *     reference the super class of the class.
+   * @return a reference to the given super type of a class.
+   */
+  public static TypeReference newSuperTypeReference(final int itfIndex) {
+    return new TypeReference((CLASS_EXTENDS << 24) | ((itfIndex & 0xFFFF) << 8));
+  }
+
+  /**
+   * Returns a reference to the type of a formal parameter of a method.
+   *
+   * @param paramIndex the formal parameter index.
+   * @return a reference to the type of the given method formal parameter.
+   */
+  public static TypeReference newFormalParameterReference(final int paramIndex) {
+    return new TypeReference((METHOD_FORMAL_PARAMETER << 24) | (paramIndex << 16));
+  }
+
+  /**
+   * Returns a reference to the type of an exception, in a 'throws' clause of a method.
+   *
+   * @param exceptionIndex the index of an exception in a 'throws' clause of a method.
+   * @return a reference to the type of the given exception.
+   */
+  public static TypeReference newExceptionReference(final int exceptionIndex) {
+    return new TypeReference((THROWS << 24) | (exceptionIndex << 8));
+  }
+
+  /**
+   * Returns a reference to the type of the exception declared in a 'catch' clause of a method.
+   *
+   * @param tryCatchBlockIndex the index of a try catch block (using the order in which they are
+   *     visited with visitTryCatchBlock).
+   * @return a reference to the type of the given exception.
+   */
+  public static TypeReference newTryCatchReference(final int tryCatchBlockIndex) {
+    return new TypeReference((EXCEPTION_PARAMETER << 24) | (tryCatchBlockIndex << 8));
+  }
+
+  /**
+   * Returns a reference to the type of a type argument in a constructor or method call or
+   * reference.
+   *
+   * @param sort one of {@link #CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link
+   *     #METHOD_INVOCATION_TYPE_ARGUMENT}, {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link
+   *     #METHOD_REFERENCE_TYPE_ARGUMENT}.
+   * @param argIndex the type argument index.
+   * @return a reference to the type of the given type argument.
+   */
+  public static TypeReference newTypeArgumentReference(final int sort, final int argIndex) {
+    return new TypeReference((sort << 24) | argIndex);
+  }
+
+  /**
+   * Returns the sort of this type reference.
+   *
+   * @return one of {@link #CLASS_TYPE_PARAMETER}, {@link #METHOD_TYPE_PARAMETER}, {@link
+   *     #CLASS_EXTENDS}, {@link #CLASS_TYPE_PARAMETER_BOUND}, {@link #METHOD_TYPE_PARAMETER_BOUND},
+   *     {@link #FIELD}, {@link #METHOD_RETURN}, {@link #METHOD_RECEIVER}, {@link
+   *     #METHOD_FORMAL_PARAMETER}, {@link #THROWS}, {@link #LOCAL_VARIABLE}, {@link
+   *     #RESOURCE_VARIABLE}, {@link #EXCEPTION_PARAMETER}, {@link #INSTANCEOF}, {@link #NEW},
+   *     {@link #CONSTRUCTOR_REFERENCE}, {@link #METHOD_REFERENCE}, {@link #CAST}, {@link
+   *     #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link #METHOD_INVOCATION_TYPE_ARGUMENT}, {@link
+   *     #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link #METHOD_REFERENCE_TYPE_ARGUMENT}.
+   */
+  public int getSort() {
+    return targetTypeAndInfo >>> 24;
+  }
+
+  /**
+   * Returns the index of the type parameter referenced by this type reference. This method must
+   * only be used for type references whose sort is {@link #CLASS_TYPE_PARAMETER}, {@link
+   * #METHOD_TYPE_PARAMETER}, {@link #CLASS_TYPE_PARAMETER_BOUND} or {@link
+   * #METHOD_TYPE_PARAMETER_BOUND}.
+   *
+   * @return a type parameter index.
+   */
+  public int getTypeParameterIndex() {
+    return (targetTypeAndInfo & 0x00FF0000) >> 16;
+  }
+
+  /**
+   * Returns the index of the type parameter bound, within the type parameter {@link
+   * #getTypeParameterIndex}, referenced by this type reference. This method must only be used for
+   * type references whose sort is {@link #CLASS_TYPE_PARAMETER_BOUND} or {@link
+   * #METHOD_TYPE_PARAMETER_BOUND}.
+   *
+   * @return a type parameter bound index.
+   */
+  public int getTypeParameterBoundIndex() {
+    return (targetTypeAndInfo & 0x0000FF00) >> 8;
+  }
+
+  /**
+   * Returns the index of the "super type" of a class that is referenced by this type reference.
+   * This method must only be used for type references whose sort is {@link #CLASS_EXTENDS}.
+   *
+   * @return the index of an interface in the 'implements' clause of a class, or -1 if this type
+   *     reference references the type of the super class.
+   */
+  public int getSuperTypeIndex() {
+    return (short) ((targetTypeAndInfo & 0x00FFFF00) >> 8);
+  }
+
+  /**
+   * Returns the index of the formal parameter whose type is referenced by this type reference. This
+   * method must only be used for type references whose sort is {@link #METHOD_FORMAL_PARAMETER}.
+   *
+   * @return a formal parameter index.
+   */
+  public int getFormalParameterIndex() {
+    return (targetTypeAndInfo & 0x00FF0000) >> 16;
+  }
+
+  /**
+   * Returns the index of the exception, in a 'throws' clause of a method, whose type is referenced
+   * by this type reference. This method must only be used for type references whose sort is {@link
+   * #THROWS}.
+   *
+   * @return the index of an exception in the 'throws' clause of a method.
+   */
+  public int getExceptionIndex() {
+    return (targetTypeAndInfo & 0x00FFFF00) >> 8;
+  }
+
+  /**
+   * Returns the index of the try catch block (using the order in which they are visited with
+   * visitTryCatchBlock), whose 'catch' type is referenced by this type reference. This method must
+   * only be used for type references whose sort is {@link #EXCEPTION_PARAMETER} .
+   *
+   * @return the index of an exception in the 'throws' clause of a method.
+   */
+  public int getTryCatchBlockIndex() {
+    return (targetTypeAndInfo & 0x00FFFF00) >> 8;
+  }
+
+  /**
+   * Returns the index of the type argument referenced by this type reference. This method must only
+   * be used for type references whose sort is {@link #CAST}, {@link
+   * #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link #METHOD_INVOCATION_TYPE_ARGUMENT}, {@link
+   * #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link #METHOD_REFERENCE_TYPE_ARGUMENT}.
+   *
+   * @return a type parameter index.
+   */
+  public int getTypeArgumentIndex() {
+    return targetTypeAndInfo & 0xFF;
+  }
+
+  /**
+   * Returns the int encoded value of this type reference, suitable for use in visit methods related
+   * to type annotations, like visitTypeAnnotation.
+   *
+   * @return the int encoded value of this type reference.
+   */
+  public int getValue() {
+    return targetTypeAndInfo;
+  }
+
+  /**
+   * Puts the given target_type and target_info JVMS structures into the given ByteVector.
+   *
+   * @param targetTypeAndInfo a target_type and a target_info structures encoded as in {@link
+   *     #targetTypeAndInfo}. LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported.
+   * @param output where the type reference must be put.
+   */
+  static void putTarget(final int targetTypeAndInfo, final ByteVector output) {
+    switch (targetTypeAndInfo >>> 24) {
+      case CLASS_TYPE_PARAMETER:
+      case METHOD_TYPE_PARAMETER:
+      case METHOD_FORMAL_PARAMETER:
+        output.putShort(targetTypeAndInfo >>> 16);
+        break;
+      case FIELD:
+      case METHOD_RETURN:
+      case METHOD_RECEIVER:
+        output.putByte(targetTypeAndInfo >>> 24);
+        break;
+      case CAST:
+      case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
+      case METHOD_INVOCATION_TYPE_ARGUMENT:
+      case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
+      case METHOD_REFERENCE_TYPE_ARGUMENT:
+        output.putInt(targetTypeAndInfo);
+        break;
+      case CLASS_EXTENDS:
+      case CLASS_TYPE_PARAMETER_BOUND:
+      case METHOD_TYPE_PARAMETER_BOUND:
+      case THROWS:
+      case EXCEPTION_PARAMETER:
+      case INSTANCEOF:
+      case NEW:
+      case CONSTRUCTOR_REFERENCE:
+      case METHOD_REFERENCE:
+        output.put12(targetTypeAndInfo >>> 24, (targetTypeAndInfo & 0xFFFF00) >> 8);
+        break;
+      default:
+        throw new IllegalArgumentException();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java
old mode 100644
new mode 100755
index a0f6880..96e0c48
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.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,606 +39,621 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
 import org.apache.tapestry5.internal.plastic.asm.Type;
 
 /**
- * A {@link org.objectweb.asm.MethodVisitor} to insert before, after and around
- * advices in methods and constructors.
- * <p>
- * The behavior for constructors is like this:
- * <ol>
- * 
- * <li>as long as the INVOKESPECIAL for the object initialization has not been
- * reached, every bytecode instruction is dispatched in the ctor code visitor</li>
- * 
- * <li>when this one is reached, it is only added in the ctor code visitor and a
- * JP invoke is added</li>
- * 
- * <li>after that, only the other code visitor receives the instructions</li>
- * 
- * </ol>
- * 
+ * A {@link MethodVisitor} to insert before, after and around advices in methods and constructors.
+ * For constructors, the code keeps track of the elements on the stack in order to detect when the
+ * super class constructor is called (note that there can be multiple such calls in different
+ * branches). {@code onMethodEnter} is called after each super class constructor call, because the
+ * object cannot be used before it is properly initialized.
+ *
  * @author Eugene Kuleshov
  * @author Eric Bruneton
  */
 public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes {
 
-    private static final Object THIS = new Object();
-
-    private static final Object OTHER = new Object();
-
-    protected int methodAccess;
-
-    protected String methodDesc;
-
-    private boolean constructor;
-
-    private boolean superInitialized;
-
-    private List<Object> stackFrame;
-
-    private Map<Label, List<Object>> branches;
-
-    /**
-     * Creates a new {@link AdviceAdapter}.
-     * 
-     * @param api
-     *            the ASM API version implemented by this visitor. Must be one
-     *            of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
-     * @param mv
-     *            the method visitor to which this adapter delegates calls.
-     * @param access
-     *            the method's access flags (see {@link Opcodes}).
-     * @param name
-     *            the method's name.
-     * @param desc
-     *            the method's descriptor (see {@link Type Type}).
-     */
-    protected AdviceAdapter(final int api, final MethodVisitor mv,
-            final int access, final String name, final String desc) {
-        super(api, mv, access, name, desc);
-        methodAccess = access;
-        methodDesc = desc;
-        constructor = "<init>".equals(name);
-    }
-
-    @Override
-    public void visitCode() {
-        mv.visitCode();
-        if (constructor) {
-            stackFrame = new ArrayList<Object>();
-            branches = new HashMap<Label, List<Object>>();
-        } else {
-            superInitialized = true;
-            onMethodEnter();
-        }
-    }
-
-    @Override
-    public void visitLabel(final Label label) {
-        mv.visitLabel(label);
-        if (constructor && branches != null) {
-            List<Object> frame = branches.get(label);
-            if (frame != null) {
-                stackFrame = frame;
-                branches.remove(label);
-            }
-        }
+  /** The "uninitialized this" value. */
+  private static final Object UNINITIALIZED_THIS = new Object();
+
+  /** Any value other than "uninitialized this". */
+  private static final Object OTHER = new Object();
+
+  /** Prefix of the error message when invalid opcodes are found. */
+  private static final String INVALID_OPCODE = "Invalid opcode ";
+
+  /** The access flags of the visited method. */
+  protected int methodAccess;
+
+  /** The descriptor of the visited method. */
+  protected String methodDesc;
+
+  /** Whether the visited method is a constructor. */
+  private final boolean isConstructor;
+
+  /**
+   * Whether the super class constructor has been called (if the visited method is a constructor),
+   * at the current instruction. There can be multiple call sites to the super constructor (e.g. for
+   * Java code such as {@code super(expr ? value1 : value2);}), in different branches. When scanning
+   * the bytecode linearly, we can move from one branch where the super constructor has been called
+   * to another where it has not been called yet. Therefore, this value can change from false to
+   * true, and vice-versa.
+   */
+  private boolean superClassConstructorCalled;
+
+  /**
+   * The values on the current execution stack frame (long and double are represented by two
+   * elements). Each value is either {@link #UNINITIALIZED_THIS} (for the uninitialized this value),
+   * or {@link #OTHER} (for any other value). This field is only maintained for constructors, in
+   * branches where the super class constructor has not been called yet.
+   */
+  private List<Object> stackFrame;
+
+  /**
+   * The stack map frames corresponding to the labels of the forward jumps made *before* the super
+   * class constructor has been called (note that the Java Virtual Machine forbids backward jumps
+   * before the super class constructor is called). Note that by definition (cf. the 'before'), when
+   * we reach a label from this map, {@link #superClassConstructorCalled} must be reset to false.
+   * This field is only maintained for constructors.
+   */
+  private Map<Label, List<Object>> forwardJumpStackFrames;
+
+  /**
+   * Constructs a new {@link AdviceAdapter}.
+   *
+   * @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 methodVisitor the method visitor to which this adapter delegates calls.
+   * @param access the method's access flags (see {@link Opcodes}).
+   * @param name the method's name.
+   * @param descriptor the method's descriptor (see {@link Type Type}).
+   */
+  protected AdviceAdapter(
+      final int api,
+      final MethodVisitor methodVisitor,
+      final int access,
+      final String name,
+      final String descriptor) {
+    super(api, methodVisitor, access, name, descriptor);
+    methodAccess = access;
+    methodDesc = descriptor;
+    isConstructor = "<init>".equals(name);
+  }
+
+  @Override
+  public void visitCode() {
+    super.visitCode();
+    if (isConstructor) {
+      stackFrame = new ArrayList<Object>();
+      forwardJumpStackFrames = new HashMap<Label, List<Object>>();
+    } else {
+      onMethodEnter();
     }
-
-    @Override
-    public void visitInsn(final int opcode) {
-        if (constructor) {
-            int s;
-            switch (opcode) {
-            case RETURN: // empty stack
-                onMethodExit(opcode);
-                break;
-            case IRETURN: // 1 before n/a after
-            case FRETURN: // 1 before n/a after
-            case ARETURN: // 1 before n/a after
-            case ATHROW: // 1 before n/a after
-                popValue();
-                onMethodExit(opcode);
-                break;
-            case LRETURN: // 2 before n/a after
-            case DRETURN: // 2 before n/a after
-                popValue();
-                popValue();
-                onMethodExit(opcode);
-                break;
-            case NOP:
-            case LALOAD: // remove 2 add 2
-            case DALOAD: // remove 2 add 2
-            case LNEG:
-            case DNEG:
-            case FNEG:
-            case INEG:
-            case L2D:
-            case D2L:
-            case F2I:
-            case I2B:
-            case I2C:
-            case I2S:
-            case I2F:
-            case ARRAYLENGTH:
-                break;
-            case ACONST_NULL:
-            case ICONST_M1:
-            case ICONST_0:
-            case ICONST_1:
-            case ICONST_2:
-            case ICONST_3:
-            case ICONST_4:
-            case ICONST_5:
-            case FCONST_0:
-            case FCONST_1:
-            case FCONST_2:
-            case F2L: // 1 before 2 after
-            case F2D:
-            case I2L:
-            case I2D:
-                pushValue(OTHER);
-                break;
-            case LCONST_0:
-            case LCONST_1:
-            case DCONST_0:
-            case DCONST_1:
-                pushValue(OTHER);
-                pushValue(OTHER);
-                break;
-            case IALOAD: // remove 2 add 1
-            case FALOAD: // remove 2 add 1
-            case AALOAD: // remove 2 add 1
-            case BALOAD: // remove 2 add 1
-            case CALOAD: // remove 2 add 1
-            case SALOAD: // remove 2 add 1
-            case POP:
-            case IADD:
-            case FADD:
-            case ISUB:
-            case LSHL: // 3 before 2 after
-            case LSHR: // 3 before 2 after
-            case LUSHR: // 3 before 2 after
-            case L2I: // 2 before 1 after
-            case L2F: // 2 before 1 after
-            case D2I: // 2 before 1 after
-            case D2F: // 2 before 1 after
-            case FSUB:
-            case FMUL:
-            case FDIV:
-            case FREM:
-            case FCMPL: // 2 before 1 after
-            case FCMPG: // 2 before 1 after
-            case IMUL:
-            case IDIV:
-            case IREM:
-            case ISHL:
-            case ISHR:
-            case IUSHR:
-            case IAND:
-            case IOR:
-            case IXOR:
-            case MONITORENTER:
-            case MONITOREXIT:
-                popValue();
-                break;
-            case POP2:
-            case LSUB:
-            case LMUL:
-            case LDIV:
-            case LREM:
-            case LADD:
-            case LAND:
-            case LOR:
-            case LXOR:
-            case DADD:
-            case DMUL:
-            case DSUB:
-            case DDIV:
-            case DREM:
-                popValue();
-                popValue();
-                break;
-            case IASTORE:
-            case FASTORE:
-            case AASTORE:
-            case BASTORE:
-            case CASTORE:
-            case SASTORE:
-            case LCMP: // 4 before 1 after
-            case DCMPL:
-            case DCMPG:
-                popValue();
-                popValue();
-                popValue();
-                break;
-            case LASTORE:
-            case DASTORE:
-                popValue();
-                popValue();
-                popValue();
-                popValue();
-                break;
-            case DUP:
-                pushValue(peekValue());
-                break;
-            case DUP_X1:
-                s = stackFrame.size();
-                stackFrame.add(s - 2, stackFrame.get(s - 1));
-                break;
-            case DUP_X2:
-                s = stackFrame.size();
-                stackFrame.add(s - 3, stackFrame.get(s - 1));
-                break;
-            case DUP2:
-                s = stackFrame.size();
-                stackFrame.add(s - 2, stackFrame.get(s - 1));
-                stackFrame.add(s - 2, stackFrame.get(s - 1));
-                break;
-            case DUP2_X1:
-                s = stackFrame.size();
-                stackFrame.add(s - 3, stackFrame.get(s - 1));
-                stackFrame.add(s - 3, stackFrame.get(s - 1));
-                break;
-            case DUP2_X2:
-                s = stackFrame.size();
-                stackFrame.add(s - 4, stackFrame.get(s - 1));
-                stackFrame.add(s - 4, stackFrame.get(s - 1));
-                break;
-            case SWAP:
-                s = stackFrame.size();
-                stackFrame.add(s - 2, stackFrame.get(s - 1));
-                stackFrame.remove(s);
-                break;
-            }
-        } else {
-            switch (opcode) {
-            case RETURN:
-            case IRETURN:
-            case FRETURN:
-            case ARETURN:
-            case LRETURN:
-            case DRETURN:
-            case ATHROW:
-                onMethodExit(opcode);
-                break;
-            }
-        }
-        mv.visitInsn(opcode);
+  }
+
+  @Override
+  public void visitLabel(final Label label) {
+    super.visitLabel(label);
+    if (isConstructor && forwardJumpStackFrames != null) {
+      List<Object> labelStackFrame = forwardJumpStackFrames.get(label);
+      if (labelStackFrame != null) {
+        stackFrame = labelStackFrame;
+        superClassConstructorCalled = false;
+        forwardJumpStackFrames.remove(label);
+      }
     }
-
-    @Override
-    public void visitVarInsn(final int opcode, final int var) {
-        super.visitVarInsn(opcode, var);
-        if (constructor) {
-            switch (opcode) {
-            case ILOAD:
-            case FLOAD:
-                pushValue(OTHER);
-                break;
-            case LLOAD:
-            case DLOAD:
-                pushValue(OTHER);
-                pushValue(OTHER);
-                break;
-            case ALOAD:
-                pushValue(var == 0 ? THIS : OTHER);
-                break;
-            case ASTORE:
-            case ISTORE:
-            case FSTORE:
-                popValue();
-                break;
-            case LSTORE:
-            case DSTORE:
-                popValue();
-                popValue();
-                break;
-            }
-        }
+  }
+
+  @Override
+  public void visitInsn(final int opcode) {
+    if (isConstructor && !superClassConstructorCalled) {
+      int stackSize;
+      switch (opcode) {
+        case IRETURN:
+        case FRETURN:
+        case ARETURN:
+        case LRETURN:
+        case DRETURN:
+          throw new IllegalArgumentException("Invalid return in constructor");
+        case RETURN: // empty stack
+          onMethodExit(opcode);
+          break;
+        case ATHROW: // 1 before n/a after
+          popValue();
+          onMethodExit(opcode);
+          break;
+        case NOP:
+        case LALOAD: // remove 2 add 2
+        case DALOAD: // remove 2 add 2
+        case LNEG:
+        case DNEG:
+        case FNEG:
+        case INEG:
+        case L2D:
+        case D2L:
+        case F2I:
+        case I2B:
+        case I2C:
+        case I2S:
+        case I2F:
+        case ARRAYLENGTH:
+          break;
+        case ACONST_NULL:
+        case ICONST_M1:
+        case ICONST_0:
+        case ICONST_1:
+        case ICONST_2:
+        case ICONST_3:
+        case ICONST_4:
+        case ICONST_5:
+        case FCONST_0:
+        case FCONST_1:
+        case FCONST_2:
+        case F2L: // 1 before 2 after
+        case F2D:
+        case I2L:
+        case I2D:
+          pushValue(OTHER);
+          break;
+        case LCONST_0:
+        case LCONST_1:
+        case DCONST_0:
+        case DCONST_1:
+          pushValue(OTHER);
+          pushValue(OTHER);
+          break;
+        case IALOAD: // remove 2 add 1
+        case FALOAD: // remove 2 add 1
+        case AALOAD: // remove 2 add 1
+        case BALOAD: // remove 2 add 1
+        case CALOAD: // remove 2 add 1
+        case SALOAD: // remove 2 add 1
+        case POP:
+        case IADD:
+        case FADD:
+        case ISUB:
+        case LSHL: // 3 before 2 after
+        case LSHR: // 3 before 2 after
+        case LUSHR: // 3 before 2 after
+        case L2I: // 2 before 1 after
+        case L2F: // 2 before 1 after
+        case D2I: // 2 before 1 after
+        case D2F: // 2 before 1 after
+        case FSUB:
+        case FMUL:
+        case FDIV:
+        case FREM:
+        case FCMPL: // 2 before 1 after
+        case FCMPG: // 2 before 1 after
+        case IMUL:
+        case IDIV:
+        case IREM:
+        case ISHL:
+        case ISHR:
+        case IUSHR:
+        case IAND:
+        case IOR:
+        case IXOR:
+        case MONITORENTER:
+        case MONITOREXIT:
+          popValue();
+          break;
+        case POP2:
+        case LSUB:
+        case LMUL:
+        case LDIV:
+        case LREM:
+        case LADD:
+        case LAND:
+        case LOR:
+        case LXOR:
+        case DADD:
+        case DMUL:
+        case DSUB:
+        case DDIV:
+        case DREM:
+          popValue();
+          popValue();
+          break;
+        case IASTORE:
+        case FASTORE:
+        case AASTORE:
+        case BASTORE:
+        case CASTORE:
+        case SASTORE:
+        case LCMP: // 4 before 1 after
+        case DCMPL:
+        case DCMPG:
+          popValue();
+          popValue();
+          popValue();
+          break;
+        case LASTORE:
+        case DASTORE:
+          popValue();
+          popValue();
+          popValue();
+          popValue();
+          break;
+        case DUP:
+          pushValue(peekValue());
+          break;
+        case DUP_X1:
+          stackSize = stackFrame.size();
+          stackFrame.add(stackSize - 2, stackFrame.get(stackSize - 1));
+          break;
+        case DUP_X2:
+          stackSize = stackFrame.size();
+          stackFrame.add(stackSize - 3, stackFrame.get(stackSize - 1));
+          break;
+        case DUP2:
+          stackSize = stackFrame.size();
+          stackFrame.add(stackSize - 2, stackFrame.get(stackSize - 1));
+          stackFrame.add(stackSize - 2, stackFrame.get(stackSize - 1));
+          break;
+        case DUP2_X1:
+          stackSize = stackFrame.size();
+          stackFrame.add(stackSize - 3, stackFrame.get(stackSize - 1));
+          stackFrame.add(stackSize - 3, stackFrame.get(stackSize - 1));
+          break;
+        case DUP2_X2:
+          stackSize = stackFrame.size();
+          stackFrame.add(stackSize - 4, stackFrame.get(stackSize - 1));
+          stackFrame.add(stackSize - 4, stackFrame.get(stackSize - 1));
+          break;
+        case SWAP:
+          stackSize = stackFrame.size();
+          stackFrame.add(stackSize - 2, stackFrame.get(stackSize - 1));
+          stackFrame.remove(stackSize);
+          break;
+        default:
+          throw new IllegalArgumentException(INVALID_OPCODE + opcode);
+      }
+    } else {
+      switch (opcode) {
+        case RETURN:
+        case IRETURN:
+        case FRETURN:
+        case ARETURN:
+        case LRETURN:
+        case DRETURN:
+        case ATHROW:
+          onMethodExit(opcode);
+          break;
+        default:
+          break;
+      }
     }
-
-    @Override
-    public void visitFieldInsn(final int opcode, final String owner,
-            final String name, final String desc) {
-        mv.visitFieldInsn(opcode, owner, name, desc);
-        if (constructor) {
-            char c = desc.charAt(0);
-            boolean longOrDouble = c == 'J' || c == 'D';
-            switch (opcode) {
-            case GETSTATIC:
-                pushValue(OTHER);
-                if (longOrDouble) {
-                    pushValue(OTHER);
-                }
-                break;
-            case PUTSTATIC:
-                popValue();
-                if (longOrDouble) {
-                    popValue();
-                }
-                break;
-            case PUTFIELD:
-                popValue();
-                popValue();
-                if (longOrDouble) {
-                    popValue();
-                }
-                break;
-            // case GETFIELD:
-            default:
-                if (longOrDouble) {
-                    pushValue(OTHER);
-                }
-            }
-        }
+    super.visitInsn(opcode);
+  }
+
+  @Override
+  public void visitVarInsn(final int opcode, final int var) {
+    super.visitVarInsn(opcode, var);
+    if (isConstructor && !superClassConstructorCalled) {
+      switch (opcode) {
+        case ILOAD:
+        case FLOAD:
+          pushValue(OTHER);
+          break;
+        case LLOAD:
+        case DLOAD:
+          pushValue(OTHER);
+          pushValue(OTHER);
+          break;
+        case ALOAD:
+          pushValue(var == 0 ? UNINITIALIZED_THIS : OTHER);
+          break;
+        case ASTORE:
+        case ISTORE:
+        case FSTORE:
+          popValue();
+          break;
+        case LSTORE:
+        case DSTORE:
+          popValue();
+          popValue();
+          break;
+        default:
+          throw new IllegalArgumentException(INVALID_OPCODE + opcode);
+      }
     }
-
-    @Override
-    public void visitIntInsn(final int opcode, final int operand) {
-        mv.visitIntInsn(opcode, operand);
-        if (constructor && opcode != NEWARRAY) {
-            pushValue(OTHER);
-        }
-    }
-
-    @Override
-    public void visitLdcInsn(final Object cst) {
-        mv.visitLdcInsn(cst);
-        if (constructor) {
+  }
+
+  @Override
+  public void visitFieldInsn(
+      final int opcode, final String owner, final String name, final String descriptor) {
+    super.visitFieldInsn(opcode, owner, name, descriptor);
+    if (isConstructor && !superClassConstructorCalled) {
+      char firstDescriptorChar = descriptor.charAt(0);
+      boolean longOrDouble = firstDescriptorChar == 'J' || firstDescriptorChar == 'D';
+      switch (opcode) {
+        case GETSTATIC:
+          pushValue(OTHER);
+          if (longOrDouble) {
             pushValue(OTHER);
-            if (cst instanceof Double || cst instanceof Long) {
-                pushValue(OTHER);
-            }
-        }
-    }
-
-    @Override
-    public void visitMultiANewArrayInsn(final String desc, final int dims) {
-        mv.visitMultiANewArrayInsn(desc, dims);
-        if (constructor) {
-            for (int i = 0; i < dims; i++) {
-                popValue();
-            }
+          }
+          break;
+        case PUTSTATIC:
+          popValue();
+          if (longOrDouble) {
+            popValue();
+          }
+          break;
+        case PUTFIELD:
+          popValue();
+          popValue();
+          if (longOrDouble) {
+            popValue();
+          }
+          break;
+        case GETFIELD:
+          if (longOrDouble) {
             pushValue(OTHER);
-        }
+          }
+          break;
+        default:
+          throw new IllegalArgumentException(INVALID_OPCODE + opcode);
+      }
     }
+  }
 
-    @Override
-    public void visitTypeInsn(final int opcode, final String type) {
-        mv.visitTypeInsn(opcode, type);
-        // ANEWARRAY, CHECKCAST or INSTANCEOF don't change stack
-        if (constructor && opcode == NEW) {
-            pushValue(OTHER);
-        }
+  @Override
+  public void visitIntInsn(final int opcode, final int operand) {
+    super.visitIntInsn(opcode, operand);
+    if (isConstructor && !superClassConstructorCalled && opcode != NEWARRAY) {
+      pushValue(OTHER);
     }
-
-    @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);
+  }
+
+  @Override
+  public void visitLdcInsn(final Object value) {
+    super.visitLdcInsn(value);
+    if (isConstructor && !superClassConstructorCalled) {
+      pushValue(OTHER);
+      if (value instanceof Double
+          || value instanceof Long
+          || (value instanceof ConstantDynamic && ((ConstantDynamic) value).getSize() == 2)) {
+        pushValue(OTHER);
+      }
     }
-
-    @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);
+  }
+
+  @Override
+  public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
+    super.visitMultiANewArrayInsn(descriptor, numDimensions);
+    if (isConstructor && !superClassConstructorCalled) {
+      for (int i = 0; i < numDimensions; i++) {
+        popValue();
+      }
+      pushValue(OTHER);
     }
-
-    private void doVisitMethodInsn(int opcode, final String owner,
-            final String name, final String desc, final boolean itf) {
-        mv.visitMethodInsn(opcode, owner, name, desc, itf);
-        if (constructor) {
-            Type[] types = Type.getArgumentTypes(desc);
-            for (int i = 0; i < types.length; i++) {
-                popValue();
-                if (types[i].getSize() == 2) {
-                    popValue();
-                }
-            }
-            switch (opcode) {
-            // case INVOKESTATIC:
-            // break;
-            case INVOKEINTERFACE:
-            case INVOKEVIRTUAL:
-                popValue(); // objectref
-                break;
-            case INVOKESPECIAL:
-                Object type = popValue(); // objectref
-                if (type == THIS && !superInitialized) {
-                    onMethodEnter();
-                    superInitialized = true;
-                    // once super has been initialized it is no longer
-                    // necessary to keep track of stack state
-                    constructor = false;
-                }
-                break;
-            }
-
-            Type returnType = Type.getReturnType(desc);
-            if (returnType != Type.VOID_TYPE) {
-                pushValue(OTHER);
-                if (returnType.getSize() == 2) {
-                    pushValue(OTHER);
-                }
-            }
-        }
+  }
+
+  @Override
+  public void visitTypeInsn(final int opcode, final String type) {
+    super.visitTypeInsn(opcode, type);
+    // ANEWARRAY, CHECKCAST or INSTANCEOF don't change stack.
+    if (isConstructor && !superClassConstructorCalled && opcode == NEW) {
+      pushValue(OTHER);
     }
-
-    @Override
-    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
-            Object... bsmArgs) {
-        mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
-        if (constructor) {
-            Type[] types = Type.getArgumentTypes(desc);
-            for (int i = 0; i < types.length; i++) {
-                popValue();
-                if (types[i].getSize() == 2) {
-                    popValue();
-                }
-            }
-
-            Type returnType = Type.getReturnType(desc);
-            if (returnType != Type.VOID_TYPE) {
-                pushValue(OTHER);
-                if (returnType.getSize() == 2) {
-                    pushValue(OTHER);
-                }
-            }
-        }
+  }
+
+  /**
+   * 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 visitJumpInsn(final int opcode, final Label label) {
-        mv.visitJumpInsn(opcode, label);
-        if (constructor) {
-            switch (opcode) {
-            case IFEQ:
-            case IFNE:
-            case IFLT:
-            case IFGE:
-            case IFGT:
-            case IFLE:
-            case IFNULL:
-            case IFNONNULL:
-                popValue();
-                break;
-            case IF_ICMPEQ:
-            case IF_ICMPNE:
-            case IF_ICMPLT:
-            case IF_ICMPGE:
-            case IF_ICMPGT:
-            case IF_ICMPLE:
-            case IF_ACMPEQ:
-            case IF_ACMPNE:
-                popValue();
-                popValue();
-                break;
-            case JSR:
-                pushValue(OTHER);
-                break;
-            }
-            addBranch(label);
-        }
+    mv.visitMethodInsn(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE);
+    doVisitMethodInsn(opcode, descriptor);
+  }
+
+  @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;
     }
-
-    @Override
-    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
-            final Label[] labels) {
-        mv.visitLookupSwitchInsn(dflt, keys, labels);
-        if (constructor) {
-            popValue();
-            addBranches(dflt, labels);
+    mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+    doVisitMethodInsn(opcode, descriptor);
+  }
+
+  private void doVisitMethodInsn(final int opcode, final String descriptor) {
+    if (isConstructor && !superClassConstructorCalled) {
+      for (Type argumentType : Type.getArgumentTypes(descriptor)) {
+        popValue();
+        if (argumentType.getSize() == 2) {
+          popValue();
         }
-    }
-
-    @Override
-    public void visitTableSwitchInsn(final int min, final int max,
-            final Label dflt, final Label... labels) {
-        mv.visitTableSwitchInsn(min, max, dflt, labels);
-        if (constructor) {
-            popValue();
-            addBranches(dflt, labels);
-        }
-    }
-
-    @Override
-    public void visitTryCatchBlock(Label start, Label end, Label handler,
-            String type) {
-        super.visitTryCatchBlock(start, end, handler, type);
-        if (constructor && !branches.containsKey(handler)) {
-            List<Object> stackFrame = new ArrayList<Object>();
-            stackFrame.add(OTHER);
-            branches.put(handler, stackFrame);
-        }
-    }
-
-    private void addBranches(final Label dflt, final Label[] labels) {
-        addBranch(dflt);
-        for (int i = 0; i < labels.length; i++) {
-            addBranch(labels[i]);
+      }
+      switch (opcode) {
+        case INVOKEINTERFACE:
+        case INVOKEVIRTUAL:
+          popValue();
+          break;
+        case INVOKESPECIAL:
+          Object value = popValue();
+          if (value == UNINITIALIZED_THIS && !superClassConstructorCalled) {
+            superClassConstructorCalled = true;
+            onMethodEnter();
+          }
+          break;
+        default:
+          break;
+      }
+
+      Type returnType = Type.getReturnType(descriptor);
+      if (returnType != Type.VOID_TYPE) {
+        pushValue(OTHER);
+        if (returnType.getSize() == 2) {
+          pushValue(OTHER);
         }
+      }
     }
-
-    private void addBranch(final Label label) {
-        if (branches.containsKey(label)) {
-            return;
-        }
-        branches.put(label, new ArrayList<Object>(stackFrame));
+  }
+
+  @Override
+  public void visitInvokeDynamicInsn(
+      final String name,
+      final String descriptor,
+      final Handle bootstrapMethodHandle,
+      final Object... bootstrapMethodArguments) {
+    super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
+    doVisitMethodInsn(Opcodes.INVOKEDYNAMIC, descriptor);
+  }
+
+  @Override
+  public void visitJumpInsn(final int opcode, final Label label) {
+    super.visitJumpInsn(opcode, label);
+    if (isConstructor && !superClassConstructorCalled) {
+      switch (opcode) {
+        case IFEQ:
+        case IFNE:
+        case IFLT:
+        case IFGE:
+        case IFGT:
+        case IFLE:
+        case IFNULL:
+        case IFNONNULL:
+          popValue();
+          break;
+        case IF_ICMPEQ:
+        case IF_ICMPNE:
+        case IF_ICMPLT:
+        case IF_ICMPGE:
+        case IF_ICMPGT:
+        case IF_ICMPLE:
+        case IF_ACMPEQ:
+        case IF_ACMPNE:
+          popValue();
+          popValue();
+          break;
+        case JSR:
+          pushValue(OTHER);
+          break;
+        default:
+          break;
+      }
+      addForwardJump(label);
     }
-
-    private Object popValue() {
-        return stackFrame.remove(stackFrame.size() - 1);
+  }
+
+  @Override
+  public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
+    super.visitLookupSwitchInsn(dflt, keys, labels);
+    if (isConstructor && !superClassConstructorCalled) {
+      popValue();
+      addForwardJumps(dflt, labels);
     }
-
-    private Object peekValue() {
-        return stackFrame.get(stackFrame.size() - 1);
+  }
+
+  @Override
+  public void visitTableSwitchInsn(
+      final int min, final int max, final Label dflt, final Label... labels) {
+    super.visitTableSwitchInsn(min, max, dflt, labels);
+    if (isConstructor && !superClassConstructorCalled) {
+      popValue();
+      addForwardJumps(dflt, labels);
     }
-
-    private void pushValue(final Object o) {
-        stackFrame.add(o);
+  }
+
+  @Override
+  public void visitTryCatchBlock(
+      final Label start, final Label end, final Label handler, final String type) {
+    super.visitTryCatchBlock(start, end, handler, type);
+    // By definition of 'forwardJumpStackFrames', 'handler' should be pushed only if there is an
+    // instruction between 'start' and 'end' at which the super class constructor is not yet
+    // called. Unfortunately, try catch blocks must be visited before their labels, so we have no
+    // way to know this at this point. Instead, we suppose that the super class constructor has not
+    // been called at the start of *any* exception handler. If this is wrong, normally there should
+    // not be a second super class constructor call in the exception handler (an object can't be
+    // initialized twice), so this is not issue (in the sense that there is no risk to emit a wrong
+    // 'onMethodEnter').
+    if (isConstructor && !forwardJumpStackFrames.containsKey(handler)) {
+      List<Object> handlerStackFrame = new ArrayList<Object>();
+      handlerStackFrame.add(OTHER);
+      forwardJumpStackFrames.put(handler, handlerStackFrame);
     }
+  }
 
-    /**
-     * Called at the beginning of the method or after super class call in
-     * the constructor. <br>
-     * <br>
-     * 
-     * <i>Custom code can use or change all the local variables, but should not
-     * change state of the stack.</i>
-     */
-    protected void onMethodEnter() {
+  private void addForwardJumps(final Label dflt, final Label[] labels) {
+    addForwardJump(dflt);
+    for (Label label : labels) {
+      addForwardJump(label);
     }
+  }
 
-    /**
-     * Called before explicit exit from the method using either return or throw.
-     * Top element on the stack contains the return value or exception instance.
-     * For example:
-     * 
-     * <pre>
-     *   public void onMethodExit(int opcode) {
-     *     if(opcode==RETURN) {
-     *         visitInsn(ACONST_NULL);
-     *     } else if(opcode==ARETURN || opcode==ATHROW) {
-     *         dup();
-     *     } else {
-     *         if(opcode==LRETURN || opcode==DRETURN) {
-     *             dup2();
-     *         } else {
-     *             dup();
-     *         }
-     *         box(Type.getReturnType(this.methodDesc));
-     *     }
-     *     visitIntInsn(SIPUSH, opcode);
-     *     visitMethodInsn(INVOKESTATIC, owner, "onExit", "(Ljava/lang/Object;I)V");
-     *   }
-     * 
-     *   // an actual call back method
-     *   public static void onExit(Object param, int opcode) {
-     *     ...
-     * </pre>
-     * 
-     * <br>
-     * <br>
-     * 
-     * <i>Custom code can use or change all the local variables, but should not
-     * change state of the stack.</i>
-     * 
-     * @param opcode
-     *            one of the RETURN, IRETURN, FRETURN, ARETURN, LRETURN, DRETURN
-     *            or ATHROW
-     * 
-     */
-    protected void onMethodExit(int opcode) {
+  private void addForwardJump(final Label label) {
+    if (forwardJumpStackFrames.containsKey(label)) {
+      return;
     }
-
-    // TODO onException, onMethodCall
+    forwardJumpStackFrames.put(label, new ArrayList<Object>(stackFrame));
+  }
+
+  private Object popValue() {
+    return stackFrame.remove(stackFrame.size() - 1);
+  }
+
+  private Object peekValue() {
+    return stackFrame.get(stackFrame.size() - 1);
+  }
+
+  private void pushValue(final Object value) {
+    stackFrame.add(value);
+  }
+
+  /**
+   * Generates the "before" advice for the visited method. The default implementation of this method
+   * does nothing. Subclasses can use or change all the local variables, but should not change state
+   * of the stack. This method is called at the beginning of the method or after super class
+   * constructor has been called (in constructors).
+   */
+  protected void onMethodEnter() {}
+
+  /**
+   * Generates the "after" advice for the visited method. The default implementation of this method
+   * does nothing. Subclasses can use or change all the local variables, but should not change state
+   * of the stack. This method is called at the end of the method, just before return and athrow
+   * instructions. The top element on the stack contains the return value or the exception instance.
+   * For example:
+   *
+   * <pre>
+   * public void onMethodExit(final int opcode) {
+   *   if (opcode == RETURN) {
+   *     visitInsn(ACONST_NULL);
+   *   } else if (opcode == ARETURN || opcode == ATHROW) {
+   *     dup();
+   *   } else {
+   *     if (opcode == LRETURN || opcode == DRETURN) {
+   *       dup2();
+   *     } else {
+   *       dup();
+   *     }
+   *     box(Type.getReturnType(this.methodDesc));
+   *   }
+   *   visitIntInsn(SIPUSH, opcode);
+   *   visitMethodInsn(INVOKESTATIC, owner, "onExit", "(Ljava/lang/Object;I)V");
+   * }
+   *
+   * // An actual call back method.
+   * public static void onExit(final Object exitValue, final int opcode) {
+   *   ...
+   * }
+   * </pre>
+   *
+   * @param opcode one of {@link Opcodes#RETURN}, {@link Opcodes#IRETURN}, {@link Opcodes#FRETURN},
+   *     {@link Opcodes#ARETURN}, {@link Opcodes#LRETURN}, {@link Opcodes#DRETURN} or {@link
+   *     Opcodes#ATHROW}.
+   */
+  protected void onMethodExit(final int opcode) {}
 }