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

[46/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7 for Java 9+ support

TAP5-2588: upgrading from ASM 6 to 7 for Java 9+ support


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/1c71aec7
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/1c71aec7
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/1c71aec7

Branch: refs/heads/master
Commit: 1c71aec760797c7dc595351639767ae4974b1b82
Parents: cb3b34d
Author: Thiago H. de Paula Figueiredo <th...@arsmachina.com.br>
Authored: Wed Nov 28 22:33:25 2018 -0200
Committer: Thiago H. de Paula Figueiredo <th...@arsmachina.com.br>
Committed: Wed Nov 28 22:33:25 2018 -0200

----------------------------------------------------------------------
 gradle/wrapper/gradle-wrapper.properties        |    2 +-
 plastic/LICENSE-ASM-5_0.txt                     |   29 -
 plastic/LICENSE-ASM-7_0.txt                     |   28 +
 plastic/build.gradle                            |    2 +-
 .../internal/plastic/asm/AnnotationVisitor.java |  268 +-
 .../internal/plastic/asm/AnnotationWriter.java  |  713 +-
 .../internal/plastic/asm/Attribute.java         |  530 +-
 .../internal/plastic/asm/ByteVector.java        |  636 +-
 .../internal/plastic/asm/ClassReader.java       | 6213 ++++++++++--------
 .../plastic/asm/ClassTooLargeException.java     |   71 +
 .../internal/plastic/asm/ClassVisitor.java      |  603 +-
 .../internal/plastic/asm/ClassWriter.java       | 2820 +++-----
 .../internal/plastic/asm/ConstantDynamic.java   |  178 +
 .../internal/plastic/asm/Constants.java         |  177 +
 .../tapestry5/internal/plastic/asm/Context.java |  282 +-
 .../internal/plastic/asm/CurrentFrame.java      |  112 +-
 .../tapestry5/internal/plastic/asm/Edge.java    |  144 +-
 .../internal/plastic/asm/FieldVisitor.java      |  243 +-
 .../internal/plastic/asm/FieldWriter.java       |  603 +-
 .../tapestry5/internal/plastic/asm/Frame.java   | 2812 ++++----
 .../tapestry5/internal/plastic/asm/Handle.java  |  373 +-
 .../tapestry5/internal/plastic/asm/Handler.java |  291 +-
 .../tapestry5/internal/plastic/asm/Item.java    |  318 -
 .../tapestry5/internal/plastic/asm/Label.java   | 1141 ++--
 .../plastic/asm/MethodTooLargeException.java    |   99 +
 .../internal/plastic/asm/MethodVisitor.java     | 1646 +++--
 .../internal/plastic/asm/MethodWriter.java      | 4710 ++++++-------
 .../internal/plastic/asm/ModuleVisitor.java     |  330 +-
 .../internal/plastic/asm/ModuleWriter.java      |  518 +-
 .../tapestry5/internal/plastic/asm/Opcodes.java |  652 +-
 .../tapestry5/internal/plastic/asm/Symbol.java  |  243 +
 .../internal/plastic/asm/SymbolTable.java       | 1318 ++++
 .../tapestry5/internal/plastic/asm/Type.java    | 1734 +++--
 .../internal/plastic/asm/TypePath.java          |  397 +-
 .../internal/plastic/asm/TypeReference.java     |  888 ++-
 .../plastic/asm/commons/AdviceAdapter.java      | 1217 ++--
 .../plastic/asm/commons/AnalyzerAdapter.java    | 1770 +++--
 .../plastic/asm/commons/AnnotationRemapper.java |  142 +-
 .../plastic/asm/commons/ClassRemapper.java      |  354 +-
 .../plastic/asm/commons/CodeSizeEvaluator.java  |  443 +-
 .../plastic/asm/commons/FieldRemapper.java      |  124 +-
 .../plastic/asm/commons/GeneratorAdapter.java   | 2868 ++++----
 .../plastic/asm/commons/InstructionAdapter.java | 2471 +++----
 .../plastic/asm/commons/JSRInlinerAdapter.java  | 1173 ++--
 .../asm/commons/LocalVariablesSorter.java       |  650 +-
 .../internal/plastic/asm/commons/Method.java    |  470 +-
 .../plastic/asm/commons/MethodRemapper.java     |  432 +-
 .../asm/commons/ModuleHashesAttribute.java      |  223 +-
 .../plastic/asm/commons/ModuleRemapper.java     |  194 +-
 .../asm/commons/ModuleResolutionAttribute.java  |  191 +-
 .../asm/commons/ModuleTargetAttribute.java      |  140 +-
 .../internal/plastic/asm/commons/Remapper.java  |  516 +-
 .../asm/commons/RemappingAnnotationAdapter.java |  124 +-
 .../asm/commons/RemappingClassAdapter.java      |  270 +-
 .../asm/commons/RemappingFieldAdapter.java      |  105 +-
 .../asm/commons/RemappingMethodAdapter.java     |  415 +-
 .../asm/commons/RemappingSignatureAdapter.java  |  284 +-
 .../asm/commons/SerialVersionUIDAdder.java      |  934 ++-
 .../plastic/asm/commons/SignatureRemapper.java  |  309 +-
 .../plastic/asm/commons/SimpleRemapper.java     |  131 +-
 .../plastic/asm/commons/StaticInitMerger.java   |  175 +-
 .../asm/commons/TableSwitchGenerator.java       |   80 +-
 .../asm/commons/TryCatchBlockSorter.java        |  171 +-
 .../internal/plastic/asm/commons/package.html   |    0
 .../tapestry5/internal/plastic/asm/package.html |   19 +-
 .../plastic/asm/signature/SignatureReader.java  |  438 +-
 .../plastic/asm/signature/SignatureVisitor.java |  415 +-
 .../plastic/asm/signature/SignatureWriter.java  |  447 +-
 .../internal/plastic/asm/signature/package.html |    0
 .../plastic/asm/tree/AbstractInsnNode.java      |  553 +-
 .../plastic/asm/tree/AnnotationNode.java        |  463 +-
 .../internal/plastic/asm/tree/ClassNode.java    |  813 ++-
 .../plastic/asm/tree/FieldInsnNode.java         |  170 +-
 .../internal/plastic/asm/tree/FieldNode.java    |  481 +-
 .../internal/plastic/asm/tree/FrameNode.java    |  340 +-
 .../internal/plastic/asm/tree/IincInsnNode.java |  123 +-
 .../plastic/asm/tree/InnerClassNode.java        |  154 +-
 .../internal/plastic/asm/tree/InsnList.java     | 1168 ++--
 .../internal/plastic/asm/tree/InsnNode.java     |  131 +-
 .../internal/plastic/asm/tree/IntInsnNode.java  |  133 +-
 .../plastic/asm/tree/InvokeDynamicInsnNode.java |  154 +-
 .../internal/plastic/asm/tree/JumpInsnNode.java |  152 +-
 .../internal/plastic/asm/tree/LabelNode.java    |  125 +-
 .../internal/plastic/asm/tree/LdcInsnNode.java  |  121 +-
 .../plastic/asm/tree/LineNumberNode.java        |  126 +-
 .../asm/tree/LocalVariableAnnotationNode.java   |  297 +-
 .../plastic/asm/tree/LocalVariableNode.java     |  168 +-
 .../plastic/asm/tree/LookupSwitchInsnNode.java  |  167 +-
 .../plastic/asm/tree/MethodInsnNode.java        |  229 +-
 .../internal/plastic/asm/tree/MethodNode.java   | 1579 +++--
 .../plastic/asm/tree/ModuleExportNode.java      |  133 +-
 .../internal/plastic/asm/tree/ModuleNode.java   |  420 +-
 .../plastic/asm/tree/ModuleOpenNode.java        |  135 +-
 .../plastic/asm/tree/ModuleProvideNode.java     |  112 +-
 .../plastic/asm/tree/ModuleRequireNode.java     |  134 +-
 .../asm/tree/MultiANewArrayInsnNode.java        |  124 +-
 .../plastic/asm/tree/ParameterNode.java         |  120 +-
 .../plastic/asm/tree/TableSwitchInsnNode.java   |  163 +-
 .../plastic/asm/tree/TryCatchBlockNode.java     |  235 +-
 .../plastic/asm/tree/TypeAnnotationNode.java    |  185 +-
 .../internal/plastic/asm/tree/TypeInsnNode.java |  146 +-
 .../tree/UnsupportedClassVersionException.java  |   14 +
 .../internal/plastic/asm/tree/Util.java         |  157 +
 .../internal/plastic/asm/tree/VarInsnNode.java  |  146 +-
 .../plastic/asm/tree/analysis/Analyzer.java     | 1047 +--
 .../asm/tree/analysis/AnalyzerException.java    |  123 +-
 .../asm/tree/analysis/BasicInterpreter.java     |  650 +-
 .../plastic/asm/tree/analysis/BasicValue.java   |  216 +-
 .../asm/tree/analysis/BasicVerifier.java        |  795 +--
 .../plastic/asm/tree/analysis/Frame.java        | 1333 ++--
 .../plastic/asm/tree/analysis/Interpreter.java  |  470 +-
 .../asm/tree/analysis/SimpleVerifier.java       |  600 +-
 .../plastic/asm/tree/analysis/SmallSet.java     |  266 +-
 .../asm/tree/analysis/SourceInterpreter.java    |  345 +-
 .../plastic/asm/tree/analysis/SourceValue.java  |  178 +-
 .../plastic/asm/tree/analysis/Subroutine.java   |  157 +-
 .../plastic/asm/tree/analysis/Value.java        |   73 +-
 .../plastic/asm/tree/analysis/package.html      |   30 +-
 .../internal/plastic/asm/tree/package.html      |   71 +-
 .../internal/plastic/asm/util/ASMifiable.java   |   70 +-
 .../internal/plastic/asm/util/ASMifier.java     | 2952 +++++----
 .../asm/util/CheckAnnotationAdapter.java        |  217 +-
 .../plastic/asm/util/CheckClassAdapter.java     | 1967 +++---
 .../plastic/asm/util/CheckFieldAdapter.java     |  186 +-
 .../plastic/asm/util/CheckMethodAdapter.java    | 2870 ++++----
 .../plastic/asm/util/CheckModuleAdapter.java    |  323 +-
 .../plastic/asm/util/CheckSignatureAdapter.java |  627 +-
 .../internal/plastic/asm/util/Printer.java      | 2457 ++++---
 .../internal/plastic/asm/util/Textifiable.java  |   67 +-
 .../internal/plastic/asm/util/Textifier.java    | 3143 ++++-----
 .../asm/util/TraceAnnotationVisitor.java        |  146 +-
 .../plastic/asm/util/TraceClassVisitor.java     |  402 +-
 .../plastic/asm/util/TraceFieldVisitor.java     |  140 +-
 .../plastic/asm/util/TraceMethodVisitor.java    |  582 +-
 .../plastic/asm/util/TraceModuleVisitor.java    |  184 +-
 .../plastic/asm/util/TraceSignatureVisitor.java |  610 +-
 .../internal/plastic/asm/util/package.html      |    4 +-
 .../plastic/asm/xml/ASMContentHandler.java      | 1569 -----
 .../internal/plastic/asm/xml/Processor.java     | 1044 ---
 .../internal/plastic/asm/xml/SAXAdapter.java    |   89 -
 .../plastic/asm/xml/SAXAnnotationAdapter.java   |  242 -
 .../plastic/asm/xml/SAXClassAdapter.java        |  381 --
 .../plastic/asm/xml/SAXCodeAdapter.java         |  415 --
 .../plastic/asm/xml/SAXFieldAdapter.java        |   71 -
 .../plastic/asm/xml/SAXModuleAdapter.java       |  137 -
 .../internal/plastic/asm/xml/asm-xml.dtd        |  363 -
 .../internal/plastic/asm/xml/package.html       |   96 -
 .../plastic/InstructionBuilderImpl.java         |   84 +-
 .../internal/plastic/PlasticClassImpl.java      |  174 +-
 .../internal/plastic/PlasticClassPool.java      |    2 +-
 .../org/apache/tapestry5/ioc/internal/Main.java |   38 +
 .../src/test/resources/hibernate.cfg.xml        |   42 +
 152 files changed, 42157 insertions(+), 44581 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/gradle/wrapper/gradle-wrapper.properties
----------------------------------------------------------------------
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 0e680f3..fb7ef98 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.3.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/LICENSE-ASM-5_0.txt
----------------------------------------------------------------------
diff --git a/plastic/LICENSE-ASM-5_0.txt b/plastic/LICENSE-ASM-5_0.txt
deleted file mode 100644
index c5aba7b..0000000
--- a/plastic/LICENSE-ASM-5_0.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-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.

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/LICENSE-ASM-7_0.txt
----------------------------------------------------------------------
diff --git a/plastic/LICENSE-ASM-7_0.txt b/plastic/LICENSE-ASM-7_0.txt
new file mode 100755
index 0000000..4d19185
--- /dev/null
+++ b/plastic/LICENSE-ASM-7_0.txt
@@ -0,0 +1,28 @@
+
+ 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.

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/build.gradle
----------------------------------------------------------------------
diff --git a/plastic/build.gradle b/plastic/build.gradle
index 25a53f9..d292efa 100644
--- a/plastic/build.gradle
+++ b/plastic/build.gradle
@@ -9,7 +9,7 @@ test {
   useJUnit()
 }
 
-// Add the source directory for the imported/repackaged ASM 3.3.1 code
+// Add the source directory for the imported/repackaged ASM 7.0.1 code
 
 sourceSets.main.java.srcDir "src/external/java"
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
old mode 100644
new mode 100755
index a3df31b..a0c6726
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
@@ -1,169 +1,145 @@
-/***
- * 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;
 
 /**
- * A visitor to visit a Java annotation. The methods of this class must be
- * called in the following order: ( <tt>visit</tt> | <tt>visitEnum</tt> |
- * <tt>visitAnnotation</tt> | <tt>visitArray</tt> )* <tt>visitEnd</tt>.
- * 
+ * A visitor to visit a Java annotation. The methods of this class must be called in the following
+ * order: ( {@code visit} | {@code visitEnum} | {@code visitAnnotation} | {@code visitArray} )*
+ * {@code visitEnd}.
+ *
  * @author Eric Bruneton
  * @author Eugene Kuleshov
  */
 public abstract class AnnotationVisitor {
 
-    /**
-     * The ASM API version implemented by this visitor. The value of this field
-     * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
-     */
-    protected final int api;
+  /**
+   * The ASM API version implemented by this visitor. The value of this field must be one of {@link
+   * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+   */
+  protected final int api;
 
-    /**
-     * The annotation visitor to which this visitor must delegate method calls.
-     * May be null.
-     */
-    protected AnnotationVisitor av;
+  /** The annotation visitor to which this visitor must delegate method calls. May be null. */
+  protected AnnotationVisitor av;
 
-    /**
-     * Constructs a new {@link AnnotationVisitor}.
-     * 
-     * @param api
-     *            the ASM API version implemented by this visitor. Must be one
-     *            of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
-     */
-    public AnnotationVisitor(final int api) {
-        this(api, null);
-    }
+  /**
+   * Constructs a new {@link AnnotationVisitor}.
+   *
+   * @param api the ASM API version implemented by this visitor. Must be one of {@link
+   *     Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+   */
+  public AnnotationVisitor(final int api) {
+    this(api, null);
+  }
 
-    /**
-     * Constructs a new {@link AnnotationVisitor}.
-     * 
-     * @param api
-     *            the ASM API version implemented by this visitor. Must be one
-     *            of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
-     * @param av
-     *            the annotation visitor to which this visitor must delegate
-     *            method calls. May be null.
-     */
-    public AnnotationVisitor(final int api, final AnnotationVisitor av) {
-        if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
-            throw new IllegalArgumentException();
-        }
-        this.api = api;
-        this.av = av;
+  /**
+   * Constructs a new {@link AnnotationVisitor}.
+   *
+   * @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 annotationVisitor the annotation visitor to which this visitor must delegate method
+   *     calls. May be null.
+   */
+  public AnnotationVisitor(final int api, final AnnotationVisitor annotationVisitor) {
+    if (api != Opcodes.ASM6 && api != Opcodes.ASM5 && api != Opcodes.ASM4 && api != Opcodes.ASM7) {
+      throw new IllegalArgumentException();
     }
+    this.api = api;
+    this.av = annotationVisitor;
+  }
 
-    /**
-     * Visits a primitive value of the annotation.
-     * 
-     * @param name
-     *            the value name.
-     * @param value
-     *            the actual value, whose type must be {@link Byte},
-     *            {@link Boolean}, {@link Character}, {@link Short},
-     *            {@link Integer} , {@link Long}, {@link Float}, {@link Double},
-     *            {@link String} or {@link Type} of OBJECT or ARRAY sort. This
-     *            value can also be an array of byte, boolean, short, char, int,
-     *            long, float or double values (this is equivalent to using
-     *            {@link #visitArray visitArray} and visiting each array element
-     *            in turn, but is more convenient).
-     */
-    public void visit(String name, Object value) {
-        if (av != null) {
-            av.visit(name, value);
-        }
+  /**
+   * Visits a primitive value of the annotation.
+   *
+   * @param name the value name.
+   * @param value the actual value, whose type must be {@link Byte}, {@link Boolean}, {@link
+   *     Character}, {@link Short}, {@link Integer} , {@link Long}, {@link Float}, {@link Double},
+   *     {@link String} or {@link Type} of {@link Type#OBJECT} or {@link Type#ARRAY} sort. This
+   *     value can also be an array of byte, boolean, short, char, int, long, float or double values
+   *     (this is equivalent to using {@link #visitArray} and visiting each array element in turn,
+   *     but is more convenient).
+   */
+  public void visit(final String name, final Object value) {
+    if (av != null) {
+      av.visit(name, value);
     }
+  }
 
-    /**
-     * Visits an enumeration value of the annotation.
-     * 
-     * @param name
-     *            the value name.
-     * @param desc
-     *            the class descriptor of the enumeration class.
-     * @param value
-     *            the actual enumeration value.
-     */
-    public void visitEnum(String name, String desc, String value) {
-        if (av != null) {
-            av.visitEnum(name, desc, value);
-        }
+  /**
+   * Visits an enumeration value of the annotation.
+   *
+   * @param name the value name.
+   * @param descriptor the class descriptor of the enumeration class.
+   * @param value the actual enumeration value.
+   */
+  public void visitEnum(final String name, final String descriptor, final String value) {
+    if (av != null) {
+      av.visitEnum(name, descriptor, value);
     }
+  }
 
-    /**
-     * Visits a nested annotation value of the annotation.
-     * 
-     * @param name
-     *            the value name.
-     * @param desc
-     *            the class descriptor of the nested annotation class.
-     * @return a visitor to visit the actual nested annotation value, or
-     *         <tt>null</tt> if this visitor is not interested in visiting this
-     *         nested annotation. <i>The nested annotation value must be fully
-     *         visited before calling other methods on this annotation
-     *         visitor</i>.
-     */
-    public AnnotationVisitor visitAnnotation(String name, String desc) {
-        if (av != null) {
-            return av.visitAnnotation(name, desc);
-        }
-        return null;
+  /**
+   * Visits a nested annotation value of the annotation.
+   *
+   * @param name the value name.
+   * @param descriptor the class descriptor of the nested annotation class.
+   * @return a visitor to visit the actual nested annotation value, or {@literal null} if this
+   *     visitor is not interested in visiting this nested annotation. <i>The nested annotation
+   *     value must be fully visited before calling other methods on this annotation visitor</i>.
+   */
+  public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
+    if (av != null) {
+      return av.visitAnnotation(name, descriptor);
     }
+    return null;
+  }
 
-    /**
-     * Visits an array value of the annotation. Note that arrays of primitive
-     * types (such as byte, boolean, short, char, int, long, float or double)
-     * can be passed as value to {@link #visit visit}. This is what
-     * {@link ClassReader} does.
-     * 
-     * @param name
-     *            the value name.
-     * @return a visitor to visit the actual array value elements, or
-     *         <tt>null</tt> if this visitor is not interested in visiting these
-     *         values. The 'name' parameters passed to the methods of this
-     *         visitor are ignored. <i>All the array values must be visited
-     *         before calling other methods on this annotation visitor</i>.
-     */
-    public AnnotationVisitor visitArray(String name) {
-        if (av != null) {
-            return av.visitArray(name);
-        }
-        return null;
+  /**
+   * Visits an array value of the annotation. Note that arrays of primitive types (such as byte,
+   * boolean, short, char, int, long, float or double) can be passed as value to {@link #visit
+   * visit}. This is what {@link ClassReader} does.
+   *
+   * @param name the value name.
+   * @return a visitor to visit the actual array value elements, or {@literal null} if this visitor
+   *     is not interested in visiting these values. The 'name' parameters passed to the methods of
+   *     this visitor are ignored. <i>All the array values must be visited before calling other
+   *     methods on this annotation visitor</i>.
+   */
+  public AnnotationVisitor visitArray(final String name) {
+    if (av != null) {
+      return av.visitArray(name);
     }
+    return null;
+  }
 
-    /**
-     * Visits the end of the annotation.
-     */
-    public void visitEnd() {
-        if (av != null) {
-            av.visitEnd();
-        }
+  /** Visits the end of the annotation. */
+  public void visitEnd() {
+    if (av != null) {
+      av.visitEnd();
     }
+  }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
old mode 100644
new mode 100755
index d0d2d4a..c55f36a
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
@@ -1,371 +1,418 @@
-/***
- * 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;
 
 /**
- * An {@link AnnotationVisitor} that generates annotations in bytecode form.
- * 
+ * An {@link AnnotationVisitor} that generates a corresponding 'annotation' or 'type_annotation'
+ * structure, as defined in the Java Virtual Machine Specification (JVMS). AnnotationWriter
+ * instances can be chained in a doubly linked list, from which Runtime[In]Visible[Type]Annotations
+ * attributes can be generated with the {@link #putAnnotations} method. Similarly, arrays of such
+ * lists can be used to generate Runtime[In]VisibleParameterAnnotations attributes.
+ *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16">JVMS
+ *     4.7.16</a>
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20">JVMS
+ *     4.7.20</a>
  * @author Eric Bruneton
  * @author Eugene Kuleshov
  */
 final class AnnotationWriter extends AnnotationVisitor {
 
-    /**
-     * The class writer to which this annotation must be added.
-     */
-    private final ClassWriter cw;
-
-    /**
-     * The number of values in this annotation.
-     */
-    private int size;
+  /** Where the constants used in this AnnotationWriter must be stored. */
+  private final SymbolTable symbolTable;
 
-    /**
-     * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation
-     * writers used for annotation default and annotation arrays use unnamed
-     * values.
-     */
-    private final boolean named;
+  /**
+   * Whether values are named or not. AnnotationWriter instances used for annotation default and
+   * annotation arrays use unnamed values (i.e. they generate an 'element_value' structure for each
+   * value, instead of an element_name_index followed by an element_value).
+   */
+  private final boolean useNamedValues;
 
-    /**
-     * The annotation values in bytecode form. This byte vector only contains
-     * the values themselves, i.e. the number of values must be stored as a
-     * unsigned short just before these bytes.
-     */
-    private final ByteVector bv;
+  /**
+   * The 'annotation' or 'type_annotation' JVMS structure corresponding to the annotation values
+   * visited so far. All the fields of these structures, except the last one - the
+   * element_value_pairs array, must be set before this ByteVector is passed to the constructor
+   * (num_element_value_pairs can be set to 0, it is reset to the correct value in {@link
+   * #visitEnd()}). The element_value_pairs array is filled incrementally in the various visit()
+   * methods.
+   *
+   * <p>Note: as an exception to the above rules, for AnnotationDefault attributes (which contain a
+   * single element_value by definition), this ByteVector is initially empty when passed to the
+   * constructor, and {@link #numElementValuePairsOffset} is set to -1.
+   */
+  private final ByteVector annotation;
 
-    /**
-     * The byte vector to be used to store the number of values of this
-     * annotation. See {@link #bv}.
-     */
-    private final ByteVector parent;
+  /**
+   * The offset in {@link #annotation} where {@link #numElementValuePairs} must be stored (or -1 for
+   * the case of AnnotationDefault attributes).
+   */
+  private final int numElementValuePairsOffset;
 
-    /**
-     * Where the number of values of this annotation must be stored in
-     * {@link #parent}.
-     */
-    private final int offset;
+  /** The number of element value pairs visited so far. */
+  private int numElementValuePairs;
 
-    /**
-     * Next annotation writer. This field is used to store annotation lists.
-     */
-    AnnotationWriter next;
+  /**
+   * The previous AnnotationWriter. This field is used to store the list of annotations of a
+   * Runtime[In]Visible[Type]Annotations attribute. It is unused for nested or array annotations
+   * (annotation values of annotation type), or for AnnotationDefault attributes.
+   */
+  private final AnnotationWriter previousAnnotation;
 
-    /**
-     * Previous annotation writer. This field is used to store annotation lists.
-     */
-    AnnotationWriter prev;
+  /**
+   * The next AnnotationWriter. This field is used to store the list of annotations of a
+   * Runtime[In]Visible[Type]Annotations attribute. It is unused for nested or array annotations
+   * (annotation values of annotation type), or for AnnotationDefault attributes.
+   */
+  private AnnotationWriter nextAnnotation;
 
-    // ------------------------------------------------------------------------
-    // Constructor
-    // ------------------------------------------------------------------------
+  // -----------------------------------------------------------------------------------------------
+  // Constructors
+  // -----------------------------------------------------------------------------------------------
 
-    /**
-     * Constructs a new {@link AnnotationWriter}.
-     * 
-     * @param cw
-     *            the class writer to which this annotation must be added.
-     * @param named
-     *            <tt>true<tt> if values are named, <tt>false</tt> otherwise.
-     * @param bv
-     *            where the annotation values must be stored.
-     * @param parent
-     *            where the number of annotation values must be stored.
-     * @param offset
-     *            where in <tt>parent</tt> the number of annotation values must
-     *            be stored.
-     */
-    AnnotationWriter(final ClassWriter cw, final boolean named,
-            final ByteVector bv, final ByteVector parent, final int offset) {
-        super(Opcodes.ASM6);
-        this.cw = cw;
-        this.named = named;
-        this.bv = bv;
-        this.parent = parent;
-        this.offset = offset;
+  /**
+   * Constructs a new {@link AnnotationWriter}.
+   *
+   * @param symbolTable where the constants used in this AnnotationWriter must be stored.
+   * @param useNamedValues whether values are named or not. AnnotationDefault and annotation arrays
+   *     use unnamed values.
+   * @param annotation where the 'annotation' or 'type_annotation' JVMS structure corresponding to
+   *     the visited content must be stored. This ByteVector must already contain all the fields of
+   *     the structure except the last one (the element_value_pairs array).
+   * @param previousAnnotation the previously visited annotation of the
+   *     Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or null in
+   *     other cases (e.g. nested or array annotations).
+   */
+  AnnotationWriter(
+      final SymbolTable symbolTable,
+      final boolean useNamedValues,
+      final ByteVector annotation,
+      final AnnotationWriter previousAnnotation) {
+    super(Opcodes.ASM7);
+    this.symbolTable = symbolTable;
+    this.useNamedValues = useNamedValues;
+    this.annotation = annotation;
+    // By hypothesis, num_element_value_pairs is stored in the last unsigned short of 'annotation'.
+    this.numElementValuePairsOffset = annotation.length == 0 ? -1 : annotation.length - 2;
+    this.previousAnnotation = previousAnnotation;
+    if (previousAnnotation != null) {
+      previousAnnotation.nextAnnotation = this;
     }
+  }
 
-    // ------------------------------------------------------------------------
-    // Implementation of the AnnotationVisitor abstract class
-    // ------------------------------------------------------------------------
+  /**
+   * Constructs a new {@link AnnotationWriter} using named values.
+   *
+   * @param symbolTable where the constants used in this AnnotationWriter must be stored.
+   * @param annotation where the 'annotation' or 'type_annotation' JVMS structure corresponding to
+   *     the visited content must be stored. This ByteVector must already contain all the fields of
+   *     the structure except the last one (the element_value_pairs array).
+   * @param previousAnnotation the previously visited annotation of the
+   *     Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or null in
+   *     other cases (e.g. nested or array annotations).
+   */
+  AnnotationWriter(
+      final SymbolTable symbolTable,
+      final ByteVector annotation,
+      final AnnotationWriter previousAnnotation) {
+    this(symbolTable, /* useNamedValues = */ true, annotation, previousAnnotation);
+  }
 
-    @Override
-    public void visit(final String name, final Object value) {
-        ++size;
-        if (named) {
-            bv.putShort(cw.newUTF8(name));
-        }
-        if (value instanceof String) {
-            bv.put12('s', cw.newUTF8((String) value));
-        } else if (value instanceof Byte) {
-            bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index);
-        } else if (value instanceof Boolean) {
-            int v = ((Boolean) value).booleanValue() ? 1 : 0;
-            bv.put12('Z', cw.newInteger(v).index);
-        } else if (value instanceof Character) {
-            bv.put12('C', cw.newInteger(((Character) value).charValue()).index);
-        } else if (value instanceof Short) {
-            bv.put12('S', cw.newInteger(((Short) value).shortValue()).index);
-        } else if (value instanceof Type) {
-            bv.put12('c', cw.newUTF8(((Type) value).getDescriptor()));
-        } else if (value instanceof byte[]) {
-            byte[] v = (byte[]) value;
-            bv.put12('[', v.length);
-            for (int i = 0; i < v.length; i++) {
-                bv.put12('B', cw.newInteger(v[i]).index);
-            }
-        } else if (value instanceof boolean[]) {
-            boolean[] v = (boolean[]) value;
-            bv.put12('[', v.length);
-            for (int i = 0; i < v.length; i++) {
-                bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index);
-            }
-        } else if (value instanceof short[]) {
-            short[] v = (short[]) value;
-            bv.put12('[', v.length);
-            for (int i = 0; i < v.length; i++) {
-                bv.put12('S', cw.newInteger(v[i]).index);
-            }
-        } else if (value instanceof char[]) {
-            char[] v = (char[]) value;
-            bv.put12('[', v.length);
-            for (int i = 0; i < v.length; i++) {
-                bv.put12('C', cw.newInteger(v[i]).index);
-            }
-        } else if (value instanceof int[]) {
-            int[] v = (int[]) value;
-            bv.put12('[', v.length);
-            for (int i = 0; i < v.length; i++) {
-                bv.put12('I', cw.newInteger(v[i]).index);
-            }
-        } else if (value instanceof long[]) {
-            long[] v = (long[]) value;
-            bv.put12('[', v.length);
-            for (int i = 0; i < v.length; i++) {
-                bv.put12('J', cw.newLong(v[i]).index);
-            }
-        } else if (value instanceof float[]) {
-            float[] v = (float[]) value;
-            bv.put12('[', v.length);
-            for (int i = 0; i < v.length; i++) {
-                bv.put12('F', cw.newFloat(v[i]).index);
-            }
-        } else if (value instanceof double[]) {
-            double[] v = (double[]) value;
-            bv.put12('[', v.length);
-            for (int i = 0; i < v.length; i++) {
-                bv.put12('D', cw.newDouble(v[i]).index);
-            }
-        } else {
-            Item i = cw.newConstItem(value);
-            bv.put12(".s.IFJDCS".charAt(i.type), i.index);
-        }
+  // -----------------------------------------------------------------------------------------------
+  // Implementation of the AnnotationVisitor abstract class
+  // -----------------------------------------------------------------------------------------------
+
+  @Override
+  public void visit(final String name, final Object value) {
+    // Case of an element_value with a const_value_index, class_info_index or array_index field.
+    // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1.
+    ++numElementValuePairs;
+    if (useNamedValues) {
+      annotation.putShort(symbolTable.addConstantUtf8(name));
+    }
+    if (value instanceof String) {
+      annotation.put12('s', symbolTable.addConstantUtf8((String) value));
+    } else if (value instanceof Byte) {
+      annotation.put12('B', symbolTable.addConstantInteger(((Byte) value).byteValue()).index);
+    } else if (value instanceof Boolean) {
+      int booleanValue = ((Boolean) value).booleanValue() ? 1 : 0;
+      annotation.put12('Z', symbolTable.addConstantInteger(booleanValue).index);
+    } else if (value instanceof Character) {
+      annotation.put12('C', symbolTable.addConstantInteger(((Character) value).charValue()).index);
+    } else if (value instanceof Short) {
+      annotation.put12('S', symbolTable.addConstantInteger(((Short) value).shortValue()).index);
+    } else if (value instanceof Type) {
+      annotation.put12('c', symbolTable.addConstantUtf8(((Type) value).getDescriptor()));
+    } else if (value instanceof byte[]) {
+      byte[] byteArray = (byte[]) value;
+      annotation.put12('[', byteArray.length);
+      for (byte byteValue : byteArray) {
+        annotation.put12('B', symbolTable.addConstantInteger(byteValue).index);
+      }
+    } else if (value instanceof boolean[]) {
+      boolean[] booleanArray = (boolean[]) value;
+      annotation.put12('[', booleanArray.length);
+      for (boolean booleanValue : booleanArray) {
+        annotation.put12('Z', symbolTable.addConstantInteger(booleanValue ? 1 : 0).index);
+      }
+    } else if (value instanceof short[]) {
+      short[] shortArray = (short[]) value;
+      annotation.put12('[', shortArray.length);
+      for (short shortValue : shortArray) {
+        annotation.put12('S', symbolTable.addConstantInteger(shortValue).index);
+      }
+    } else if (value instanceof char[]) {
+      char[] charArray = (char[]) value;
+      annotation.put12('[', charArray.length);
+      for (char charValue : charArray) {
+        annotation.put12('C', symbolTable.addConstantInteger(charValue).index);
+      }
+    } else if (value instanceof int[]) {
+      int[] intArray = (int[]) value;
+      annotation.put12('[', intArray.length);
+      for (int intValue : intArray) {
+        annotation.put12('I', symbolTable.addConstantInteger(intValue).index);
+      }
+    } else if (value instanceof long[]) {
+      long[] longArray = (long[]) value;
+      annotation.put12('[', longArray.length);
+      for (long longValue : longArray) {
+        annotation.put12('J', symbolTable.addConstantLong(longValue).index);
+      }
+    } else if (value instanceof float[]) {
+      float[] floatArray = (float[]) value;
+      annotation.put12('[', floatArray.length);
+      for (float floatValue : floatArray) {
+        annotation.put12('F', symbolTable.addConstantFloat(floatValue).index);
+      }
+    } else if (value instanceof double[]) {
+      double[] doubleArray = (double[]) value;
+      annotation.put12('[', doubleArray.length);
+      for (double doubleValue : doubleArray) {
+        annotation.put12('D', symbolTable.addConstantDouble(doubleValue).index);
+      }
+    } else {
+      Symbol symbol = symbolTable.addConstant(value);
+      annotation.put12(".s.IFJDCS".charAt(symbol.tag), symbol.index);
     }
+  }
 
-    @Override
-    public void visitEnum(final String name, final String desc,
-            final String value) {
-        ++size;
-        if (named) {
-            bv.putShort(cw.newUTF8(name));
-        }
-        bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value));
+  @Override
+  public void visitEnum(final String name, final String descriptor, final String value) {
+    // Case of an element_value with an enum_const_value field.
+    // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1.
+    ++numElementValuePairs;
+    if (useNamedValues) {
+      annotation.putShort(symbolTable.addConstantUtf8(name));
     }
+    annotation
+        .put12('e', symbolTable.addConstantUtf8(descriptor))
+        .putShort(symbolTable.addConstantUtf8(value));
+  }
 
-    @Override
-    public AnnotationVisitor visitAnnotation(final String name,
-            final String desc) {
-        ++size;
-        if (named) {
-            bv.putShort(cw.newUTF8(name));
-        }
-        // write tag and type, and reserve space for values count
-        bv.put12('@', cw.newUTF8(desc)).putShort(0);
-        return new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
+  @Override
+  public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
+    // Case of an element_value with an annotation_value field.
+    // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1.
+    ++numElementValuePairs;
+    if (useNamedValues) {
+      annotation.putShort(symbolTable.addConstantUtf8(name));
     }
+    // Write tag and type_index, and reserve 2 bytes for num_element_value_pairs.
+    annotation.put12('@', symbolTable.addConstantUtf8(descriptor)).putShort(0);
+    return new AnnotationWriter(symbolTable, annotation, null);
+  }
 
-    @Override
-    public AnnotationVisitor visitArray(final String name) {
-        ++size;
-        if (named) {
-            bv.putShort(cw.newUTF8(name));
-        }
-        // write tag, and reserve space for array size
-        bv.put12('[', 0);
-        return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);
+  @Override
+  public AnnotationVisitor visitArray(final String name) {
+    // Case of an element_value with an array_value field.
+    // https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1
+    ++numElementValuePairs;
+    if (useNamedValues) {
+      annotation.putShort(symbolTable.addConstantUtf8(name));
     }
+    // Write tag, and reserve 2 bytes for num_values. Here we take advantage of the fact that the
+    // end of an element_value of array type is similar to the end of an 'annotation' structure: an
+    // unsigned short num_values followed by num_values element_value, versus an unsigned short
+    // num_element_value_pairs, followed by num_element_value_pairs { element_name_index,
+    // element_value } tuples. This allows us to use an AnnotationWriter with unnamed values to
+    // visit the array elements. Its num_element_value_pairs will correspond to the number of array
+    // elements and will be stored in what is in fact num_values.
+    annotation.put12('[', 0);
+    return new AnnotationWriter(symbolTable, /* useNamedValues = */ false, annotation, null);
+  }
 
-    @Override
-    public void visitEnd() {
-        if (parent != null) {
-            byte[] data = parent.data;
-            data[offset] = (byte) (size >>> 8);
-            data[offset + 1] = (byte) size;
-        }
+  @Override
+  public void visitEnd() {
+    if (numElementValuePairsOffset != -1) {
+      byte[] data = annotation.data;
+      data[numElementValuePairsOffset] = (byte) (numElementValuePairs >>> 8);
+      data[numElementValuePairsOffset + 1] = (byte) numElementValuePairs;
     }
+  }
 
-    // ------------------------------------------------------------------------
-    // Utility methods
-    // ------------------------------------------------------------------------
+  // -----------------------------------------------------------------------------------------------
+  // Utility methods
+  // -----------------------------------------------------------------------------------------------
 
-    /**
-     * Returns the size of this annotation writer list.
-     * 
-     * @return the size of this annotation writer list.
-     */
-    int getSize() {
-        int size = 0;
-        AnnotationWriter aw = this;
-        while (aw != null) {
-            size += aw.bv.length;
-            aw = aw.next;
-        }
-        return size;
+  /**
+   * Returns the size of a Runtime[In]Visible[Type]Annotations attribute containing this annotation
+   * and all its <i>predecessors</i> (see {@link #previousAnnotation}. Also adds the attribute name
+   * to the constant pool of the class (if not null).
+   *
+   * @param attributeName one of "Runtime[In]Visible[Type]Annotations", or null.
+   * @return the size in bytes of a Runtime[In]Visible[Type]Annotations attribute containing this
+   *     annotation and all its predecessors. This includes the size of the attribute_name_index and
+   *     attribute_length fields.
+   */
+  int computeAnnotationsSize(final String attributeName) {
+    if (attributeName != null) {
+      symbolTable.addConstantUtf8(attributeName);
+    }
+    // The attribute_name_index, attribute_length and num_annotations fields use 8 bytes.
+    int attributeSize = 8;
+    AnnotationWriter annotationWriter = this;
+    while (annotationWriter != null) {
+      attributeSize += annotationWriter.annotation.length;
+      annotationWriter = annotationWriter.previousAnnotation;
     }
+    return attributeSize;
+  }
 
-    /**
-     * Puts the annotations of this annotation writer list into the given byte
-     * vector.
-     * 
-     * @param out
-     *            where the annotations must be put.
-     */
-    void put(final ByteVector out) {
-        int n = 0;
-        int size = 2;
-        AnnotationWriter aw = this;
-        AnnotationWriter last = null;
-        while (aw != null) {
-            ++n;
-            size += aw.bv.length;
-            aw.visitEnd(); // in case user forgot to call visitEnd
-            aw.prev = last;
-            last = aw;
-            aw = aw.next;
-        }
-        out.putInt(size);
-        out.putShort(n);
-        aw = last;
-        while (aw != null) {
-            out.putByteArray(aw.bv.data, 0, aw.bv.length);
-            aw = aw.prev;
-        }
+  /**
+   * Puts a Runtime[In]Visible[Type]Annotations attribute containing this annotations and all its
+   * <i>predecessors</i> (see {@link #previousAnnotation} in the given ByteVector. Annotations are
+   * put in the same order they have been visited.
+   *
+   * @param attributeNameIndex the constant pool index of the attribute name (one of
+   *     "Runtime[In]Visible[Type]Annotations").
+   * @param output where the attribute must be put.
+   */
+  void putAnnotations(final int attributeNameIndex, final ByteVector output) {
+    int attributeLength = 2; // For num_annotations.
+    int numAnnotations = 0;
+    AnnotationWriter annotationWriter = this;
+    AnnotationWriter firstAnnotation = null;
+    while (annotationWriter != null) {
+      // In case the user forgot to call visitEnd().
+      annotationWriter.visitEnd();
+      attributeLength += annotationWriter.annotation.length;
+      numAnnotations++;
+      firstAnnotation = annotationWriter;
+      annotationWriter = annotationWriter.previousAnnotation;
     }
+    output.putShort(attributeNameIndex);
+    output.putInt(attributeLength);
+    output.putShort(numAnnotations);
+    annotationWriter = firstAnnotation;
+    while (annotationWriter != null) {
+      output.putByteArray(annotationWriter.annotation.data, 0, annotationWriter.annotation.length);
+      annotationWriter = annotationWriter.nextAnnotation;
+    }
+  }
 
-    /**
-     * Puts the given annotation lists into the given byte vector.
-     * 
-     * @param panns
-     *            an array of annotation writer lists.
-     * @param off
-     *            index of the first annotation to be written.
-     * @param out
-     *            where the annotations must be put.
-     */
-    static void put(final AnnotationWriter[] panns, final int off,
-            final ByteVector out) {
-        int size = 1 + 2 * (panns.length - off);
-        for (int i = off; i < panns.length; ++i) {
-            size += panns[i] == null ? 0 : panns[i].getSize();
-        }
-        out.putInt(size).putByte(panns.length - off);
-        for (int i = off; i < panns.length; ++i) {
-            AnnotationWriter aw = panns[i];
-            AnnotationWriter last = null;
-            int n = 0;
-            while (aw != null) {
-                ++n;
-                aw.visitEnd(); // in case user forgot to call visitEnd
-                aw.prev = last;
-                last = aw;
-                aw = aw.next;
-            }
-            out.putShort(n);
-            aw = last;
-            while (aw != null) {
-                out.putByteArray(aw.bv.data, 0, aw.bv.length);
-                aw = aw.prev;
-            }
-        }
+  /**
+   * Returns the size of a Runtime[In]VisibleParameterAnnotations attribute containing all the
+   * annotation lists from the given AnnotationWriter sub-array. Also adds the attribute name to the
+   * constant pool of the class.
+   *
+   * @param attributeName one of "Runtime[In]VisibleParameterAnnotations".
+   * @param annotationWriters an array of AnnotationWriter lists (designated by their <i>last</i>
+   *     element).
+   * @param annotableParameterCount the number of elements in annotationWriters to take into account
+   *     (elements [0..annotableParameterCount[ are taken into account).
+   * @return the size in bytes of a Runtime[In]VisibleParameterAnnotations attribute corresponding
+   *     to the given sub-array of AnnotationWriter lists. This includes the size of the
+   *     attribute_name_index and attribute_length fields.
+   */
+  static int computeParameterAnnotationsSize(
+      final String attributeName,
+      final AnnotationWriter[] annotationWriters,
+      final int annotableParameterCount) {
+    // Note: attributeName is added to the constant pool by the call to computeAnnotationsSize
+    // below. This assumes that there is at least one non-null element in the annotationWriters
+    // sub-array (which is ensured by the lazy instantiation of this array in MethodWriter).
+    // The attribute_name_index, attribute_length and num_parameters fields use 7 bytes, and each
+    // element of the parameter_annotations array uses 2 bytes for its num_annotations field.
+    int attributeSize = 7 + 2 * annotableParameterCount;
+    for (int i = 0; i < annotableParameterCount; ++i) {
+      AnnotationWriter annotationWriter = annotationWriters[i];
+      attributeSize +=
+          annotationWriter == null ? 0 : annotationWriter.computeAnnotationsSize(attributeName) - 8;
     }
+    return attributeSize;
+  }
 
-    /**
-     * Puts the given type reference and type path into the given bytevector.
-     * LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported.
-     * 
-     * @param typeRef
-     *            a reference to the annotated type. See {@link TypeReference}.
-     * @param typePath
-     *            the path to the annotated type argument, wildcard bound, array
-     *            element type, or static inner type within 'typeRef'. May be
-     *            <tt>null</tt> if the annotation targets 'typeRef' as a whole.
-     * @param out
-     *            where the type reference and type path must be put.
-     */
-    static void putTarget(int typeRef, TypePath typePath, ByteVector out) {
-        switch (typeRef >>> 24) {
-        case 0x00: // CLASS_TYPE_PARAMETER
-        case 0x01: // METHOD_TYPE_PARAMETER
-        case 0x16: // METHOD_FORMAL_PARAMETER
-            out.putShort(typeRef >>> 16);
-            break;
-        case 0x13: // FIELD
-        case 0x14: // METHOD_RETURN
-        case 0x15: // METHOD_RECEIVER
-            out.putByte(typeRef >>> 24);
-            break;
-        case 0x47: // CAST
-        case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
-        case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
-        case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
-        case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
-            out.putInt(typeRef);
-            break;
-        // case 0x10: // CLASS_EXTENDS
-        // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
-        // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
-        // case 0x17: // THROWS
-        // case 0x42: // EXCEPTION_PARAMETER
-        // case 0x43: // INSTANCEOF
-        // case 0x44: // NEW
-        // case 0x45: // CONSTRUCTOR_REFERENCE
-        // case 0x46: // METHOD_REFERENCE
-        default:
-            out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8);
-            break;
-        }
-        if (typePath == null) {
-            out.putByte(0);
-        } else {
-            int length = typePath.b[typePath.offset] * 2 + 1;
-            out.putByteArray(typePath.b, typePath.offset, length);
-        }
+  /**
+   * Puts a Runtime[In]VisibleParameterAnnotations attribute containing all the annotation lists
+   * from the given AnnotationWriter sub-array in the given ByteVector.
+   *
+   * @param attributeNameIndex constant pool index of the attribute name (one of
+   *     Runtime[In]VisibleParameterAnnotations).
+   * @param annotationWriters an array of AnnotationWriter lists (designated by their <i>last</i>
+   *     element).
+   * @param annotableParameterCount the number of elements in annotationWriters to put (elements
+   *     [0..annotableParameterCount[ are put).
+   * @param output where the attribute must be put.
+   */
+  static void putParameterAnnotations(
+      final int attributeNameIndex,
+      final AnnotationWriter[] annotationWriters,
+      final int annotableParameterCount,
+      final ByteVector output) {
+    // The num_parameters field uses 1 byte, and each element of the parameter_annotations array
+    // uses 2 bytes for its num_annotations field.
+    int attributeLength = 1 + 2 * annotableParameterCount;
+    for (int i = 0; i < annotableParameterCount; ++i) {
+      AnnotationWriter annotationWriter = annotationWriters[i];
+      attributeLength +=
+          annotationWriter == null ? 0 : annotationWriter.computeAnnotationsSize(null) - 8;
+    }
+    output.putShort(attributeNameIndex);
+    output.putInt(attributeLength);
+    output.putByte(annotableParameterCount);
+    for (int i = 0; i < annotableParameterCount; ++i) {
+      AnnotationWriter annotationWriter = annotationWriters[i];
+      AnnotationWriter firstAnnotation = null;
+      int numAnnotations = 0;
+      while (annotationWriter != null) {
+        // In case user the forgot to call visitEnd().
+        annotationWriter.visitEnd();
+        numAnnotations++;
+        firstAnnotation = annotationWriter;
+        annotationWriter = annotationWriter.previousAnnotation;
+      }
+      output.putShort(numAnnotations);
+      annotationWriter = firstAnnotation;
+      while (annotationWriter != null) {
+        output.putByteArray(
+            annotationWriter.annotation.data, 0, annotationWriter.annotation.length);
+        annotationWriter = annotationWriter.nextAnnotation;
+      }
     }
+  }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
old mode 100644
new mode 100755
index fae580f..c062ade
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
@@ -1,255 +1,325 @@
-/***
- * 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;
 
 /**
- * A non standard class, field, method or code attribute.
- * 
+ * A non standard class, field, method or code attribute, as defined in the Java Virtual Machine
+ * Specification (JVMS).
+ *
+ * @see <a href= "https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7">JVMS
+ *     4.7</a>
+ * @see <a href= "https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.3">JVMS
+ *     4.7.3</a>
  * @author Eric Bruneton
  * @author Eugene Kuleshov
  */
 public class Attribute {
 
-    /**
-     * The type of this attribute.
-     */
-    public final String type;
-
-    /**
-     * The raw value of this attribute, used only for unknown attributes.
-     */
-    byte[] value;
-
-    /**
-     * The next attribute in this attribute list. May be <tt>null</tt>.
-     */
-    Attribute next;
-
-    /**
-     * Constructs a new empty attribute.
-     * 
-     * @param type
-     *            the type of the attribute.
-     */
-    protected Attribute(final String type) {
-        this.type = type;
-    }
+  /** The type of this attribute, also called its name in the JVMS. */
+  public final String type;
 
-    /**
-     * Returns <tt>true</tt> if this type of attribute is unknown. The default
-     * implementation of this method always returns <tt>true</tt>.
-     * 
-     * @return <tt>true</tt> if this type of attribute is unknown.
-     */
-    public boolean isUnknown() {
-        return true;
-    }
+  /**
+   * The raw content of this attribute, only used for unknown attributes (see {@link #isUnknown()}).
+   * The 6 header bytes of the attribute (attribute_name_index and attribute_length) are <i>not</i>
+   * included.
+   */
+  private byte[] content;
 
-    /**
-     * Returns <tt>true</tt> if this type of attribute is a code attribute.
-     * 
-     * @return <tt>true</tt> if this type of attribute is a code attribute.
-     */
-    public boolean isCodeAttribute() {
-        return false;
-    }
+  /**
+   * The next attribute in this attribute list (Attribute instances can be linked via this field to
+   * store a list of class, field, method or code attributes). May be {@literal null}.
+   */
+  Attribute nextAttribute;
+
+  /**
+   * Constructs a new empty attribute.
+   *
+   * @param type the type of the attribute.
+   */
+  protected Attribute(final String type) {
+    this.type = type;
+  }
+
+  /**
+   * Returns {@literal true} if this type of attribute is unknown. This means that the attribute
+   * content can't be parsed to extract constant pool references, labels, etc. Instead, the
+   * attribute content is read as an opaque byte array, and written back as is. This can lead to
+   * invalid attributes, if the content actually contains constant pool references, labels, or other
+   * symbolic references that need to be updated when there are changes to the constant pool, the
+   * method bytecode, etc. The default implementation of this method always returns {@literal true}.
+   *
+   * @return {@literal true} if this type of attribute is unknown.
+   */
+  public boolean isUnknown() {
+    return true;
+  }
+
+  /**
+   * Returns {@literal true} if this type of attribute is a code attribute.
+   *
+   * @return {@literal true} if this type of attribute is a code attribute.
+   */
+  public boolean isCodeAttribute() {
+    return false;
+  }
+
+  /**
+   * Returns the labels corresponding to this attribute.
+   *
+   * @return the labels corresponding to this attribute, or {@literal null} if this attribute is not
+   *     a code attribute that contains labels.
+   */
+  protected Label[] getLabels() {
+    return new Label[0];
+  }
 
-    /**
-     * Returns the labels corresponding to this attribute.
-     * 
-     * @return the labels corresponding to this attribute, or <tt>null</tt> if
-     *         this attribute is not a code attribute that contains labels.
-     */
-    protected Label[] getLabels() {
-        return null;
+  /**
+   * Reads a {@link #type} attribute. This method must return a <i>new</i> {@link Attribute} object,
+   * of type {@link #type}, corresponding to the 'length' bytes starting at 'offset', in the given
+   * ClassReader.
+   *
+   * @param classReader the class that contains the attribute to be read.
+   * @param offset index of the first byte of the attribute's content in {@link ClassReader#b}. The
+   *     6 attribute header bytes (attribute_name_index and attribute_length) are not taken into
+   *     account here.
+   * @param length the length of the attribute's content (excluding the 6 attribute header bytes).
+   * @param charBuffer the buffer to be used to call the ClassReader methods requiring a
+   *     'charBuffer' parameter.
+   * @param codeAttributeOffset index of the first byte of content of the enclosing Code attribute
+   *     in {@link ClassReader#b}, or -1 if the attribute to be read is not a code attribute. The 6
+   *     attribute header bytes (attribute_name_index and attribute_length) are not taken into
+   *     account here.
+   * @param labels the labels of the method's code, or {@literal null} if the attribute to be read
+   *     is not a code attribute.
+   * @return a <i>new</i> {@link Attribute} object corresponding to the specified bytes.
+   */
+  protected Attribute read(
+      final ClassReader classReader,
+      final int offset,
+      final int length,
+      final char[] charBuffer,
+      final int codeAttributeOffset,
+      final Label[] labels) {
+    Attribute attribute = new Attribute(type);
+    attribute.content = new byte[length];
+    System.arraycopy(classReader.b, offset, attribute.content, 0, length);
+    return attribute;
+  }
+
+  /**
+   * Returns the byte array form of the content of this attribute. The 6 header bytes
+   * (attribute_name_index and attribute_length) must <i>not</i> be added in the returned
+   * ByteVector.
+   *
+   * @param classWriter the class to which this attribute must be added. This parameter can be used
+   *     to add the items that corresponds to this attribute to the constant pool of this class.
+   * @param code the bytecode of the method corresponding to this code attribute, or {@literal null}
+   *     if this attribute is not a code attribute. Corresponds to the 'code' field of the Code
+   *     attribute.
+   * @param codeLength the length of the bytecode of the method corresponding to this code
+   *     attribute, or 0 if this attribute is not a code attribute. Corresponds to the 'code_length'
+   *     field of the Code attribute.
+   * @param maxStack the maximum stack size of the method corresponding to this code attribute, or
+   *     -1 if this attribute is not a code attribute.
+   * @param maxLocals the maximum number of local variables of the method corresponding to this code
+   *     attribute, or -1 if this attribute is not a code attribute.
+   * @return the byte array form of this attribute.
+   */
+  protected ByteVector write(
+      final ClassWriter classWriter,
+      final byte[] code,
+      final int codeLength,
+      final int maxStack,
+      final int maxLocals) {
+    return new ByteVector(content);
+  }
+
+  /**
+   * Returns the number of attributes of the attribute list that begins with this attribute.
+   *
+   * @return the number of attributes of the attribute list that begins with this attribute.
+   */
+  final int getAttributeCount() {
+    int count = 0;
+    Attribute attribute = this;
+    while (attribute != null) {
+      count += 1;
+      attribute = attribute.nextAttribute;
     }
+    return count;
+  }
+
+  /**
+   * Returns the total size in bytes of all the attributes in the attribute list that begins with
+   * this attribute. This size includes the 6 header bytes (attribute_name_index and
+   * attribute_length) per attribute. Also adds the attribute type names to the constant pool.
+   *
+   * @param symbolTable where the constants used in the attributes must be stored.
+   * @return the size of all the attributes in this attribute list. This size includes the size of
+   *     the attribute headers.
+   */
+  final int computeAttributesSize(final SymbolTable symbolTable) {
+    final byte[] code = null;
+    final int codeLength = 0;
+    final int maxStack = -1;
+    final int maxLocals = -1;
+    return computeAttributesSize(symbolTable, code, codeLength, maxStack, maxLocals);
+  }
 
-    /**
-     * Reads a {@link #type type} attribute. This method must return a
-     * <i>new</i> {@link Attribute} object, of type {@link #type type},
-     * corresponding to the <tt>len</tt> bytes starting at the given offset, in
-     * the given class reader.
-     * 
-     * @param cr
-     *            the class that contains the attribute to be read.
-     * @param off
-     *            index of the first byte of the attribute's content in
-     *            {@link ClassReader#b cr.b}. The 6 attribute header bytes,
-     *            containing the type and the length of the attribute, are not
-     *            taken into account here.
-     * @param len
-     *            the length of the attribute's content.
-     * @param buf
-     *            buffer to be used to call {@link ClassReader#readUTF8
-     *            readUTF8}, {@link ClassReader#readClass(int,char[]) readClass}
-     *            or {@link ClassReader#readConst readConst}.
-     * @param codeOff
-     *            index of the first byte of code's attribute content in
-     *            {@link ClassReader#b cr.b}, or -1 if the attribute to be read
-     *            is not a code attribute. The 6 attribute header bytes,
-     *            containing the type and the length of the attribute, are not
-     *            taken into account here.
-     * @param labels
-     *            the labels of the method's code, or <tt>null</tt> if the
-     *            attribute to be read is not a code attribute.
-     * @return a <i>new</i> {@link Attribute} object corresponding to the given
-     *         bytes.
-     */
-    protected Attribute read(final ClassReader cr, final int off,
-            final int len, final char[] buf, final int codeOff,
-            final Label[] labels) {
-        Attribute attr = new Attribute(type);
-        attr.value = new byte[len];
-        System.arraycopy(cr.b, off, attr.value, 0, len);
-        return attr;
+  /**
+   * Returns the total size in bytes of all the attributes in the attribute list that begins with
+   * this attribute. This size includes the 6 header bytes (attribute_name_index and
+   * attribute_length) per attribute. Also adds the attribute type names to the constant pool.
+   *
+   * @param symbolTable where the constants used in the attributes must be stored.
+   * @param code the bytecode of the method corresponding to these code attributes, or {@literal
+   *     null} if they are not code attributes. Corresponds to the 'code' field of the Code
+   *     attribute.
+   * @param codeLength the length of the bytecode of the method corresponding to these code
+   *     attributes, or 0 if they are not code attributes. Corresponds to the 'code_length' field of
+   *     the Code attribute.
+   * @param maxStack the maximum stack size of the method corresponding to these code attributes, or
+   *     -1 if they are not code attributes.
+   * @param maxLocals the maximum number of local variables of the method corresponding to these
+   *     code attributes, or -1 if they are not code attribute.
+   * @return the size of all the attributes in this attribute list. This size includes the size of
+   *     the attribute headers.
+   */
+  final int computeAttributesSize(
+      final SymbolTable symbolTable,
+      final byte[] code,
+      final int codeLength,
+      final int maxStack,
+      final int maxLocals) {
+    final ClassWriter classWriter = symbolTable.classWriter;
+    int size = 0;
+    Attribute attribute = this;
+    while (attribute != null) {
+      symbolTable.addConstantUtf8(attribute.type);
+      size += 6 + attribute.write(classWriter, code, codeLength, maxStack, maxLocals).length;
+      attribute = attribute.nextAttribute;
     }
+    return size;
+  }
 
-    /**
-     * Returns the byte array form of this attribute.
-     * 
-     * @param cw
-     *            the class to which this attribute must be added. This
-     *            parameter can be used to add to the constant pool of this
-     *            class the items that corresponds to this attribute.
-     * @param code
-     *            the bytecode of the method corresponding to this code
-     *            attribute, or <tt>null</tt> if this attribute is not a code
-     *            attributes.
-     * @param len
-     *            the length of the bytecode of the method corresponding to this
-     *            code attribute, or <tt>null</tt> if this attribute is not a
-     *            code attribute.
-     * @param maxStack
-     *            the maximum stack size of the method corresponding to this
-     *            code attribute, or -1 if this attribute is not a code
-     *            attribute.
-     * @param maxLocals
-     *            the maximum number of local variables of the method
-     *            corresponding to this code attribute, or -1 if this attribute
-     *            is not a code attribute.
-     * @return the byte array form of this attribute.
-     */
-    protected ByteVector write(final ClassWriter cw, final byte[] code,
-            final int len, final int maxStack, final int maxLocals) {
-        ByteVector v = new ByteVector();
-        v.data = value;
-        v.length = value.length;
-        return v;
+  /**
+   * Puts all the attributes of the attribute list that begins with this attribute, in the given
+   * byte vector. This includes the 6 header bytes (attribute_name_index and attribute_length) per
+   * attribute.
+   *
+   * @param symbolTable where the constants used in the attributes must be stored.
+   * @param output where the attributes must be written.
+   */
+  final void putAttributes(final SymbolTable symbolTable, final ByteVector output) {
+    final byte[] code = null;
+    final int codeLength = 0;
+    final int maxStack = -1;
+    final int maxLocals = -1;
+    putAttributes(symbolTable, code, codeLength, maxStack, maxLocals, output);
+  }
+
+  /**
+   * Puts all the attributes of the attribute list that begins with this attribute, in the given
+   * byte vector. This includes the 6 header bytes (attribute_name_index and attribute_length) per
+   * attribute.
+   *
+   * @param symbolTable where the constants used in the attributes must be stored.
+   * @param code the bytecode of the method corresponding to these code attributes, or {@literal
+   *     null} if they are not code attributes. Corresponds to the 'code' field of the Code
+   *     attribute.
+   * @param codeLength the length of the bytecode of the method corresponding to these code
+   *     attributes, or 0 if they are not code attributes. Corresponds to the 'code_length' field of
+   *     the Code attribute.
+   * @param maxStack the maximum stack size of the method corresponding to these code attributes, or
+   *     -1 if they are not code attributes.
+   * @param maxLocals the maximum number of local variables of the method corresponding to these
+   *     code attributes, or -1 if they are not code attribute.
+   * @param output where the attributes must be written.
+   */
+  final void putAttributes(
+      final SymbolTable symbolTable,
+      final byte[] code,
+      final int codeLength,
+      final int maxStack,
+      final int maxLocals,
+      final ByteVector output) {
+    final ClassWriter classWriter = symbolTable.classWriter;
+    Attribute attribute = this;
+    while (attribute != null) {
+      ByteVector attributeContent =
+          attribute.write(classWriter, code, codeLength, maxStack, maxLocals);
+      // Put attribute_name_index and attribute_length.
+      output.putShort(symbolTable.addConstantUtf8(attribute.type)).putInt(attributeContent.length);
+      output.putByteArray(attributeContent.data, 0, attributeContent.length);
+      attribute = attribute.nextAttribute;
     }
+  }
+
+  /** A set of attribute prototypes (attributes with the same type are considered equal). */
+  static final class Set {
 
-    /**
-     * Returns the length of the attribute list that begins with this attribute.
-     * 
-     * @return the length of the attribute list that begins with this attribute.
-     */
-    final int getCount() {
-        int count = 0;
-        Attribute attr = this;
-        while (attr != null) {
-            count += 1;
-            attr = attr.next;
+    private static final int SIZE_INCREMENT = 6;
+
+    private int size;
+    private Attribute[] data = new Attribute[SIZE_INCREMENT];
+
+    void addAttributes(final Attribute attributeList) {
+      Attribute attribute = attributeList;
+      while (attribute != null) {
+        if (!contains(attribute)) {
+          add(attribute);
         }
-        return count;
+        attribute = attribute.nextAttribute;
+      }
     }
 
-    /**
-     * Returns the size of all the attributes in this attribute list.
-     * 
-     * @param cw
-     *            the class writer to be used to convert the attributes into
-     *            byte arrays, with the {@link #write write} method.
-     * @param code
-     *            the bytecode of the method corresponding to these code
-     *            attributes, or <tt>null</tt> if these attributes are not code
-     *            attributes.
-     * @param len
-     *            the length of the bytecode of the method corresponding to
-     *            these code attributes, or <tt>null</tt> if these attributes
-     *            are not code attributes.
-     * @param maxStack
-     *            the maximum stack size of the method corresponding to these
-     *            code attributes, or -1 if these attributes are not code
-     *            attributes.
-     * @param maxLocals
-     *            the maximum number of local variables of the method
-     *            corresponding to these code attributes, or -1 if these
-     *            attributes are not code attributes.
-     * @return the size of all the attributes in this attribute list. This size
-     *         includes the size of the attribute headers.
-     */
-    final int getSize(final ClassWriter cw, final byte[] code, final int len,
-            final int maxStack, final int maxLocals) {
-        Attribute attr = this;
-        int size = 0;
-        while (attr != null) {
-            cw.newUTF8(attr.type);
-            size += attr.write(cw, code, len, maxStack, maxLocals).length + 6;
-            attr = attr.next;
-        }
-        return size;
+    Attribute[] toArray() {
+      Attribute[] result = new Attribute[size];
+      System.arraycopy(data, 0, result, 0, size);
+      return result;
     }
 
-    /**
-     * Writes all the attributes of this attribute list in the given byte
-     * vector.
-     * 
-     * @param cw
-     *            the class writer to be used to convert the attributes into
-     *            byte arrays, with the {@link #write write} method.
-     * @param code
-     *            the bytecode of the method corresponding to these code
-     *            attributes, or <tt>null</tt> if these attributes are not code
-     *            attributes.
-     * @param len
-     *            the length of the bytecode of the method corresponding to
-     *            these code attributes, or <tt>null</tt> if these attributes
-     *            are not code attributes.
-     * @param maxStack
-     *            the maximum stack size of the method corresponding to these
-     *            code attributes, or -1 if these attributes are not code
-     *            attributes.
-     * @param maxLocals
-     *            the maximum number of local variables of the method
-     *            corresponding to these code attributes, or -1 if these
-     *            attributes are not code attributes.
-     * @param out
-     *            where the attributes must be written.
-     */
-    final void put(final ClassWriter cw, final byte[] code, final int len,
-            final int maxStack, final int maxLocals, final ByteVector out) {
-        Attribute attr = this;
-        while (attr != null) {
-            ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
-            out.putShort(cw.newUTF8(attr.type)).putInt(b.length);
-            out.putByteArray(b.data, 0, b.length);
-            attr = attr.next;
+    private boolean contains(final Attribute attribute) {
+      for (int i = 0; i < size; ++i) {
+        if (data[i].type.equals(attribute.type)) {
+          return true;
         }
+      }
+      return false;
+    }
+
+    private void add(final Attribute attribute) {
+      if (size >= data.length) {
+        Attribute[] newData = new Attribute[data.length + SIZE_INCREMENT];
+        System.arraycopy(data, 0, newData, 0, size);
+        data = newData;
+      }
+      data[size++] = attribute;
     }
+  }
 }