changeset 6500:a40b0f51613b

7197401: Add a subset of the org.objectweb.asm packages to jdk8 Reviewed-by: ohair, briangoetz, erikj, iris
author jjh
date Sat, 20 Oct 2012 22:49:26 +0100
parents 93303f8a4a8e
children b39ab9c6f4cb
files THIRD_PARTY_README make/Makefile make/jdk/Makefile make/jdk/asm/Makefile src/share/classes/jdk/internal/org/objectweb/asm/AnnotationVisitor.java src/share/classes/jdk/internal/org/objectweb/asm/AnnotationWriter.java src/share/classes/jdk/internal/org/objectweb/asm/Attribute.java src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java src/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java src/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java src/share/classes/jdk/internal/org/objectweb/asm/Edge.java src/share/classes/jdk/internal/org/objectweb/asm/FieldVisitor.java src/share/classes/jdk/internal/org/objectweb/asm/FieldWriter.java src/share/classes/jdk/internal/org/objectweb/asm/Frame.java src/share/classes/jdk/internal/org/objectweb/asm/Handle.java src/share/classes/jdk/internal/org/objectweb/asm/Handler.java src/share/classes/jdk/internal/org/objectweb/asm/Item.java src/share/classes/jdk/internal/org/objectweb/asm/Label.java src/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java src/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java src/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java src/share/classes/jdk/internal/org/objectweb/asm/Type.java src/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java src/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java src/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java src/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java src/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java src/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java src/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java src/share/classes/jdk/internal/org/objectweb/asm/commons/Method.java src/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingClassAdapter.java src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingFieldAdapter.java src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java src/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java src/share/classes/jdk/internal/org/objectweb/asm/commons/SimpleRemapper.java src/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java src/share/classes/jdk/internal/org/objectweb/asm/commons/TableSwitchGenerator.java src/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java src/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureReader.java src/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureVisitor.java src/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureWriter.java src/share/classes/jdk/internal/org/objectweb/asm/tree/AbstractInsnNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/FieldInsnNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/FrameNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/IincInsnNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/InnerClassNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java src/share/classes/jdk/internal/org/objectweb/asm/tree/InsnNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/IntInsnNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/InvokeDynamicInsnNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/JumpInsnNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/LabelNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/LdcInsnNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/LineNumberNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/LookupSwitchInsnNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodInsnNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/MultiANewArrayInsnNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/TableSwitchInsnNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/TryCatchBlockNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/TypeInsnNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/VarInsnNode.java src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Analyzer.java src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/AnalyzerException.java src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicInterpreter.java src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicValue.java src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicVerifier.java src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Interpreter.java src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SimpleVerifier.java src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SmallSet.java src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceInterpreter.java src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceValue.java src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Subroutine.java src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Value.java src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifiable.java src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java src/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java src/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java src/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java src/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java src/share/classes/jdk/internal/org/objectweb/asm/util/CheckSignatureAdapter.java src/share/classes/jdk/internal/org/objectweb/asm/util/Printer.java src/share/classes/jdk/internal/org/objectweb/asm/util/Textifiable.java src/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java src/share/classes/jdk/internal/org/objectweb/asm/util/TraceAnnotationVisitor.java src/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java src/share/classes/jdk/internal/org/objectweb/asm/util/TraceFieldVisitor.java src/share/classes/jdk/internal/org/objectweb/asm/util/TraceMethodVisitor.java src/share/classes/jdk/internal/org/objectweb/asm/util/TraceSignatureVisitor.java src/share/lib/security/java.security src/share/lib/security/java.security-macosx src/share/lib/security/java.security-solaris src/share/lib/security/java.security-windows test/Makefile test/jdk/asm/AsmSanity.java
diffstat 104 files changed, 38511 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/THIRD_PARTY_README	Sat Oct 20 21:07:50 2012 +0100
+++ b/THIRD_PARTY_README	Sat Oct 20 22:49:26 2012 +0100
@@ -2,11 +2,11 @@
 -----------------------------
 
 %% This notice is provided with respect to ASM Bytecode Manipulation 
-Framework v3.1, which is included with JRE 7, JDK 7, and OpenJDK 7.
+Framework v4.0, which is included with JRE 8, and JDK 8.
 
 --- begin of LICENSE ---
 
-Copyright (c) 2000-2005 INRIA, France Telecom
+Copyright (c) 2000-2011 France TÚlÚcom
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
--- a/make/Makefile	Sat Oct 20 21:07:50 2012 +0100
+++ b/make/Makefile	Sat Oct 20 22:49:26 2012 +0100
@@ -233,7 +233,7 @@
 
 all build:: sanity-all post-sanity-all
 
-SUBDIRS       = tools java javax sun com
+SUBDIRS       = tools java javax sun com jdk
 ifeq ($(PLATFORM), macosx)
   SUBDIRS += apple
 endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/jdk/Makefile	Sat Oct 20 22:49:26 2012 +0100
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+#
+# Makefile for building all of java
+#
+
+BUILDDIR = ..
+PRODUCT = jdk
+include $(BUILDDIR)/common/Defs.gmk
+
+SUBDIRS = asm
+include $(BUILDDIR)/common/Subdirs.gmk
+
+all build clean clobber::
+	$(SUBDIRS-loop)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/jdk/asm/Makefile	Sat Oct 20 22:49:26 2012 +0100
@@ -0,0 +1,40 @@
+#
+# Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+BUILDDIR = ../..
+PACKAGE = jdk.internal.org.objectweb.asm
+PRODUCT = jdk
+JAVAC_LINT_OPTIONS=-Xlint:all
+include $(BUILDDIR)/common/Defs.gmk
+
+#
+# Files to compile
+#
+AUTO_FILES_JAVA_DIRS = jdk/internal/org/objectweb/asm
+
+#
+# Rules
+#
+include $(BUILDDIR)/common/Classes.gmk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/AnnotationVisitor.java	Sat Oct 20 22:49:26 2012 +0100
@@ -0,0 +1,186 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * 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 jdk.internal.org.objectweb.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>.
+ *
+ * @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}.
+     */
+    protected final int api;
+
+    /**
+     * 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}.
+     */
+    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}.
+     * @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) {
+            throw new IllegalArgumentException();
+        }*/
+        this.api = api;
+        this.av = av;
+    }
+
+    /**
+     * 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} or 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 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 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 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 the end of the annotation.
+     */
+    public void visitEnd() {
+        if (av != null) {
+            av.visitEnd();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/AnnotationWriter.java	Sat Oct 20 22:49:26 2012 +0100
@@ -0,0 +1,351 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * 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 jdk.internal.org.objectweb.asm;
+
+/**
+ * An {@link AnnotationVisitor} that generates annotations in bytecode form.
+ *
+ * @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;
+
+    /**
+     * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation
+     * writers used for annotation default and annotation arrays use unnamed
+     * values.
+     */
+    private final boolean named;
+
+    /**
+     * The annotation values in bytecode form. This byte vector only contains
+     * the values themselves, i.e. the number of values must be stored as a
+     * unsigned short just before these bytes.
+     */
+    private final ByteVector bv;
+
+    /**
+     * The byte vector to be used to store the number of values of this
+     * annotation. See {@link #bv}.
+     */
+    private final ByteVector parent;
+
+    /**
+     * Where the number of values of this annotation must be stored in
+     * {@link #parent}.
+     */
+    private final int offset;
+
+    /**
+     * Next annotation writer. This field is used to store annotation lists.
+     */
+    AnnotationWriter next;
+
+    /**
+     * Previous annotation writer. This field is used to store annotation lists.
+     */
+    AnnotationWriter prev;
+
+    // ------------------------------------------------------------------------
+    // Constructor
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructs a new {@link AnnotationWriter}.
+     *
+     * @param cw the class writer to which this annotation must be added.
+     * @param named <tt>true<tt> if values are named, <tt>false</tt> otherwise.
+     * @param bv where the annotation values must be stored.
+     * @param parent where the number of annotation values must be stored.
+     * @param offset where in <tt>parent</tt> the number of annotation values must
+     *      be stored.
+     */
+    AnnotationWriter(
+        final ClassWriter cw,
+        final boolean named,
+        final ByteVector bv,
+        final ByteVector parent,
+        final int offset)
+    {
+        super(Opcodes.ASM4);
+        this.cw = cw;
+        this.named = named;
+        this.bv = bv;
+        this.parent = parent;
+        this.offset = offset;
+    }
+
+    // ------------------------------------------------------------------------
+    // Implementation of the AnnotationVisitor abstract class
+    // ------------------------------------------------------------------------
+
+    @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);
+        }
+    }
+
+    @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 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 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 void visitEnd() {
+        if (parent != null) {
+            byte[] data = parent.data;
+            data[offset] = (byte) (size >>> 8);
+            data[offset + 1] = (byte) size;
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the size of this annotation writer list.
+     *
+     * @return the size of this annotation writer list.
+     */
+    int getSize() {
+        int size = 0;
+        AnnotationWriter aw = this;
+        while (aw != null) {
+            size += aw.bv.length;
+            aw = aw.next;
+        }
+        return size;
+    }
+
+    /**
+     * Puts the annotations of this annotation writer list into the given byte
+     * vector.
+     *
+     * @param out where the annotations must be put.
+     */
+    void put(final ByteVector out) {
+        int n = 0;
+        int size = 2;
+        AnnotationWriter aw = this;
+        AnnotationWriter last = null;
+        while (aw != null) {
+            ++n;
+            size += aw.bv.length;
+            aw.visitEnd(); // in case user forgot to call visitEnd
+            aw.prev = last;
+            last = aw;
+            aw = aw.next;
+        }
+        out.putInt(size);
+        out.putShort(n);
+        aw = last;
+        while (aw != null) {
+            out.putByteArray(aw.bv.data, 0, aw.bv.length);
+            aw = aw.prev;
+        }
+    }
+
+    /**
+     * Puts the given annotation lists into the given byte vector.
+     *
+     * @param panns an array of annotation writer lists.
+     * @param 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;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/Attribute.java	Sat Oct 20 22:49:26 2012 +0100
@@ -0,0 +1,283 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * 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 jdk.internal.org.objectweb.asm;
+
+/**
+ * A non standard class, field, method or code attribute.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class Attribute {
+
+    /**
+     * The type of this attribute.
+     */
+    public final String type;
+
+    /**
+     * The raw value of this attribute, used only for unknown attributes.
+     */
+    byte[] value;
+
+    /**
+     * The next attribute in this attribute list. May be <tt>null</tt>.
+     */
+    Attribute next;
+
+    /**
+     * Constructs a new empty attribute.
+     *
+     * @param type the type of the attribute.
+     */
+    protected Attribute(final String type) {
+        this.type = type;
+    }
+
+    /**
+     * Returns <tt>true</tt> if this type of attribute is unknown. The default
+     * implementation of this method always returns <tt>true</tt>.
+     *
+     * @return <tt>true</tt> if this type of attribute is unknown.
+     */
+    public boolean isUnknown() {
+        return true;
+    }
+
+    /**
+     * Returns <tt>true</tt> if this type of attribute is a code attribute.
+     *
+     * @return <tt>true</tt> if this type of attribute is a code attribute.
+     */
+    public boolean isCodeAttribute() {
+        return false;
+    }
+
+    /**
+     * Returns the labels corresponding to this attribute.
+     *
+     * @return the labels corresponding to this attribute, or <tt>null</tt> if
+     *         this attribute is not a code attribute that contains labels.
+     */
+    protected Label[] getLabels() {
+        return null;
+    }
+
+    /**
+     * Reads a {@link #type type} attribute. This method must return a <i>new</i>
+     * {@link Attribute} object, of type {@link #type type}, corresponding to
+     * the <tt>len</tt> bytes starting at the given offset, in the given class
+     * reader.
+     *
+     * @param cr the class that contains the attribute to be read.
+     * @param off index of the first byte of the attribute's content in {@link
+     *        ClassReader#b cr.b}. The 6 attribute header bytes, containing the
+     *        type and the length of the attribute, are not taken into account
+     *        here.
+     * @param len the length of the attribute's content.
+     * @param buf buffer to be used to call
+     *        {@link ClassReader#readUTF8 readUTF8},
+     *        {@link ClassReader#readClass(int,char[]) readClass} or
+     *        {@link ClassReader#readConst readConst}.
+     * @param codeOff index of the first byte of code's attribute content in
+     *        {@link ClassReader#b cr.b}, or -1 if the attribute to be read is
+     *        not a code attribute. The 6 attribute header bytes, containing the
+     *        type and the length of the attribute, are not taken into account
+     *        here.
+     * @param labels the labels of the method's code, or <tt>null</tt> if the
+     *        attribute to be read is not a code attribute.
+     * @return a <i>new</i> {@link Attribute} object corresponding to the given
+     *         bytes.
+     */
+    protected Attribute read(
+        final ClassReader cr,
+        final int off,
+        final int len,
+        final char[] buf,
+        final int codeOff,
+        final Label[] labels)
+    {
+        Attribute attr = new Attribute(type);
+        attr.value = new byte[len];
+        System.arraycopy(cr.b, off, attr.value, 0, len);
+        return attr;
+    }
+
+    /**
+     * Returns the byte array form of this attribute.
+     *
+     * @param cw the class to which this attribute must be added. This parameter
+     *        can be used to add to the constant pool of this class the items
+     *        that corresponds to this attribute.
+     * @param code the bytecode of the method corresponding to this code
+     *        attribute, or <tt>null</tt> if this attribute is not a code
+     *        attributes.
+     * @param len the length of the bytecode of the method corresponding to this
+     *        code attribute, or <tt>null</tt> if this attribute is not a code
+     *        attribute.
+     * @param maxStack the maximum stack size of the method corresponding to
+     *        this code attribute, or -1 if this attribute is not a code
+     *        attribute.
+     * @param maxLocals the maximum number of local variables of the method
+     *        corresponding to this code attribute, or -1 if this attribute is
+     *        not a code attribute.
+     * @return the byte array form of this attribute.
+     */
+    protected ByteVector write(
+        final ClassWriter cw,
+        final byte[] code,
+        final int len,
+        final int maxStack,
+        final int maxLocals)
+    {
+        ByteVector v = new ByteVector();
+        v.data = value;
+        v.length = value.length;
+        return v;
+    }
+
+    /**
+     * Returns the length of the attribute list that begins with this attribute.
+     *
+     * @return the length of the attribute list that begins with this attribute.
+     */
+    final int getCount() {
+        int count = 0;
+        Attribute attr = this;
+        while (attr != null) {
+            count += 1;
+            attr = attr.next;
+        }
+        return count;
+    }
+
+    /**
+     * Returns the size of all the attributes in this attribute list.
+     *
+     * @param cw the class writer to be used to convert the attributes into byte
+     *        arrays, with the {@link #write write} method.
+     * @param code the bytecode of the method corresponding to these code
+     *        attributes, or <tt>null</tt> if these attributes are not code
+     *        attributes.
+     * @param len the length of the bytecode of the method corresponding to
+     *        these code attributes, or <tt>null</tt> if these attributes are
+     *        not code attributes.
+     * @param maxStack the maximum stack size of the method corresponding to
+     *        these code attributes, or -1 if these attributes are not code
+     *        attributes.
+     * @param maxLocals the maximum number of local variables of the method
+     *        corresponding to these code attributes, or -1 if these attributes
+     *        are not code attributes.
+     * @return the size of all the attributes in this attribute list. This size
+     *         includes the size of the attribute headers.
+     */
+    final int getSize(
+        final ClassWriter cw,
+        final byte[] code,
+        final int len,
+        final int maxStack,
+        final int maxLocals)
+    {
+        Attribute attr = this;
+        int size = 0;
+        while (attr != null) {
+            cw.newUTF8(attr.type);
+            size += attr.write(cw, code, len, maxStack, maxLocals).length + 6;
+            attr = attr.next;
+        }
+        return size;
+    }
+
+    /**
+     * Writes all the attributes of this attribute list in the given byte
+     * vector.
+     *
+     * @param cw the class writer to be used to convert the attributes into byte
+     *        arrays, with the {@link #write write} method.
+     * @param code the bytecode of the method corresponding to these code
+     *        attributes, or <tt>null</tt> if these attributes are not code
+     *        attributes.
+     * @param len the length of the bytecode of the method corresponding to
+     *        these code attributes, or <tt>null</tt> if these attributes are
+     *        not code attributes.
+     * @param maxStack the maximum stack size of the method corresponding to
+     *        these code attributes, or -1 if these attributes are not code
+     *        attributes.
+     * @param maxLocals the maximum number of local variables of the method
+     *        corresponding to these code attributes, or -1 if these attributes
+     *        are not code attributes.
+     * @param out where the attributes must be written.
+     */
+    final void put(
+        final ClassWriter cw,
+        final byte[] code,
+        final int len,
+        final int maxStack,
+        final int maxLocals,
+        final ByteVector out)
+    {
+        Attribute attr = this;
+        while (attr != null) {
+            ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
+            out.putShort(cw.newUTF8(attr.type)).putInt(b.length);
+            out.putByteArray(b.data, 0, b.length);
+            attr = attr.next;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java	Sat Oct 20 22:49:26 2012 +0100
@@ -0,0 +1,322 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * 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 jdk.internal.org.objectweb.asm;
+
+/**
+ * A dynamically extensible vector of bytes. This class is roughly equivalent to
+ * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
+ *
+ * @author Eric Bruneton
+ */
+public class ByteVector {
+
+    /**
+     * The content of this vector.
+     */
+    byte[] data;
+
+    /**
+     * Actual number of bytes in this vector.
+     */
+    int length;
+
+    /**
+     * Constructs a new {@link ByteVector ByteVector} with a default initial
+     * size.
+     */
+    public ByteVector() {
+        data = new byte[64];
+    }
+
+    /**
+     * Constructs a new {@link ByteVector ByteVector} with the given initial
+     * size.
+     *
+     * @param initialSize the initial size of the byte vector to be constructed.
+     */
+    public ByteVector(final int initialSize) {
+        data = new byte[initialSize];
+    }
+
+    /**
+     * Puts a byte into this byte vector. The byte vector is automatically
+     * enlarged if necessary.
+     *
+     * @param b a byte.
+     * @return this byte vector.
+     */
+    public ByteVector putByte(final int b) {
+        int length = this.length;
+        if (length + 1 > data.length) {
+            enlarge(1);
+        }
+        data[length++] = (byte) b;
+        this.length = length;
+        return this;
+    }
+
+    /**
+     * Puts two bytes into this byte vector. The byte vector is automatically
+     * enlarged if necessary.
+     *
+     * @param b1 a byte.
+     * @param b2 another byte.
+     * @return this byte vector.
+     */
+    ByteVector put11(final int b1, final int b2) {
+        int length = this.length;
+        if (length + 2 > data.length) {
+            enlarge(2);
+        }
+        byte[] data = this.data;
+        data[length++] = (byte) b1;
+        data[length++] = (byte) b2;
+        this.length = length;
+        return this;
+    }
+
+    /**
+     * Puts a short into this byte vector. The byte vector is automatically
+     * enlarged if necessary.
+     *
+     * @param s a short.
+     * @return this byte vector.
+     */
+    public ByteVector putShort(final int s) {
+        int length = this.length;
+        if (length + 2 > data.length) {
+            enlarge(2);
+        }
+        byte[] data = this.data;
+        data[length++] = (byte) (s >>> 8);
+        data[length++] = (byte) s;
+        this.length = length;
+        return this;
+    }
+
+    /**
+     * Puts a byte and a short into this byte vector. The byte vector is
+     * automatically enlarged if necessary.
+     *
+     * @param b a byte.
+     * @param s a short.
+     * @return this byte vector.
+     */
+    ByteVector put12(final int b, final int s) {
+        int length = this.length;
+        if (length + 3 > data.length) {
+            enlarge(3);
+        }
+        byte[] data = this.data;
+        data[length++] = (byte) b;
+        data[length++] = (byte) (s >>> 8);
+        data[length++] = (byte) s;
+        this.length = length;
+        return this;
+    }
+
+    /**
+     * Puts an int into this byte vector. The byte vector is automatically
+     * enlarged if necessary.
+     *
+     * @param i an int.
+     * @return this byte vector.
+     */
+    public ByteVector putInt(final int i) {
+        int length = this.length;
+        if (length + 4 > data.length) {
+            enlarge(4);
+        }
+        byte[] data = this.data;
+        data[length++] = (byte) (i >>> 24);
+        data[length++] = (byte) (i >>> 16);
+        data[length++] = (byte) (i >>> 8);
+        data[length++] = (byte) i;
+        this.length = length;
+        return this;
+    }
+
+    /**
+     * Puts a long into this byte vector. The byte vector is automatically
+     * enlarged if necessary.
+     *
+     * @param l a long.
+     * @return this byte vector.
+     */
+    public ByteVector putLong(final long l) {
+        int length = this.length;
+        if (length + 8 > data.length) {
+            enlarge(8);
+        }
+        byte[] data = this.data;
+        int i = (int) (l >>> 32);
+        data[length++] = (byte) (i >>> 24);
+        data[length++] = (byte) (i >>> 16);
+        data[length++] = (byte) (i >>> 8);
+        data[length++] = (byte) i;
+        i = (int) l;
+        data[length++] = (byte) (i >>> 24);
+        data[length++] = (byte) (i >>> 16);
+        data[length++] = (byte) (i >>> 8);
+        data[length++] = (byte) i;
+        this.length = length;
+        return this;
+    }
+
+    /**
+     * Puts an UTF8 string into this byte vector. The byte vector is
+     * automatically enlarged if necessary.
+     *
+     * @param s a String.
+     * @return this byte vector.
+     */
+    public ByteVector putUTF8(final String s) {
+        int charLength = s.length();
+        int len = length;
+        if (len + 2 + charLength > data.length) {
+            enlarge(2 + charLength);
+        }
+        byte[] data = this.data;
+        // optimistic algorithm: instead of computing the byte length and then
+        // serializing the string (which requires two loops), we assume the byte
+        // length is equal to char length (which is the most frequent case), and
+        // we start serializing the string right away. During the serialization,
+        // if we find that this assumption is wrong, we continue with the
+        // general method.
+        data[len++] = (byte) (charLength >>> 8);
+        data[len++] = (byte) charLength;
+        for (int i = 0; i < charLength; ++i) {
+            char c = s.charAt(i);
+            if (c >= '\001' && c <= '\177') {
+                data[len++] = (byte) c;
+            } else {
+                int byteLength = i;
+                for (int j = i; j < charLength; ++j) {
+                    c = s.charAt(j);
+                    if (c >= '\001' && c <= '\177') {
+                        byteLength++;
+                    } else if (c > '\u07FF') {
+                        byteLength += 3;
+                    } else {
+                        byteLength += 2;
+                    }
+                }
+                data[length] = (byte) (byteLength >>> 8);
+                data[length + 1] = (byte) byteLength;
+                if (length + 2 + byteLength > data.length) {
+                    length = len;
+                    enlarge(2 + byteLength);
+                    data = this.data;
+                }
+                for (int j = i; j < charLength; ++j) {
+                    c = s.charAt(j);
+                    if (c >= '\001' && c <= '\177') {
+                        data[len++] = (byte) c;
+                    } else if (c > '\u07FF') {
+                        data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
+                        data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
+                        data[len++] = (byte) (0x80 | c & 0x3F);
+                    } else {
+                        data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
+                        data[len++] = (byte) (0x80 | c & 0x3F);
+                    }
+                }
+                break;
+            }
+        }
+        length = len;
+        return this;
+    }
+
+    /**
+     * Puts an array of bytes into this byte vector. The byte vector is
+     * automatically enlarged if necessary.
+     *
+     * @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
+     *        null bytes into this byte vector.
+     * @param off index of the fist byte of b that must be copied.
+     * @param len number of bytes of b that must be copied.
+     * @return this byte vector.
+     */
+    public ByteVector putByteArray(final byte[] b, final int off, final int len)
+    {
+        if (length + len > data.length) {
+            enlarge(len);
+        }
+        if (b != null) {
+            System.arraycopy(b, off, data, length, len);
+        }
+        length += len;
+        return this;
+    }
+
+    /**
+     * Enlarge this byte vector so that it can receive n more bytes.
+     *
+     * @param size number of additional bytes that this byte vector should be
+     *        able to receive.
+     */
+    private void enlarge(final int size) {
+        int length1 = 2 * data.length;
+        int length2 = length + size;
+        byte[] newData = new byte[length1 > length2 ? length1 : length2];
+        System.arraycopy(data, 0, newData, 0, length);
+        data = newData;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java	Sat Oct 20 22:49:26 2012 +0100
@@ -0,0 +1,2245 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * 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 jdk.internal.org.objectweb.asm;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A Java class parser to make a {@link ClassVisitor} visit an existing class.
+ * This class parses a byte array conforming to the Java class file format and
+ * calls the appropriate visit methods of a given class visitor for each field,
+ * method and bytecode instruction encountered.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class ClassReader {
+
+    /**
+     * True to enable signatures support.
+     */
+    static final boolean SIGNATURES = true;
+
+    /**
+     * True to enable annotations support.
+     */
+    static final boolean ANNOTATIONS = true;
+
+    /**
+     * True to enable stack map frames support.
+     */
+    static final boolean FRAMES = true;
+
+    /**
+     * True to enable bytecode writing support.
+     */
+    static final boolean WRITER = true;
+
+    /**
+     * True to enable JSR_W and GOTO_W support.
+     */
+    static final boolean RESIZE = true;
+
+    /**
+     * Flag to skip method code. If this class is set <code>CODE</code>
+     * attribute won't be visited. This can be used, for example, to retrieve
+     * annotations for methods and method parameters.
+     */
+    public static final int SKIP_CODE = 1;
+
+    /**
+     * Flag to skip the debug information in the class. If this flag is set the
+     * debug information of the class is not visited, i.e. the
+     * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
+     * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be
+     * called.
+     */
+    public static final int SKIP_DEBUG = 2;
+
+    /**
+     * Flag to skip the stack map frames in the class. If this flag is set the
+     * stack map frames of the class is not visited, i.e. the
+     * {@link MethodVisitor#visitFrame visitFrame} method will not be called.
+     * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is
+     * used: it avoids visiting frames that will be ignored and recomputed from
+     * scratch in the class writer.
+     */
+    public static final int SKIP_FRAMES = 4;
+
+    /**
+     * Flag to expand the stack map frames. By default stack map frames are
+     * visited in their original format (i.e. "expanded" for classes whose
+     * version is less than V1_6, and "compressed" for the other classes). If
+     * this flag is set, stack map frames are always visited in expanded format
+     * (this option adds a decompression/recompression step in ClassReader and
+     * ClassWriter which degrades performances quite a lot).
+     */
+    public static final int EXPAND_FRAMES = 8;
+
+    /**
+     * The class to be parsed. <i>The content of this array must not be
+     * modified. This field is intended for {@link Attribute} sub classes, and
+     * is normally not needed by class generators or adapters.</i>
+     */
+    public final byte[] b;
+
+    /**
+     * The start index of each constant pool item in {@link #b b}, plus one.
+     * The one byte offset skips the constant pool item tag that indicates its
+     * type.
+     */
+    private final int[] items;
+
+    /**
+     * The String objects corresponding to the CONSTANT_Utf8 items. This cache
+     * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
+     * which GREATLY improves performances (by a factor 2 to 3). This caching
+     * strategy could be extended to all constant pool items, but its benefit
+     * would not be so great for these items (because they are much less
+     * expensive to parse than CONSTANT_Utf8 items).
+     */
+    private final String[] strings;
+
+    /**
+     * Maximum length of the strings contained in the constant pool of the
+     * class.
+     */
+    private final int maxStringLength;
+
+    /**
+     * Start index of the class header information (access, name...) in
+     * {@link #b b}.
+     */
+    public final int header;
+
+    // ------------------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructs a new {@link ClassReader} object.
+     *
+     * @param b the bytecode of the class to be read.
+     */
+    public ClassReader(final byte[] b) {
+        this(b, 0, b.length);
+    }
+
+    /**
+     * Constructs a new {@link ClassReader} object.
+     *
+     * @param b the bytecode of the class to be read.
+     * @param off the start offset of the class data.
+     * @param len the length of the class data.
+     */
+    public ClassReader(final byte[] b, final int off, final int len) {
+        this.b = b;
+        // checks the class version
+        if (readShort(6) > Opcodes.V1_7) {
+            throw new IllegalArgumentException();
+        }
+        // parses the constant pool
+        items = new int[readUnsignedShort(off + 8)];
+        int n = items.length;
+        strings = new String[n];
+        int max = 0;
+        int index = off + 10;
+        for (int i = 1; i < n; ++i) {
+            items[i] = index + 1;
+            int size;
+            switch (b[index]) {
+                case ClassWriter.FIELD:
+                case ClassWriter.METH:
+                case ClassWriter.IMETH:
+                case ClassWriter.INT:
+                case ClassWriter.FLOAT:
+                case ClassWriter.NAME_TYPE:
+                case ClassWriter.INDY:
+                    size = 5;
+                    break;
+                case ClassWriter.LONG:
+                case ClassWriter.DOUBLE:
+                    size = 9;
+                    ++i;
+                    break;
+                case ClassWriter.UTF8:
+                    size = 3 + readUnsignedShort(index + 1);
+                    if (size > max) {
+                        max = size;
+                    }
+                    break;
+                case ClassWriter.HANDLE:
+                    size = 4;
+                    break;
+                // case ClassWriter.CLASS:
+                // case ClassWriter.STR:
+                // case ClassWriter.MTYPE
+                default:
+                    size = 3;
+                    break;
+            }
+            index += size;
+        }
+        maxStringLength = max;
+        // the class header information starts just after the constant pool
+        header = index;
+    }
+
+    /**
+     * Returns the class's access flags (see {@link Opcodes}). This value may
+     * not reflect Deprecated and Synthetic flags when bytecode is before 1.5
+     * and those flags are represented by attributes.
+     *
+     * @return the class access flags
+     *
+     * @see ClassVisitor#visit(int, int, String, String, String, String[])
+     */
+    public int getAccess() {
+        return readUnsignedShort(header);
+    }
+
+    /**
+     * Returns the internal name of the class (see
+     * {@link Type#getInternalName() getInternalName}).
+     *
+     * @return the internal class name
+     *
+     * @see ClassVisitor#visit(int, int, String, String, String, String[])
+     */
+    public String getClassName() {
+        return readClass(header + 2, new char[maxStringLength]);
+    }
+
+    /**
+     * Returns the internal of name of the super class (see
+     * {@link Type#getInternalName() getInternalName}). For interfaces, the
+     * super class is {@link Object}.
+     *
+     * @return the internal name of super class, or <tt>null</tt> for
+     *         {@link Object} class.
+     *
+     * @see ClassVisitor#visit(int, int, String, String, String, String[])
+     */
+    public String getSuperName() {
+        int n = items[readUnsignedShort(header + 4)];
+        return n == 0 ? null : readUTF8(n, new char[maxStringLength]);
+    }
+
+    /**
+     * Returns the internal names of the class's interfaces (see
+     * {@link Type#getInternalName() getInternalName}).
+     *
+     * @return the array of internal names for all implemented interfaces or
+     *         <tt>null</tt>.
+     *
+     * @see ClassVisitor#visit(int, int, String, String, String, String[])
+     */
+    public String[] getInterfaces() {
+        int index = header + 6;
+        int n = readUnsignedShort(index);
+        String[] interfaces = new String[n];
+        if (n > 0) {
+            char[] buf = new char[maxStringLength];
+            for (int i = 0; i < n; ++i) {
+                index += 2;
+                interfaces[i] = readClass(index, buf);
+            }
+        }
+        return interfaces;
+    }
+
+    /**
+     * Copies the constant pool data into the given {@link ClassWriter}. Should
+     * be called before the {@link #accept(ClassVisitor,int)} method.
+     *
+     * @param classWriter the {@link ClassWriter} to copy constant pool into.
+     */
+    void copyPool(final ClassWriter classWriter) {
+        char[] buf = new char[maxStringLength];
+        int ll = items.length;
+        Item[] items2 = new Item[ll];
+        for (int i = 1; i < ll; i++) {
+            int index = items[i];
+            int tag = b[index - 1];
+            Item item = new Item(i);
+            int nameType;
+            switch (tag) {
+                case ClassWriter.FIELD:
+                case ClassWriter.METH:
+                case ClassWriter.IMETH:
+                    nameType = items[readUnsignedShort(index + 2)];
+                    item.set(tag,
+                            readClass(index, buf),
+                            readUTF8(nameType, buf),
+                            readUTF8(nameType + 2, buf));
+                    break;
+
+                case ClassWriter.INT:
+                    item.set(readInt(index));
+                    break;
+
+                case ClassWriter.FLOAT:
+                    item.set(Float.intBitsToFloat(readInt(index)));
+                    break;
+
+                case ClassWriter.NAME_TYPE:
+                    item.set(tag,
+                            readUTF8(index, buf),
+                            readUTF8(index + 2, buf),
+                            null);
+                    break;
+
+                case ClassWriter.LONG:
+                    item.set(readLong(index));
+                    ++i;
+                    break;
+
+                case ClassWriter.DOUBLE:
+                    item.set(Double.longBitsToDouble(readLong(index)));
+                    ++i;
+                    break;
+
+                case ClassWriter.UTF8: {
+                    String s = strings[i];
+                    if (s == null) {
+                        index = items[i];
+                        s = strings[i] = readUTF(index + 2,
+                                readUnsignedShort(index),
+                                buf);
+                    }
+                    item.set(tag, s, null, null);
+                }
+                    break;
+
+                case ClassWriter.HANDLE: {
+                    int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
+                    nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
+                    item.set(ClassWriter.HANDLE_BASE + readByte(index),
+                            readClass(fieldOrMethodRef, buf),
+                            readUTF8(nameType, buf),
+                            readUTF8(nameType + 2, buf));
+
+                }
+                    break;
+
+
+                case ClassWriter.INDY:
+                    if (classWriter.bootstrapMethods == null) {
+                        copyBootstrapMethods(classWriter, items2, buf);
+                    }
+                    nameType = items[readUnsignedShort(index + 2)];
+                    item.set(readUTF8(nameType, buf),
+                            readUTF8(nameType + 2, buf),
+                            readUnsignedShort(index));
+                    break;
+
+
+                // case ClassWriter.STR:
+                // case ClassWriter.CLASS:
+                // case ClassWriter.MTYPE
+                default:
+                    item.set(tag, readUTF8(index, buf), null, null);
+                    break;
+            }
+
+            int index2 = item.hashCode % items2.length;
+            item.next = items2[index2];
+            items2[index2] = item;
+        }
+
+        int off = items[1] - 1;
+        classWriter.pool.putByteArray(b, off, header - off);
+        classWriter.items = items2;
+        classWriter.threshold = (int) (0.75d * ll);
+        classWriter.index = ll;
+    }
+
+    private void copyBootstrapMethods(ClassWriter classWriter, Item[] items2, char[] buf) {
+        int i, j, k, u, v;
+
+        // skip class header
+        v = header;
+        v += 8 + (readUnsignedShort(v + 6) << 1);
+
+        // skips fields and methods
+        i = readUnsignedShort(v);
+        v += 2;
+        for (; i > 0; --i) {
+            j = readUnsignedShort(v + 6);
+            v += 8;
+            for (; j > 0; --j) {
+                v += 6 + readInt(v + 2);
+            }
+        }
+        i = readUnsignedShort(v);
+        v += 2;
+        for (; i > 0; --i) {
+            j = readUnsignedShort(v + 6);
+            v += 8;
+            for (; j > 0; --j) {
+                v += 6 + readInt(v + 2);
+            }
+        }
+
+        // read class attributes
+        i = readUnsignedShort(v);
+        v += 2;
+        for (; i > 0; --i) {
+            String attrName = readUTF8(v, buf);
+            int size = readInt(v + 2);
+            if ("BootstrapMethods".equals(attrName)) {
+                int boostrapMethodCount = readUnsignedShort(v + 6);
+                int x = v + 8;
+                for (j = 0; j < boostrapMethodCount; j++) {
+                    int hashCode = readConst(readUnsignedShort(x), buf).hashCode();
+                    k = readUnsignedShort(x + 2);
+                    u = x + 4;
+                    for(; k > 0; --k) {
+                        hashCode ^= readConst(readUnsignedShort(u), buf).hashCode();
+                        u += 2;
+                    }
+                    Item item = new Item(j);
+                    item.set(x - v - 8, hashCode & 0x7FFFFFFF);
+
+                    int index2 = item.hashCode % items2.length;
+                    item.next = items2[index2];
+                    items2[index2] = item;
+
+                    x = u;
+                }
+
+                classWriter.bootstrapMethodsCount = boostrapMethodCount;
+                ByteVector bootstrapMethods = new ByteVector(size + 62);
+                bootstrapMethods.putByteArray(b, v + 8, size - 2);
+                classWriter.bootstrapMethods = bootstrapMethods;
+                return;
+            }
+            v += 6 + size;
+        }
+
+        // we are in trouble !!!
+    }
+
+    /**
+     * Constructs a new {@link ClassReader} object.
+     *
+     * @param is an input stream from which to read the class.
+     * @throws IOException if a problem occurs during reading.
+     */
+    public ClassReader(final InputStream is) throws IOException {
+        this(readClass(is, false));
+    }
+
+    /**
+     * Constructs a new {@link ClassReader} object.
+     *
+     * @param name the binary qualified name of the class to be read.
+     * @throws IOException if an exception occurs during reading.
+     */
+    public ClassReader(final String name) throws IOException {
+        this(readClass(ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
+                + ".class"), true));
+    }
+
+    /**
+     * Reads the bytecode of a class.
+     *
+     * @param is an input stream from which to read the class.
+     * @param close true to close the input stream after reading.
+     * @return the bytecode read from the given input stream.
+     * @throws IOException if a problem occurs during reading.
+     */
+    private static byte[] readClass(final InputStream is, boolean close)
+            throws IOException
+    {
+        if (is == null) {
+            throw new IOException("Class not found");
+        }
+        try {
+            byte[] b = new byte[is.available()];
+            int len = 0;
+            while (true) {
+                int n = is.read(b, len, b.length - len);
+                if (n == -1) {
+                    if (len < b.length) {
+                        byte[] c = new byte[len];
+                        System.arraycopy(b, 0, c, 0, len);
+                        b = c;
+                    }
+                    return b;
+                }
+                len += n;
+                if (len == b.length) {
+                    int last = is.read();
+                    if (last < 0) {
+                        return b;
+                    }
+                    byte[] c = new byte[b.length + 1000];
+                    System.arraycopy(b, 0, c, 0, len);
+                    c[len++] = (byte) last;
+                    b = c;
+                }
+            }
+        } finally {
+            if (close) {
+                is.close();
+            }
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Public methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Makes the given visitor visit the Java class of this {@link ClassReader}.
+     * This class is the one specified in the constructor (see
+     * {@link #ClassReader(byte[]) ClassReader}).
+     *
+     * @param classVisitor the visitor that must visit this class.
+     * @param flags option flags that can be used to modify the default behavior
+     *        of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
+     *        {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+     */
+    public void accept(final ClassVisitor classVisitor, final int flags) {
+        accept(classVisitor, new Attribute[0], flags);
+    }
+
+    /**
+     * Makes the given visitor visit the Java class of this {@link ClassReader}.
+     * This class is the one specified in the constructor (see
+     * {@link #ClassReader(byte[]) ClassReader}).
+     *
+     * @param classVisitor the visitor that must visit this class.
+     * @param attrs prototypes of the attributes that must be parsed during the
+     *        visit of the class. Any attribute whose type is not equal to the
+     *        type of one the prototypes will not be parsed: its byte array
+     *        value will be passed unchanged to the ClassWriter. <i>This may
+     *        corrupt it if this value contains references to the constant pool,
+     *        or has syntactic or semantic links with a class element that has
+     *        been transformed by a class adapter between the reader and the
+     *        writer</i>.
+     * @param flags option flags that can be used to modify the default behavior
+     *        of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
+     *        {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+     */
+    public void accept(
+        final ClassVisitor classVisitor,
+        final Attribute[] attrs,
+        final int flags)
+    {
+        byte[] b = this.b; // the bytecode array
+        char[] c = new char[maxStringLength]; // buffer used to read strings
+        int i, j, k; // loop variables
+        int u, v, w; // indexes in b
+        Attribute attr;
+
+        int access;
+        String name;
+        String desc;
+        String attrName;
+        String signature;
+        int anns = 0;
+        int ianns = 0;
+        Attribute cattrs = null;
+
+        // visits the header
+        u = header;
+        access = readUnsignedShort(u);
+        name = readClass(u + 2, c);
+        v = items[readUnsignedShort(u + 4)];
+        String superClassName = v == 0 ? null : readUTF8(v, c);
+        String[] implementedItfs = new String[readUnsignedShort(u + 6)];
+        w = 0;
+        u += 8;
+        for (i = 0; i < implementedItfs.length; ++i) {
+            implementedItfs[i] = readClass(u, c);
+            u += 2;
+        }
+
+        boolean skipCode = (flags & SKIP_CODE) != 0;
+        boolean skipDebug = (flags & SKIP_DEBUG) != 0;
+        boolean unzip = (flags & EXPAND_FRAMES) != 0;
+
+        // skips fields and methods
+        v = u;
+        i = readUnsignedShort(v);
+        v += 2;
+        for (; i > 0; --i) {
+            j = readUnsignedShort(v + 6);
+            v += 8;
+            for (; j > 0; --j) {
+                v += 6 + readInt(v + 2);
+            }
+        }
+        i = readUnsignedShort(v);
+        v += 2;
+        for (; i > 0; --i) {
+            j = readUnsignedShort(v + 6);
+            v += 8;
+            for (; j > 0; --j) {
+                v += 6 + readInt(v + 2);
+            }
+        }
+        // reads the class's attributes
+        signature = null;
+        String sourceFile = null;
+        String sourceDebug = null;
+        String enclosingOwner = null;
+        String enclosingName = null;
+        String enclosingDesc = null;
+        int[] bootstrapMethods = null;  // start indexed of the bsms
+
+        i = readUnsignedShort(v);
+        v += 2;
+        for (; i > 0; --i) {
+            attrName = readUTF8(v, c);
+            // tests are sorted in decreasing frequency order
+            // (based on frequencies observed on typical classes)
+            if ("SourceFile".equals(attrName)) {
+                sourceFile = readUTF8(v + 6, c);
+            } else if ("InnerClasses".equals(attrName)) {
+                w = v + 6;
+            } else if ("EnclosingMethod".equals(attrName)) {
+                enclosingOwner = readClass(v + 6, c);
+                int item = readUnsignedShort(v + 8);
+                if (item != 0) {
+                    enclosingName = readUTF8(items[item], c);
+                    enclosingDesc = readUTF8(items[item] + 2, c);
+                }
+            } else if (SIGNATURES && "Signature".equals(attrName)) {
+                signature = readUTF8(v + 6, c);
+            } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
+                anns = v + 6;
+            } else if ("Deprecated".equals(attrName)) {
+                access |= Opcodes.ACC_DEPRECATED;
+            } else if ("Synthetic".equals(attrName)) {
+                access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+            } else if ("SourceDebugExtension".equals(attrName)) {
+                int len = readInt(v + 2);
+                sourceDebug = readUTF(v + 6, len, new char[len]);
+            } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
+                ianns = v + 6;
+            } else if ("BootstrapMethods".equals(attrName)) {
+                int boostrapMethodCount = readUnsignedShort(v + 6);
+                bootstrapMethods = new int[boostrapMethodCount];
+                int x = v + 8;
+                for (j = 0; j < boostrapMethodCount; j++) {
+                    bootstrapMethods[j] = x;
+                    x += 2 + readUnsignedShort(x + 2) << 1;
+                }
+            } else {
+                attr = readAttribute(attrs,
+                        attrName,
+                        v + 6,
+                        readInt(v + 2),
+                        c,
+                        -1,
+                        null);
+                if (attr != null) {
+                    attr.next = cattrs;
+                    cattrs = attr;
+                }
+            }
+            v += 6 + readInt(v + 2);
+        }
+        // calls the visit method
+        classVisitor.visit(readInt(4),
+                access,
+                name,
+                signature,
+                superClassName,
+                implementedItfs);
+
+        // calls the visitSource method
+        if (!skipDebug && (sourceFile != null || sourceDebug != null)) {
+            classVisitor.visitSource(sourceFile, sourceDebug);
+        }
+
+        // calls the visitOuterClass method
+        if (enclosingOwner != null) {
+            classVisitor.visitOuterClass(enclosingOwner,
+                    enclosingName,
+                    enclosingDesc);
+        }
+
+        // visits the class annotations
+        if (ANNOTATIONS) {
+            for (i = 1; i >= 0; --i) {
+                v = i == 0 ? ianns : anns;
+                if (v != 0) {
+                    j = readUnsignedShort(v);
+                    v += 2;
+                    for (; j > 0; --j) {
+                        v = readAnnotationValues(v + 2,
+                                c,
+                                true,
+                                classVisitor.visitAnnotation(readUTF8(v, c), i != 0));
+                    }
+                }
+            }
+        }
+
+        // visits the class attributes
+        while (cattrs != null) {
+            attr = cattrs.next;
+            cattrs.next = null;
+            classVisitor.visitAttribute(cattrs);
+            cattrs = attr;
+        }
+
+        // calls the visitInnerClass method
+        if (w != 0) {
+            i = readUnsignedShort(w);
+            w += 2;
+            for (; i > 0; --i) {
+                classVisitor.visitInnerClass(readUnsignedShort(w) == 0
+                        ? null
+                        : readClass(w, c), readUnsignedShort(w + 2) == 0
+                        ? null
+                        : readClass(w + 2, c), readUnsignedShort(w + 4) == 0
+                        ? null
+                        : readUTF8(w + 4, c), readUnsignedShort(w + 6));
+                w += 8;
+            }
+        }
+
+        // visits the fields
+        i = readUnsignedShort(u);
+        u += 2;
+        for (; i > 0; --i) {
+            access = readUnsignedShort(u);
+            name = readUTF8(u + 2, c);
+            desc = readUTF8(u + 4, c);
+            // visits the field's attributes and looks for a ConstantValue
+            // attribute
+            int fieldValueItem = 0;
+            signature = null;
+            anns = 0;
+            ianns = 0;
+            cattrs = null;
+
+            j = readUnsignedShort(u + 6);
+            u += 8;
+            for (; j > 0; --j) {
+                attrName = readUTF8(u, c);
+                // tests are sorted in decreasing frequency order
+                // (based on frequencies observed on typical classes)
+                if ("ConstantValue".equals(attrName)) {
+                    fieldValueItem = readUnsignedShort(u + 6);
+                } else if (SIGNATURES && "Signature".equals(attrName)) {
+                    signature = readUTF8(u + 6, c);
+                } else if ("Deprecated".equals(attrName)) {
+                    access |= Opcodes.ACC_DEPRECATED;
+                } else if ("Synthetic".equals(attrName)) {
+                    access |= Opcodes.ACC_SYNTHETIC  | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+                } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
+                    anns = u + 6;
+                } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
+                    ianns = u + 6;
+                } else {
+                    attr = readAttribute(attrs,
+                            attrName,
+                            u + 6,
+                            readInt(u + 2),
+                            c,
+                            -1,
+                            null);
+                    if (attr != null) {
+                        attr.next = cattrs;
+                        cattrs = attr;
+                    }
+                }
+                u += 6 + readInt(u + 2);
+            }
+            // visits the field
+            FieldVisitor fv = classVisitor.visitField(access,
+                    name,
+                    desc,
+                    signature,
+                    fieldValueItem == 0 ? null : readConst(fieldValueItem, c));
+            // visits the field annotations and attributes
+            if (fv != null) {
+                if (ANNOTATIONS) {
+                    for (j = 1; j >= 0; --j) {
+                        v = j == 0 ? ianns : anns;
+                        if (v != 0) {
+                            k = readUnsignedShort(v);
+                            v += 2;
+                            for (; k > 0; --k) {
+                                v = readAnnotationValues(v + 2,
+                                        c,
+                                        true,
+                                        fv.visitAnnotation(readUTF8(v, c), j != 0));
+                            }
+                        }
+                    }
+                }
+                while (cattrs != null) {
+                    attr = cattrs.next;
+                    cattrs.next = null;
+                    fv.visitAttribute(cattrs);
+                    cattrs = attr;
+                }
+                fv.visitEnd();
+            }
+        }
+
+        // visits the methods
+        i = readUnsignedShort(u);
+        u += 2;
+        for (; i > 0; --i) {
+            int u0 = u + 6;
+            access = readUnsignedShort(u);
+            name = readUTF8(u + 2, c);
+            desc = readUTF8(u + 4, c);
+            signature = null;
+            anns = 0;
+            ianns = 0;
+            int dann = 0;
+            int mpanns = 0;
+            int impanns = 0;
+            cattrs = null;
+            v = 0;
+            w = 0;
+
+            // looks for Code and Exceptions attributes
+            j = readUnsignedShort(u + 6);
+            u += 8;
+            for (; j > 0; --j) {
+                attrName = readUTF8(u, c);
+                int attrSize = readInt(u + 2);
+                u += 6;
+                // tests are sorted in decreasing frequency order
+                // (based on frequencies observed on typical classes)
+                if ("Code".equals(attrName)) {
+                    if (!skipCode) {
+                        v = u;
+                    }
+                } else if ("Exceptions".equals(attrName)) {
+                    w = u;
+                } else if (SIGNATURES && "Signature".equals(attrName)) {
+                    signature = readUTF8(u, c);
+                } else if ("Deprecated".equals(attrName)) {
+                    access |= Opcodes.ACC_DEPRECATED;
+                } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
+                    anns = u;
+                } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
+                    dann = u;
+                } else if ("Synthetic".equals(attrName)) {
+                    access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+                } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
+                    ianns = u;
+                } else if (ANNOTATIONS && "RuntimeVisibleParameterAnnotations".equals(attrName))
+                {
+                    mpanns = u;
+                } else if (ANNOTATIONS && "RuntimeInvisibleParameterAnnotations".equals(attrName))
+                {
+                    impanns = u;
+                } else {
+                    attr = readAttribute(attrs,
+                            attrName,
+                            u,
+                            attrSize,
+                            c,
+                            -1,
+                            null);
+                    if (attr != null) {
+                        attr.next = cattrs;
+                        cattrs = attr;
+                    }
+                }
+                u += attrSize;
+            }
+            // reads declared exceptions
+            String[] exceptions;
+            if (w == 0) {
+                exceptions = null;
+            } else {
+                exceptions = new String[readUnsignedShort(w)];
+                w += 2;
+                for (j = 0; j < exceptions.length; ++j) {
+                    exceptions[j] = readClass(w, c);
+                    w += 2;
+                }
+            }
+
+            // visits the method's code, if any
+            MethodVisitor mv = classVisitor.visitMethod(access,
+                    name,
+                    desc,
+                    signature,
+                    exceptions);
+
+            if (mv != null) {
+                /*
+                 * if the returned MethodVisitor is in fact a MethodWriter, it
+                 * means there is no method adapter between the reader and the
+                 * writer. If, in addition, the writer's constant pool was
+                 * copied from this reader (mw.cw.cr == this), and the signature
+                 * and exceptions of the method have not been changed, then it
+                 * is possible to skip all visit events and just copy the
+                 * original code of the method to the writer (the access, name
+                 * and descriptor can have been changed, this is not important
+                 * since they are not copied as is from the reader).
+                 */
+                if (WRITER && mv instanceof MethodWriter) {
+                    MethodWriter mw = (MethodWriter) mv;
+                    if (mw.cw.cr == this) {
+                        if (signature == mw.signature) {
+                            boolean sameExceptions = false;
+                            if (exceptions == null) {
+                                sameExceptions = mw.exceptionCount == 0;
+                            } else {
+                                if (exceptions.length == mw.exceptionCount) {
+                                    sameExceptions = true;
+                                    for (j = exceptions.length - 1; j >= 0; --j)
+                                    {
+                                        w -= 2;
+                                        if (mw.exceptions[j] != readUnsignedShort(w))
+                                        {
+                                            sameExceptions = false;
+                                            break;
+                                        }
+                                    }
+                                }
+                            }
+                            if (sameExceptions) {
+                                /*
+                                 * we do not copy directly the code into
+                                 * MethodWriter to save a byte array copy
+                                 * operation. The real copy will be done in
+                                 * ClassWriter.toByteArray().
+                                 */
+                                mw.classReaderOffset = u0;
+                                mw.classReaderLength = u - u0;
+                                continue;
+                            }
+                        }
+                    }
+                }
+
+                if (ANNOTATIONS && dann != 0) {
+                    AnnotationVisitor dv = mv.visitAnnotationDefault();
+                    readAnnotationValue(dann, c, null, dv);
+                    if (dv != null) {
+                        dv.visitEnd();
+                    }
+                }
+                if (ANNOTATIONS) {
+                    for (j = 1; j >= 0; --j) {
+                        w = j == 0 ? ianns : anns;
+                        if (w != 0) {
+                            k = readUnsignedShort(w);
+                            w += 2;
+                            for (; k > 0; --k) {
+                                w = readAnnotationValues(w + 2,
+                                        c,
+                                        true,
+                                        mv.visitAnnotation(readUTF8(w, c), j != 0));
+                            }
+                        }
+                    }
+                }
+                if (ANNOTATIONS && mpanns != 0) {
+                    readParameterAnnotations(mpanns, desc, c, true, mv);
+                }
+                if (ANNOTATIONS && impanns != 0) {
+                    readParameterAnnotations(impanns, desc, c, false, mv);
+                }
+                while (cattrs != null) {
+                    attr = cattrs.next;
+                    cattrs.next = null;
+                    mv.visitAttribute(cattrs);
+                    cattrs = attr;
+                }
+            }
+
+            if (mv != null && v != 0) {
+                int maxStack = readUnsignedShort(v);
+                int maxLocals = readUnsignedShort(v + 2);
+                int codeLength = readInt(v + 4);
+                v += 8;
+
+                int codeStart = v;
+                int codeEnd = v + codeLength;
+
+                mv.visitCode();
+
+                // 1st phase: finds the labels
+                int label;
+                Label[] labels = new Label[codeLength + 2];
+                readLabel(codeLength + 1, labels);
+                while (v < codeEnd) {
+                    w = v - codeStart;
+                    int opcode = b[v] & 0xFF;
+                    switch (ClassWriter.TYPE[opcode]) {
+                        case ClassWriter.NOARG_INSN:
+                        case ClassWriter.IMPLVAR_INSN:
+                            v += 1;
+                            break;
+                        case ClassWriter.LABEL_INSN:
+                            readLabel(w + readShort(v + 1), labels);
+                            v += 3;
+                            break;
+                        case ClassWriter.LABELW_INSN:
+                            readLabel(w + readInt(v + 1), labels);
+                            v += 5;
+                            break;
+                        case ClassWriter.WIDE_INSN:
+                            opcode = b[v + 1] & 0xFF;
+                            if (opcode == Opcodes.IINC) {
+                                v += 6;
+                            } else {
+                                v += 4;
+                            }
+                            break;
+                        case ClassWriter.TABL_INSN:
+                            // skips 0 to 3 padding bytes*
+                            v = v + 4 - (w & 3);
+                            // reads instruction
+                            readLabel(w + readInt(v), labels);
+                            j = readInt(v + 8) - readInt(v + 4) + 1;
+                            v += 12;
+                            for (; j > 0; --j) {
+                                readLabel(w + readInt(v), labels);
+                                v += 4;
+                            }
+                            break;
+                        case ClassWriter.LOOK_INSN:
+                            // skips 0 to 3 padding bytes*
+                            v = v + 4 - (w & 3);
+                            // reads instruction
+                            readLabel(w + readInt(v), labels);
+                            j = readInt(v + 4);
+                            v += 8;
+                            for (; j > 0; --j) {
+                                readLabel(w + readInt(v + 4), labels);
+                                v += 8;
+                            }
+                            break;
+                        case ClassWriter.VAR_INSN:
+                        case ClassWriter.SBYTE_INSN:
+                        case ClassWriter.LDC_INSN:
+                            v += 2;
+                            break;
+                        case ClassWriter.SHORT_INSN:
+                        case ClassWriter.LDCW_INSN:
+                        case ClassWriter.FIELDORMETH_INSN:
+                        case ClassWriter.TYPE_INSN:
+                        case ClassWriter.IINC_INSN:
+                            v += 3;
+                            break;
+                        case ClassWriter.ITFMETH_INSN:
+                        case ClassWriter.INDYMETH_INSN:
+                            v += 5;
+                            break;
+                        // case MANA_INSN:
+                        default:
+                            v += 4;
+                            break;
+                    }
+                }
+                // parses the try catch entries
+                j = readUnsignedShort(v);
+                v += 2;
+                for (; j > 0; --j) {
+                    Label start = readLabel(readUnsignedShort(v), labels);
+                    Label end = readLabel(readUnsignedShort(v + 2), labels);
+                    Label handler = readLabel(readUnsignedShort(v + 4), labels);
+                    int type = readUnsignedShort(v + 6);
+                    if (type == 0) {
+                        mv.visitTryCatchBlock(start, end, handler, null);
+                    } else {
+                        mv.visitTryCatchBlock(start,
+                                end,
+                                handler,
+                                readUTF8(items[type], c));
+                    }
+                    v += 8;
+                }
+                // parses the local variable, line number tables, and code
+                // attributes
+                int varTable = 0;
+                int varTypeTable = 0;
+                int stackMap = 0;
+                int stackMapSize = 0;
+                int frameCount = 0;
+                int frameMode = 0;
+                int frameOffset = 0;
+                int frameLocalCount = 0;
+                int frameLocalDiff = 0;
+                int frameStackCount = 0;
+                Object[] frameLocal = null;
+                Object[] frameStack = null;
+                boolean zip = true;
+                cattrs = null;
+                j = readUnsignedShort(v);
+                v += 2;
+                for (; j > 0; --j) {
+                    attrName = readUTF8(v, c);
+                    if ("LocalVariableTable".equals(attrName)) {
+                        if (!skipDebug) {
+                            varTable = v + 6;
+                            k = readUnsignedShort(v + 6);
+                            w = v + 8;
+                            for (; k > 0; --k) {
+                                label = readUnsignedShort(w);
+                                if (labels[label] == null) {
+                                    readLabel(label, labels).status |= Label.DEBUG;
+                                }
+                                label += readUnsignedShort(w + 2);
+                                if (labels[label] == null) {
+                                    readLabel(label, labels).status |= Label.DEBUG;
+                                }
+                                w += 10;
+                            }
+                        }
+                    } else if ("LocalVariableTypeTable".equals(attrName)) {
+                        varTypeTable = v + 6;
+                    } else if ("LineNumberTable".equals(attrName)) {
+                        if (!skipDebug) {
+                            k = readUnsignedShort(v + 6);
+                            w = v + 8;
+                            for (; k > 0; --k) {
+                                label = readUnsignedShort(w);
+                                if (labels[label] == null) {
+                                    readLabel(label, labels).status |= Label.DEBUG;
+                                }
+                                labels[label].line = readUnsignedShort(w + 2);
+                                w += 4;
+                            }
+                        }
+                    } else if (FRAMES && "StackMapTable".equals(attrName)) {
+                        if ((flags & SKIP_FRAMES) == 0) {
+                            stackMap = v + 8;
+                            stackMapSize = readInt(v + 2);
+                            frameCount = readUnsignedShort(v + 6);
+                        }
+                        /*
+                         * here we do not extract the labels corresponding to
+                         * the attribute content. This would require a full
+                         * parsing of the attribute, which would need to be
+                         * repeated in the second phase (see below). Instead the
+                         * content of the attribute is read one frame at a time
+                         * (i.e. after a frame has been visited, the next frame
+                         * is read), and the labels it contains are also
+                         * extracted one frame at a time. Thanks to the ordering
+                         * of frames, having only a "one frame lookahead" is not
+                         * a problem, i.e. it is not possible to see an offset
+                         * smaller than the offset of the current insn and for
+                         * which no Label exist.
+                         */
+                        /*
+                         * This is not true for UNINITIALIZED type offsets. We
+                         * solve this by parsing the stack map table without a
+                         * full decoding (see below).
+                         */
+                    } else if (FRAMES && "StackMap".equals(attrName)) {
+                        if ((flags & SKIP_FRAMES) == 0) {
+                            stackMap = v + 8;
+                            stackMapSize = readInt(v + 2);
+                            frameCount = readUnsignedShort(v + 6);
+                            zip = false;
+                        }
+                        /*
+                         * IMPORTANT! here we assume that the frames are
+                         * ordered, as in the StackMapTable attribute, although
+                         * this is not guaranteed by the attribute format.
+                         */
+                    } else {
+                        for (k = 0; k < attrs.length; ++k) {
+                            if (attrs[k].type.equals(attrName)) {
+                                attr = attrs[k].read(this,
+                                        v + 6,
+                                        readInt(v + 2),
+                                        c,
+                                        codeStart - 8,
+                                        labels);
+                                if (attr != null) {
+                                    attr.next = cattrs;
+                                    cattrs = attr;
+                                }
+                            }
+                        }
+                    }
+                    v += 6 + readInt(v + 2);
+                }
+
+                // 2nd phase: visits each instruction
+                if (FRAMES && stackMap != 0) {
+                    // creates the very first (implicit) frame from the method
+                    // descriptor
+                    frameLocal = new Object[maxLocals];
+                    frameStack = new Object[maxStack];
+                    if (unzip) {
+                        int local = 0;
+                        if ((access & Opcodes.ACC_STATIC) == 0) {
+                            if ("<init>".equals(name)) {
+                                frameLocal[local++] = Opcodes.UNINITIALIZED_THIS;
+                            } else {
+                                frameLocal[local++] = readClass(header + 2, c);
+                            }
+                        }
+                        j = 1;
+                        loop: while (true) {
+                            k = j;
+                            switch (desc.charAt(j++)) {
+                                case 'Z':
+                                case 'C':
+                                case 'B':
+                                case 'S':
+                                case 'I':
+                                    frameLocal[local++] = Opcodes.INTEGER;
+                                    break;
+                                case 'F':
+                                    frameLocal[local++] = Opcodes.FLOAT;
+                                    break;
+                                case 'J':
+                                    frameLocal[local++] = Opcodes.LONG;
+                                    break;
+                                case 'D':
+                                    frameLocal[local++] = Opcodes.DOUBLE;
+                                    break;
+                                case '[':
+                                    while (desc.charAt(j) == '[') {
+                                        ++j;
+                                    }
+                                    if (desc.charAt(j) == 'L') {
+                                        ++j;
+                                        while (desc.charAt(j) != ';') {
+                                            ++j;
+                                        }
+                                    }
+                                    frameLocal[local++] = desc.substring(k, ++j);
+                                    break;
+                                case 'L':
+                                    while (desc.charAt(j) != ';') {
+                                        ++j;
+                                    }
+                                    frameLocal[local++] = desc.substring(k + 1,
+                                            j++);
+                                    break;
+                                default:
+                                    break loop;
+                            }
+                        }
+                        frameLocalCount = local;
+                    }
+                    /*
+                     * for the first explicit frame the offset is not
+                     * offset_delta + 1 but only offset_delta; setting the
+                     * implicit frame offset to -1 allow the use of the
+                     * "offset_delta + 1" rule in all cases
+                     */
+                    frameOffset = -1;
+                    /*
+                     * Finds labels for UNINITIALIZED frame types. Instead of
+                     * decoding each element of the stack map table, we look
+                     * for 3 consecutive bytes that "look like" an UNINITIALIZED
+                     * type (tag 8, offset within code bounds, NEW instruction
+                     * at this offset). We may find false positives (i.e. not
+                     * real UNINITIALIZED types), but this should be rare, and
+                     * the only consequence will be the creation of an unneeded
+                     * label. This is better than creating a label for each NEW
+                     * instruction, and faster than fully decoding the whole
+                     * stack map table.
+                     */
+                    for (j = stackMap; j < stackMap + stackMapSize - 2; ++j) {
+                        if (b[j] == 8) { // UNINITIALIZED FRAME TYPE
+                            k = readUnsignedShort(j + 1);
+                            if (k >= 0 && k < codeLength) { // potential offset
+                                if ((b[codeStart + k] & 0xFF) == Opcodes.NEW) { // NEW at this offset
+                                    readLabel(k, labels);
+                                }
+                            }
+                        }
+                    }
+                }
+                v = codeStart;
+                Label l;
+                while (v < codeEnd) {
+                    w = v - codeStart;
+
+                    l = labels[w];
+                    if (l != null) {
+                        mv.visitLabel(l);
+                        if (!skipDebug && l.line > 0) {
+                            mv.visitLineNumber(l.line, l);
+                        }
+                    }
+
+                    while (FRAMES && frameLocal != null
+                            && (frameOffset == w || frameOffset == -1))
+                    {
+                        // if there is a frame for this offset,
+                        // makes the visitor visit it,
+                        // and reads the next frame if there is one.
+                        if (!zip || unzip) {
+                            mv.visitFrame(Opcodes.F_NEW,
+                                    frameLocalCount,
+                                    frameLocal,
+                                    frameStackCount,
+                                    frameStack);
+                        } else if (frameOffset != -1) {
+                            mv.visitFrame(frameMode,
+                                    frameLocalDiff,
+                                    frameLocal,
+                                    frameStackCount,
+                                    frameStack);
+                        }
+
+                        if (frameCount > 0) {
+                            int tag, delta, n;
+                            if (zip) {
+                                tag = b[stackMap++] & 0xFF;
+                            } else {
+                                tag = MethodWriter.FULL_FRAME;
+                                frameOffset = -1;
+                            }
+                            frameLocalDiff = 0;
+                            if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME)
+                            {
+                                delta = tag;
+                                frameMode = Opcodes.F_SAME;
+                                frameStackCount = 0;
+                            } else if (tag < MethodWriter.RESERVED) {
+                                delta = tag
+                                        - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME;
+                                stackMap = readFrameType(frameStack,
+                                        0,
+                                        stackMap,
+                                        c,
+                                        labels);
+                                frameMode = Opcodes.F_SAME1;
+                                frameStackCount = 1;
+                            } else {
+                                delta = readUnsignedShort(stackMap);
+                                stackMap += 2;
+                                if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
+                                {
+                                    stackMap = readFrameType(frameStack,
+                                            0,
+                                            stackMap,
+                                            c,
+                                            labels);
+                                    frameMode = Opcodes.F_SAME1;
+                                    frameStackCount = 1;
+                                } else if (tag >= MethodWriter.CHOP_FRAME
+                                        && tag < MethodWriter.SAME_FRAME_EXTENDED)
+                                {
+                                    frameMode = Opcodes.F_CHOP;
+                                    frameLocalDiff = MethodWriter.SAME_FRAME_EXTENDED
+                                            - tag;
+                                    frameLocalCount -= frameLocalDiff;
+                                    frameStackCount = 0;
+                                } else if (tag == MethodWriter.SAME_FRAME_EXTENDED)
+                                {
+                                    frameMode = Opcodes.F_SAME;
+                                    frameStackCount = 0;
+                                } else if (tag < MethodWriter.FULL_FRAME) {
+                                    j = unzip ? frameLocalCount : 0;
+                                    for (k = tag
+                                            - MethodWriter.SAME_FRAME_EXTENDED; k > 0; k--)
+                                    {
+                                        stackMap = readFrameType(frameLocal,
+                                                j++,
+                                                stackMap,
+                                                c,
+                                                labels);
+                                    }
+                                    frameMode = Opcodes.F_APPEND;
+                                    frameLocalDiff = tag
+                                            - MethodWriter.SAME_FRAME_EXTENDED;
+                                    frameLocalCount += frameLocalDiff;
+                                    frameStackCount = 0;
+                                } else { // if (tag == FULL_FRAME) {
+                                    frameMode = Opcodes.F_FULL;
+                                    n = frameLocalDiff = frameLocalCount = readUnsignedShort(stackMap);
+                                    stackMap += 2;
+                                    for (j = 0; n > 0; n--) {
+                                        stackMap = readFrameType(frameLocal,
+                                                j++,
+                                                stackMap,
+                                                c,
+                                                labels);
+                                    }
+                                    n = frameStackCount = readUnsignedShort(stackMap);
+                                    stackMap += 2;
+                                    for (j = 0; n > 0; n--) {
+                                        stackMap = readFrameType(frameStack,
+                                                j++,
+                                                stackMap,
+                                                c,
+                                                labels);
+                                    }
+                                }
+                            }
+                            frameOffset += delta + 1;
+                            readLabel(frameOffset, labels);
+
+                            --frameCount;
+                        } else {
+                            frameLocal = null;
+                        }
+                    }
+
+                    int opcode = b[v] & 0xFF;
+                    switch (ClassWriter.TYPE[opcode]) {
+                        case ClassWriter.NOARG_INSN:
+                            mv.visitInsn(opcode);
+                            v += 1;
+                            break;
+                        case ClassWriter.IMPLVAR_INSN:
+                            if (opcode > Opcodes.ISTORE) {
+                                opcode -= 59; // ISTORE_0
+                                mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),
+                                        opcode & 0x3);
+                            } else {
+                                opcode -= 26; // ILOAD_0
+                                mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2),
+                                        opcode & 0x3);
+                            }
+                            v += 1;
+                            break;
+                        case ClassWriter.LABEL_INSN:
+                            mv.visitJumpInsn(opcode, labels[w
+                                    + readShort(v + 1)]);
+                            v += 3;
+                            break;
+                        case ClassWriter.LABELW_INSN:
+                            mv.visitJumpInsn(opcode - 33, labels[w
+                                    + readInt(v + 1)]);
+                            v += 5;
+                            break;
+                        case ClassWriter.WIDE_INSN:
+                            opcode = b[v + 1] & 0xFF;
+                            if (opcode == Opcodes.IINC) {
+                                mv.visitIincInsn(readUnsignedShort(v + 2),
+                                        readShort(v + 4));
+                                v += 6;
+                            } else {
+                                mv.visitVarInsn(opcode,
+                                        readUnsignedShort(v + 2));
+                                v += 4;
+                            }
+                            break;
+                        case ClassWriter.TABL_INSN:
+                            // skips 0 to 3 padding bytes
+                            v = v + 4 - (w & 3);
+                            // reads instruction
+                            label = w + readInt(v);
+                            int min = readInt(v + 4);
+                            int max = readInt(v + 8);
+                            v += 12;
+                            Label[] table = new Label[max - min + 1];
+                            for (j = 0; j < table.length; ++j) {
+                                table[j] = labels[w + readInt(v)];
+                                v += 4;
+                            }
+                            mv.visitTableSwitchInsn(min,
+                                    max,
+                                    labels[label],
+                                    table);
+                            break;
+                        case ClassWriter.LOOK_INSN:
+                            // skips 0 to 3 padding bytes
+                            v = v + 4 - (w & 3);
+                            // reads instruction
+                            label = w + readInt(v);
+                            j = readInt(v + 4);
+                            v += 8;
+                            int[] keys = new int[j];
+                            Label[] values = new Label[j];
+                            for (j = 0; j < keys.length; ++j) {
+                                keys[j] = readInt(v);
+                                values[j] = labels[w + readInt(v + 4)];
+                                v += 8;
+                            }
+                            mv.visitLookupSwitchInsn(labels[label],
+                                    keys,
+                                    values);
+                            break;
+                        case ClassWriter.VAR_INSN:
+                            mv.visitVarInsn(opcode, b[v + 1] & 0xFF);
+                            v += 2;
+                            break;
+                        case ClassWriter.SBYTE_INSN:
+                            mv.visitIntInsn(opcode, b[v + 1]);
+                            v += 2;
+                            break;
+                        case ClassWriter.SHORT_INSN:
+                            mv.visitIntInsn(opcode, readShort(v + 1));
+                            v += 3;
+                            break;
+                        case ClassWriter.LDC_INSN:
+                            mv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c));
+                            v += 2;
+                            break;
+                        case ClassWriter.LDCW_INSN:
+                            mv.visitLdcInsn(readConst(readUnsignedShort(v + 1),
+                                    c));
+                            v += 3;
+                            break;
+                        case ClassWriter.FIELDORMETH_INSN:
+                        case ClassWriter.ITFMETH_INSN: {
+                            int cpIndex = items[readUnsignedShort(v + 1)];
+                            String iowner = readClass(cpIndex, c);
+                            cpIndex = items[readUnsignedShort(cpIndex + 2)];
+                            String iname = readUTF8(cpIndex, c);
+                            String idesc = readUTF8(cpIndex + 2, c);
+                            if (opcode < Opcodes.INVOKEVIRTUAL) {
+                                mv.visitFieldInsn(opcode, iowner, iname, idesc);
+                            } else {
+                                mv.visitMethodInsn(opcode, iowner, iname, idesc);
+                            }
+                            if (opcode == Opcodes.INVOKEINTERFACE) {
+                                v += 5;
+                            } else {
+                                v += 3;
+                            }
+                            break;
+                        }
+                        case ClassWriter.INDYMETH_INSN: {
+                            int cpIndex = items[readUnsignedShort(v + 1)];
+                            int bsmIndex = bootstrapMethods[readUnsignedShort(cpIndex)];
+                            cpIndex = items[readUnsignedShort(cpIndex + 2)];
+                            String iname = readUTF8(cpIndex, c);
+                            String idesc = readUTF8(cpIndex + 2, c);
+
+                            int mhIndex = readUnsignedShort(bsmIndex);
+                            Handle bsm = (Handle) readConst(mhIndex, c);
+                            int bsmArgCount = readUnsignedShort(bsmIndex + 2);
+                            Object[] bsmArgs = new Object[bsmArgCount];
+                            bsmIndex += 4;
+                            for(int a = 0; a < bsmArgCount; a++) {
+                                int argIndex = readUnsignedShort(bsmIndex);
+                                bsmArgs[a] = readConst(argIndex, c);
+                                bsmIndex += 2;
+                            }
+                            mv.visitInvokeDynamicInsn(iname, idesc, bsm, bsmArgs);
+
+                            v += 5;
+                            break;
+                        }
+                        case ClassWriter.TYPE_INSN:
+                            mv.visitTypeInsn(opcode, readClass(v + 1, c));
+                            v += 3;
+                            break;
+                        case ClassWriter.IINC_INSN:
+                            mv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]);
+                            v += 3;
+                            break;
+                        // case MANA_INSN:
+                        default:
+                            mv.visitMultiANewArrayInsn(readClass(v + 1, c),
+                                    b[v + 3] & 0xFF);
+                            v += 4;
+                            break;
+                    }
+                }
+                l = labels[codeEnd - codeStart];
+                if (l != null) {
+                    mv.visitLabel(l);
+                }
+                // visits the local variable tables
+                if (!skipDebug && varTable != 0) {
+                    int[] typeTable = null;
+                    if (varTypeTable != 0) {
+                        k = readUnsignedShort(varTypeTable) * 3;
+                        w = varTypeTable + 2;
+                        typeTable = new int[k];
+                        while (k > 0) {
+                            typeTable[--k] = w + 6; // signature
+                            typeTable[--k] = readUnsignedShort(w + 8); // index
+                            typeTable[--k] = readUnsignedShort(w); // start
+                            w += 10;
+                        }
+                    }
+                    k = readUnsignedShort(varTable);
+                    w = varTable + 2;
+                    for (; k > 0; --k) {
+                        int start = readUnsignedShort(w);
+                        int length = readUnsignedShort(w + 2);
+                        int index = readUnsignedShort(w + 8);
+                        String vsignature = null;
+                        if (typeTable != null) {
+                            for (int a = 0; a < typeTable.length; a += 3) {
+                                if (typeTable[a] == start
+                                        && typeTable[a + 1] == index)
+                                {
+                                    vsignature = readUTF8(typeTable[a + 2], c);
+                                    break;
+                                }
+                            }
+                        }
+                        mv.visitLocalVariable(readUTF8(w + 4, c),
+                                readUTF8(w + 6, c),
+                                vsignature,
+                                labels[start],
+                                labels[start + length],
+                                index);
+                        w += 10;
+                    }
+                }
+                // visits the other attributes
+                while (cattrs != null) {
+                    attr = cattrs.next;
+                    cattrs.next = null;
+                    mv.visitAttribute(cattrs);
+                    cattrs = attr;
+                }
+                // visits the max stack and max locals values
+                mv.visitMaxs(maxStack, maxLocals);
+            }
+
+            if (mv != null) {
+                mv.visitEnd();
+            }
+        }
+
+        // visits the end of the class
+        classVisitor.visitEnd();
+    }
+
+    /**
+     * Reads parameter annotations and makes the given visitor visit them.
+     *
+     * @param v start offset in {@link #b b} of the annotations to be read.
+     * @param desc the method descriptor.
+     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+     *        {@link #readClass(int,char[]) readClass} or
+     *        {@link #readConst readConst}.
+     * @param visible <tt>true</tt> if the annotations to be read are visible
+     *        at runtime.
+     * @param mv the visitor that must visit the annotations.
+     */
+    private void readParameterAnnotations(
+        int v,
+        final String desc,
+        final char[] buf,
+        final boolean visible,
+        final MethodVisitor mv)
+    {
+        int i;
+        int n = b[v++] & 0xFF;
+        // workaround for a bug in javac (javac compiler generates a parameter
+        // annotation array whose size is equal to the number of parameters in
+        // the Java source file, while it should generate an array whose size is
+        // equal to the number of parameters in the method descriptor - which
+        // includes the synthetic parameters added by the compiler). This work-
+        // around supposes that the synthetic parameters are the first ones.
+        int synthetics = Type.getArgumentTypes(desc).length - n;
+        AnnotationVisitor av;
+        for (i = 0; i < synthetics; ++i) {
+            // virtual annotation to detect synthetic parameters in MethodWriter
+            av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false);
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+        for (; i < n + synthetics; ++i) {
+            int j = readUnsignedShort(v);
+            v += 2;
+            for (; j > 0; --j) {
+                av = mv.visitParameterAnnotation(i, readUTF8(v, buf), visible);
+                v = readAnnotationValues(v + 2, buf, true, av);
+            }
+        }
+    }
+
+    /**
+     * Reads the values of an annotation and makes the given visitor visit them.
+     *
+     * @param v the start offset in {@link #b b} of the values to be read
+     *        (including the unsigned short that gives the number of values).
+     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+     *        {@link #readClass(int,char[]) readClass} or
+     *        {@link #readConst readConst}.
+     * @param named if the annotation values are named or not.
+     * @param av the visitor that must visit the values.
+     * @return the end offset of the annotation values.
+     */
+    private int readAnnotationValues(
+        int v,
+        final char[] buf,
+        final boolean named,
+        final AnnotationVisitor av)
+    {
+        int i = readUnsignedShort(v);
+        v += 2;
+        if (named) {
+            for (; i > 0; --i) {
+                v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av);
+            }
+        } else {
+            for (; i > 0; --i) {
+                v = readAnnotationValue(v, buf, null, av);
+            }
+        }
+        if (av != null) {
+            av.visitEnd();
+        }
+        return v;
+    }
+
+    /**
+     * Reads a value of an annotation and makes the given visitor visit it.
+     *
+     * @param v the start offset in {@link #b b} of the value to be read (<i>not
+     *        including the value name constant pool index</i>).
+     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+     *        {@link #readClass(int,char[]) readClass} or
+     *        {@link #readConst readConst}.
+     * @param name the name of the value to be read.
+     * @param av the visitor that must visit the value.
+     * @return the end offset of the annotation value.
+     */
+    private int readAnnotationValue(
+        int v,
+        final char[] buf,
+        final String name,
+        final AnnotationVisitor av)
+    {
+        int i;
+        if (av == null) {
+            switch (b[v] & 0xFF) {
+                case 'e': // enum_const_value
+                    return v + 5;
+                case '@': // annotation_value
+                    return readAnnotationValues(v + 3, buf, true, null);
+                case '[': // array_value
+                    return readAnnotationValues(v + 1, buf, false, null);
+                default:
+                    return v + 3;
+            }
+        }
+        switch (b[v++] & 0xFF) {
+            case 'I': // pointer to CONSTANT_Integer
+            case 'J': // pointer to CONSTANT_Long
+            case 'F': // pointer to CONSTANT_Float
+            case 'D': // pointer to CONSTANT_Double
+                av.visit(name, readConst(readUnsignedShort(v), buf));
+                v += 2;
+                break;
+            case 'B': // pointer to CONSTANT_Byte
+                av.visit(name,
+                        new Byte((byte) readInt(items[readUnsignedShort(v)])));
+                v += 2;
+                break;
+            case 'Z': // pointer to CONSTANT_Boolean
+                av.visit(name, readInt(items[readUnsignedShort(v)]) == 0
+                        ? Boolean.FALSE
+                        : Boolean.TRUE);
+                v += 2;
+                break;
+            case 'S': // pointer to CONSTANT_Short
+                av.visit(name,
+                        new Short((short) readInt(items[readUnsignedShort(v)])));
+                v += 2;
+                break;
+            case 'C': // pointer to CONSTANT_Char
+                av.visit(name,
+                        new Character((char) readInt(items[readUnsignedShort(v)])));
+                v += 2;
+                break;
+            case 's': // pointer to CONSTANT_Utf8
+                av.visit(name, readUTF8(v, buf));
+                v += 2;
+                break;
+            case 'e': // enum_const_value
+                av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));
+                v += 4;
+                break;
+            case 'c': // class_info
+                av.visit(name, Type.getType(readUTF8(v, buf)));
+                v += 2;
+                break;
+            case '@': // annotation_value
+                v = readAnnotationValues(v + 2,
+                        buf,
+                        true,
+                        av.visitAnnotation(name, readUTF8(v, buf)));
+                break;
+            case '[': // array_value
+                int size = readUnsignedShort(v);
+                v += 2;
+                if (size == 0) {
+                    return readAnnotationValues(v - 2,
+                            buf,
+                            false,
+                            av.visitArray(name));
+                }
+                switch (this.b[v++] & 0xFF) {
+                    case 'B':
+                        byte[] bv = new byte[size];
+                        for (i = 0; i < size; i++) {
+                            bv[i] = (byte) readInt(items[readUnsignedShort(v)]);
+                            v += 3;
+                        }
+                        av.visit(name, bv);
+                        --v;
+                        break;
+                    case 'Z':
+                        boolean[] zv = new boolean[size];
+                        for (i = 0; i < size; i++) {
+                            zv[i] = readInt(items[readUnsignedShort(v)]) != 0;
+                            v += 3;
+                        }
+                        av.visit(name, zv);
+                        --v;
+                        break;
+                    case 'S':
+                        short[] sv = new short[size];
+                        for (i = 0; i < size; i++) {
+                            sv[i] = (short) readInt(items[readUnsignedShort(v)]);
+                            v += 3;
+                        }
+                        av.visit(name, sv);
+                        --v;
+                        break;
+                    case 'C':
+                        char[] cv = new char[size];
+                        for (i = 0; i < size; i++) {
+                            cv[i] = (char) readInt(items[readUnsignedShort(v)]);
+                            v += 3;
+                        }
+                        av.visit(name, cv);
+                        --v;
+                        break;
+                    case 'I':
+                        int[] iv = new int[size];
+                        for (i = 0; i < size; i++) {
+                            iv[i] = readInt(items[readUnsignedShort(v)]);
+                            v += 3;
+                        }
+                        av.visit(name, iv);
+                        --v;
+                        break;
+                    case 'J':
+                        long[] lv = new long[size];
+                        for (i = 0; i < size; i++) {
+                            lv[i] = readLong(items[readUnsignedShort(v)]);
+                            v += 3;
+                        }
+                        av.visit(name, lv);
+                        --v;
+                        break;
+                    case 'F':
+                        float[] fv = new float[size];
+                        for (i = 0; i < size; i++) {
+                            fv[i] = Float.intBitsToFloat(readInt(items[readUnsignedShort(v)]));
+                            v += 3;
+                        }
+                        av.visit(name, fv);
+                        --v;
+                        break;
+                    case 'D':
+                        double[] dv = new double[size];
+                        for (i = 0; i < size; i++) {
+                            dv[i] = Double.longBitsToDouble(readLong(items[readUnsignedShort(v)]));
+                            v += 3;
+                        }
+                        av.visit(name, dv);
+                        --v;
+                        break;
+                    default:
+                        v = readAnnotationValues(v - 3,
+                                buf,
+                                false,
+                                av.visitArray(name));
+                }
+        }
+        return v;
+    }
+
+    private int readFrameType(
+        final Object[] frame,
+        final int index,
+        int v,
+        final char[] buf,
+        final Label[] labels)
+    {
+        int type = b[v++] & 0xFF;
+        switch (type) {
+            case 0:
+                frame[index] = Opcodes.TOP;
+                break;
+            case 1:
+                frame[index] = Opcodes.INTEGER;
+                break;
+            case 2:
+                frame[index] = Opcodes.FLOAT;
+                break;
+            case 3:
+                frame[index] = Opcodes.DOUBLE;
+                break;
+            case 4:
+                frame[index] = Opcodes.LONG;
+                break;
+            case 5:
+                frame[index] = Opcodes.NULL;
+                break;
+            case 6:
+                frame[index] = Opcodes.UNINITIALIZED_THIS;
+                break;
+            case 7: // Object
+                frame[index] = readClass(v, buf);
+                v += 2;
+                break;
+            default: // Uninitialized
+                frame[index] = readLabel(readUnsignedShort(v), labels);
+                v += 2;
+        }
+        return v;
+    }
+
+    /**
+     * Returns the label corresponding to the given offset. The default
+     * implementation of this method creates a label for the given offset if it
+     * has not been already created.
+     *
+     * @param offset a bytecode offset in a method.
+     * @param labels the already created labels, indexed by their offset. If a
+     *        label already exists for offset this method must not create a new
+     *        one. Otherwise it must store the new label in this array.
+     * @return a non null Label, which must be equal to labels[offset].
+     */
+    protected Label readLabel(int offset, Label[] labels) {
+        if (labels[offset] == null) {
+            labels[offset] = new Label();
+        }
+        return labels[offset];
+    }
+
+    /**
+     * Reads an attribute in {@link #b b}.
+     *
+     * @param attrs prototypes of the attributes that must be parsed during the
+     *        visit of the class. Any attribute whose type is not equal to the
+     *        type of one the prototypes is ignored (i.e. an empty
+     *        {@link Attribute} instance is returned).
+     * @param type the type of the attribute.
+     * @param off index of the first byte of the attribute's content in
+     *        {@link #b b}. The 6 attribute header bytes, containing the type
+     *        and the length of the attribute, are not taken into account here
+     *        (they have already been read).
+     * @param len the length of the attribute's content.
+     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+     *        {@link #readClass(int,char[]) readClass} or
+     *        {@link #readConst readConst}.
+     * @param codeOff index of the first byte of code's attribute content in
+     *        {@link #b b}, or -1 if the attribute to be read is not a code
+     *        attribute. The 6 attribute header bytes, containing the type and
+     *        the length of the attribute, are not taken into account here.
+     * @param labels the labels of the method's code, or <tt>null</tt> if the
+     *        attribute to be read is not a code attribute.
+     * @return the attribute that has been read, or <tt>null</tt> to skip this
+     *         attribute.
+     */
+    private Attribute readAttribute(
+        final Attribute[] attrs,
+        final String type,
+        final int off,
+        final int len,
+        final char[] buf,
+        final int codeOff,
+        final Label[] labels)
+    {
+        for (int i = 0; i < attrs.length; ++i) {
+            if (attrs[i].type.equals(type)) {
+                return attrs[i].read(this, off, len, buf, codeOff, labels);
+            }
+        }
+        return new Attribute(type).read(this, off, len, null, -1, null);
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods: low level parsing
+    // ------------------------------------------------------------------------
+
+    /**
+     *  Returns the number of constant pool items in {@link #b b}.
+     *
+     *  @return the number of constant pool items in {@link #b b}.
+     */
+    public int getItemCount() {
+        return items.length;
+    }
+
+    /**
+     * Returns the start index of the constant pool item in {@link #b b}, plus
+     * one. <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param item the index a constant pool item.
+     * @return the start index of the constant pool item in {@link #b b}, plus
+     *         one.
+     */
+    public int getItem(final int item) {
+        return items[item];
+    }
+
+    /**
+     * Returns the maximum length of the strings contained in the constant pool
+     * of the class.
+     *
+     * @return the maximum length of the strings contained in the constant pool
+     *         of the class.
+     */
+    public int getMaxStringLength() {
+        return maxStringLength;
+    }
+
+    /**
+     * Reads a byte value in {@link #b b}. <i>This method is intended for
+     * {@link Attribute} sub classes, and is normally not needed by class
+     * generators or adapters.</i>
+     *
+     * @param index the start index of the value to be read in {@link #b b}.
+     * @return the read value.
+     */
+    public int readByte(final int index) {
+        return b[index] & 0xFF;
+    }
+
+    /**
+     * Reads an unsigned short value in {@link #b b}. <i>This method is
+     * intended for {@link Attribute} sub classes, and is normally not needed by
+     * class generators or adapters.</i>
+     *
+     * @param index the start index of the value to be read in {@link #b b}.
+     * @return the read value.
+     */
+    public int readUnsignedShort(final int index) {
+        byte[] b = this.b;
+        return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
+    }
+
+    /**
+     * Reads a signed short value in {@link #b b}. <i>This method is intended
+     * for {@link Attribute} sub classes, and is normally not needed by class
+     * generators or adapters.</i>
+     *
+     * @param index the start index of the value to be read in {@link #b b}.
+     * @return the read value.
+     */
+    public short readShort(final int index) {
+        byte[] b = this.b;
+        return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
+    }
+
+    /**
+     * Reads a signed int value in {@link #b b}. <i>This method is intended for
+     * {@link Attribute} sub classes, and is normally not needed by class
+     * generators or adapters.</i>
+     *
+     * @param index the start index of the value to be read in {@link #b b}.
+     * @return the read value.
+     */
+    public int readInt(final int index) {
+        byte[] b = this.b;
+        return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)
+                | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
+    }
+
+    /**
+     * Reads a signed long value in {@link #b b}. <i>This method is intended
+     * for {@link Attribute} sub classes, and is normally not needed by class
+     * generators or adapters.</i>
+     *
+     * @param index the start index of the value to be read in {@link #b b}.
+     * @return the read value.
+     */
+    public long readLong(final int index) {
+        long l1 = readInt(index);
+        long l0 = readInt(index + 4) & 0xFFFFFFFFL;
+        return (l1 << 32) | l0;
+    }
+
+    /**
+     * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method
+     * is intended for {@link Attribute} sub classes, and is normally not needed
+     * by class generators or adapters.</i>
+     *
+     * @param index the start index of an unsigned short value in {@link #b b},
+     *        whose value is the index of an UTF8 constant pool item.
+     * @param buf buffer to be used to read the item. This buffer must be
+     *        sufficiently large. It is not automatically resized.
+     * @return the String corresponding to the specified UTF8 item.
+     */
+    public String readUTF8(int index, final char[] buf) {
+        int item = readUnsignedShort(index);
+        String s = strings[item];
+        if (s != null) {
+            return s;
+        }
+        index = items[item];
+        return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf);
+    }
+
+    /**
+     * Reads UTF8 string in {@link #b b}.
+     *
+     * @param index start offset of the UTF8 string to be read.
+     * @param utfLen length of the UTF8 string to be read.
+     * @param buf buffer to be used to read the string. This buffer must be
+     *        sufficiently large. It is not automatically resized.
+     * @return the String corresponding to the specified UTF8 string.
+     */
+    private String readUTF(int index, final int utfLen, final char[] buf) {
+        int endIndex = index + utfLen;
+        byte[] b = this.b;
+        int strLen = 0;
+        int c;
+        int st = 0;
+        char cc = 0;
+        while (index < endIndex) {
+            c = b[index++];
+            switch (st) {
+                case 0:
+                    c = c & 0xFF;
+                    if (c < 0x80) {  // 0xxxxxxx
+                        buf[strLen++] = (char) c;
+                    } else if (c < 0xE0 && c > 0xBF) {  // 110x xxxx 10xx xxxx
+                        cc = (char) (c & 0x1F);
+                        st = 1;
+                    } else {  // 1110 xxxx 10xx xxxx 10xx xxxx
+                        cc = (char) (c & 0x0F);
+                        st = 2;
+                    }
+                    break;
+
+                case 1:  // byte 2 of 2-byte char or byte 3 of 3-byte char
+                    buf[strLen++] = (char) ((cc << 6) | (c & 0x3F));
+                    st = 0;
+                    break;
+
+                case 2:  // byte 2 of 3-byte char
+                    cc = (char) ((cc << 6) | (c & 0x3F));
+                    st = 1;
+                    break;
+            }
+        }
+        return new String(buf, 0, strLen);
+    }
+
+    /**
+     * Reads a class constant pool item in {@link #b b}. <i>This method is
+     * intended for {@link Attribute} sub classes, and is normally not needed by
+     * class generators or adapters.</i>
+     *
+     * @param index the start index of an unsigned short value in {@link #b b},
+     *        whose value is the index of a class constant pool item.
+     * @param buf buffer to be used to read the item. This buffer must be
+     *        sufficiently large. It is not automatically resized.
+     * @return the String corresponding to the specified class item.
+     */
+    public String readClass(final int index, final char[] buf) {
+        // computes the start index of the CONSTANT_Class item in b
+        // and reads the CONSTANT_Utf8 item designated by
+        // the first two bytes of this CONSTANT_Class item
+        return readUTF8(items[readUnsignedShort(index)], buf);
+    }
+
+    /**
+     * Reads a numeric or string constant pool item in {@link #b b}. <i>This
+     * method is intended for {@link Attribute} sub classes, and is normally not
+     * needed by class generators or adapters.</i>
+     *
+     * @param item the index of a constant pool item.
+     * @param buf buffer to be used to read the item. This buffer must be
+     *        sufficiently large. It is not automatically resized.
+     * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double},
+     *         {@link String}, {@link Type} or {@link Handle} corresponding to
+     *         the given constant pool item.
+     */
+    public Object readConst(final int item, final char[] buf) {
+        int index = items[item];
+        switch (b[index - 1]) {
+            case ClassWriter.INT:
+                return new Integer(readInt(index));
+            case ClassWriter.FLOAT:
+                return new Float(Float.intBitsToFloat(readInt(index)));
+            case ClassWriter.LONG:
+                return new Long(readLong(index));
+            case ClassWriter.DOUBLE:
+                return new Double(Double.longBitsToDouble(readLong(index)));
+            case ClassWriter.CLASS:
+                return Type.getObjectType(readUTF8(index, buf));
+            case ClassWriter.STR:
+                return readUTF8(index, buf);
+            case ClassWriter.MTYPE:
+                return Type.getMethodType(readUTF8(index, buf));
+
+            //case ClassWriter.HANDLE_BASE + [1..9]:
+            default: {
+                int tag = readByte(index);
+                int[] items = this.items;
+                int cpIndex = items[readUnsignedShort(index + 1)];
+                String owner = readClass(cpIndex, buf);
+                cpIndex = items[readUnsignedShort(cpIndex + 2)];
+                String name = readUTF8(cpIndex, buf);
+                String desc = readUTF8(cpIndex + 2, buf);
+                return new Handle(tag, owner, name, desc);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java	Sat Oct 20 22:49:26 2012 +0100
@@ -0,0 +1,306 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * 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 jdk.internal.org.objectweb.asm;
+
+/**
+ * A visitor to visit a Java class. The methods of this class must be called
+ * in the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
+ * <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
+ * <tt>visitAttribute</tt> )* ( <tt>visitInnerClass</tt> |
+ * <tt>visitField</tt> | <tt>visitMethod</tt> )* <tt>visitEnd</tt>.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class ClassVisitor {
+
+    /**
+     * The ASM API version implemented by this visitor. The value of this field
+     * must be one of {@link Opcodes#ASM4}.
+     */
+    protected final int api;
+
+    /**
+     * The class visitor to which this visitor must delegate method calls. May
+     * be null.
+     */
+    protected ClassVisitor cv;
+
+    /**
+     * Constructs a new {@link ClassVisitor}.
+     *
+     * @param api the ASM API version implemented by this visitor. Must be one
+     *        of {@link Opcodes#ASM4}.
+     */
+    public ClassVisitor(final int api) {
+        this(api, null);
+    }
+
+    /**
+     * Constructs a new {@link ClassVisitor}.
+     *
+     * @param api the ASM API version implemented by this visitor. Must be one
+     *        of {@link Opcodes#ASM4}.
+     * @param cv the class visitor to which this visitor must delegate method
+     *        calls. May be null.
+     */
+    public ClassVisitor(final int api, final ClassVisitor cv) {
+        /*if (api != Opcodes.ASM4) {
+            throw new IllegalArgumentException();
+        }*/
+        this.api = api;
+        this.cv = cv;
+    }
+
+    /**
+     * Visits the header of the class.
+     *
+     * @param version the class version.
+     * @param access the class's access flags (see {@link Opcodes}). This
+     *        parameter also indicates if the class is deprecated.
+     * @param name the internal name of the class (see
+     *        {@link Type#getInternalName() getInternalName}).
+     * @param signature the signature of this class. May be <tt>null</tt> if
+     *        the class is not a generic one, and does not extend or implement
+     *        generic classes or interfaces.
+     * @param superName the internal of name of the super class (see
+     *        {@link Type#getInternalName() getInternalName}). For interfaces,
+     *        the super class is {@link Object}. May be <tt>null</tt>, but
+     *        only for the {@link Object} class.
+     * @param interfaces the internal names of the class's interfaces (see
+     *        {@link Type#getInternalName() getInternalName}). May be
+     *        <tt>null</tt>.
+     */
+    public void visit(
+        int version,
+        int access,
+        String name,
+        String signature,
+        String superName,
+        String[] interfaces)
+    {
+        if (cv != null) {
+            cv.visit(version, access, name, signature, superName, interfaces);
+        }
+    }
+
+    /**
+     * Visits the source of the class.
+     *
+     * @param source the name of the source file from which the class was
+     *        compiled. May be <tt>null</tt>.
+     * @param debug additional debug information to compute the correspondance
+     *        between source and compiled elements of the class. May be
+     *        <tt>null</tt>.
+     */
+    public void visitSource(String source, String debug) {
+        if (cv != null) {
+            cv.visitSource(source, debug);
+        }
+    }
+
+    /**
+     * Visits the enclosing class of the class. This method must be called only
+     * if the class has an enclosing class.
+     *
+     * @param owner internal name of the enclosing class of the class.
+     * @param name the name of the method that contains the class, or
+     *        <tt>null</tt> if the class is not enclosed in a method of its
+     *        enclosing class.
+     * @param desc the descriptor of the method that contains the class, or
+     *        <tt>null</tt> if the class is not enclosed in a method of its
+     *        enclosing class.
+     */
+    public void visitOuterClass(String owner, String name, String desc) {
+        if (cv != null)  {
+            cv.visitOuterClass(owner, name, desc);
+        }
+    }
+
+    /**
+     * Visits an annotation of the class.
+     *
+     * @param desc the class descriptor of the annotation class.
+     * @param visible <tt>true</tt> if the annotation is visible at runtime.
+     * @return a visitor to visit the annotation values, or <tt>null</tt> if
+     *         this visitor is not interested in visiting this annotation.
+     */
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        if (cv != null) {
+            return cv.visitAnnotation(desc, visible);
+        }
+        return null;
+    }
+
+    /**
+     * Visits a non standard attribute of the class.
+     *
+     * @param attr an attribute.
+     */
+    public void visitAttribute(Attribute attr) {
+        if (cv != null) {
+            cv.visitAttribute(attr);
+        }
+    }
+
+    /**
+     * Visits information about an inner class. This inner class is not
+     * necessarily a member of the class being visited.
+     *
+     * @param name the internal name of an inner class (see
+     *        {@link Type#getInternalName() getInternalName}).
+     * @param outerName the internal name of the class to which the inner class
+     *        belongs (see {@link Type#getInternalName() getInternalName}). May
+     *        be <tt>null</tt> for not member classes.
+     * @param innerName the (simple) name of the inner class inside its
+     *        enclosing class. May be <tt>null</tt> for anonymous inner
+     *        classes.
+     * @param access the access flags of the inner class as originally declared
+     *        in the enclosing class.
+     */
+    public void visitInnerClass(
+        String name,
+        String outerName,
+        String innerName,
+        int access)
+    {
+        if (cv != null) {
+            cv.visitInnerClass(name, outerName, innerName, access);
+        }
+    }
+
+    /**
+     * Visits a field of the class.
+     *
+     * @param access the field's access flags (see {@link Opcodes}). This
+     *        parameter also indicates if the field is synthetic and/or
+     *        deprecated.
+     * @param name the field's name.
+     * @param desc the field's descriptor (see {@link Type Type}).
+     * @param signature the field's signature. May be <tt>null</tt> if the
+     *        field's type does not use generic types.
+     * @param value the field's initial value. This parameter, which may be
+     *        <tt>null</tt> if the field does not have an initial value, must
+     *        be an {@link Integer}, a {@link Float}, a {@link Long}, a
+     *        {@link Double} or a {@link String} (for <tt>int</tt>,
+     *        <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields
+     *        respectively). <i>This parameter is only used for static fields</i>.
+     *        Its value is ignored for non static fields, which must be
+     *        initialized through bytecode instructions in constructors or
+     *        methods.
+     * @return a visitor to visit field annotations and attributes, or
+     *         <tt>null</tt> if this class visitor is not interested in
+     *         visiting these annotations and attributes.
+     */
+    public FieldVisitor visitField(
+        int access,
+        String name,
+        String desc,
+        String signature,
+        Object value)
+    {
+        if (cv != null) {
+            return cv.visitField(access, name, desc, signature, value);
+        }
+        return null;
+    }
+
+    /**
+     * Visits a method of the class. This method <i>must</i> return a new
+     * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is
+     * called, i.e., it should not return a previously returned visitor.
+     *
+     * @param access the method's access flags (see {@link Opcodes}). This
+     *        parameter also indicates if the method is synthetic and/or
+     *        deprecated.
+     * @param name the method's name.
+     * @param desc the method's descriptor (see {@link Type Type}).
+     * @param signature the method's signature. May be <tt>null</tt> if the
+     *        method parameters, return type and exceptions do not use generic
+     *        types.
+     * @param exceptions the internal names of the method's exception classes
+     *        (see {@link Type#getInternalName() getInternalName}). May be
+     *        <tt>null</tt>.
+     * @return an object to visit the byte code of the method, or <tt>null</tt>
+     *         if this class visitor is not interested in visiting the code of
+     *         this method.
+     */
+    public MethodVisitor visitMethod(
+        int access,
+        String name,
+        String desc,
+        String signature,
+        String[] exceptions)
+    {
+        if (cv != null) {
+            return cv.visitMethod(access, name, desc, signature, exceptions);
+        }
+        return null;
+    }
+
+    /**
+     * Visits the end of the class. This method, which is the last one to be
+     * called, is used to inform the visitor that all the fields and methods of
+     * the class have been visited.
+     */
+    public void visitEnd() {
+        if (cv != null) {
+            cv.visitEnd();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java	Sat Oct 20 22:49:26 2012 +0100
@@ -0,0 +1,1701 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * 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 jdk.internal.org.objectweb.asm;
+
+/**
+ * A {@link ClassVisitor} that generates classes in bytecode form. More
+ * precisely this visitor generates a byte array conforming to the Java class
+ * file format. It can be used alone, to generate a Java class "from scratch",
+ * or with one or more {@link ClassReader ClassReader} and adapter class visitor
+ * to generate a modified class from one or more existing Java classes.
+ *
+ * @author Eric Bruneton
+ */
+public class ClassWriter extends ClassVisitor {
+
+    /**
+     * Flag to automatically compute the maximum stack size and the maximum
+     * number of local variables of methods. If this flag is set, then the
+     * arguments of the {@link MethodVisitor#visitMaxs visitMaxs} method of the
+     * {@link MethodVisitor} returned by the {@link #visitMethod visitMethod}
+     * method will be ignored, and computed automatically from the signature and
+     * the bytecode of each method.
+     *
+     * @see #ClassWriter(int)
+     */
+    public static final int COMPUTE_MAXS = 1;
+
+    /**
+     * Flag to automatically compute the stack map frames of methods from
+     * scratch. If this flag is set, then the calls to the
+     * {@link MethodVisitor#visitFrame} method are ignored, and the stack map
+     * frames are recomputed from the methods bytecode. The arguments of the
+     * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
+     * recomputed from the bytecode. In other words, computeFrames implies
+     * computeMaxs.
+     *
+     * @see #ClassWriter(int)
+     */
+    public static final int COMPUTE_FRAMES = 2;
+
+    /**
+     * Pseudo access flag to distinguish between the synthetic attribute and
+     * the synthetic access flag.
+     */
+    static final int ACC_SYNTHETIC_ATTRIBUTE = 0x40000;
+
+    /**
+     * The type of instructions without any argument.
+     */
+    static final int NOARG_INSN = 0;
+
+    /**
+     * The type of instructions with an signed byte argument.
+     */
+    static final int SBYTE_INSN = 1;
+
+    /**
+     * The type of instructions with an signed short argument.
+     */
+    static final int SHORT_INSN = 2;
+
+    /**
+     * The type of instructions with a local variable index argument.
+     */
+    static final int VAR_INSN = 3;
+
+    /**
+     * The type of instructions with an implicit local variable index argument.
+     */
+    static final int IMPLVAR_INSN = 4;
+
+    /**
+     * The type of instructions with a type descriptor argument.
+     */
+    static final int TYPE_INSN = 5;
+
+    /**
+     * The type of field and method invocations instructions.
+     */
+    static final int FIELDORMETH_INSN = 6;
+
+    /**
+     * The type of the INVOKEINTERFACE/INVOKEDYNAMIC instruction.
+     */
+    static final int ITFMETH_INSN = 7;
+
+    /**
+     * The type of the INVOKEDYNAMIC instruction.
+     */
+    static final int INDYMETH_INSN = 8;
+
+    /**
+     * The type of instructions with a 2 bytes bytecode offset label.
+     */
+    static final int LABEL_INSN = 9;
+
+    /**
+     * The type of instructions with a 4 bytes bytecode offset label.
+     */
+    static final int LABELW_INSN = 10;
+
+    /**
+     * The type of the LDC instruction.
+     */
+    static final int LDC_INSN = 11;
+
+    /**
+     * The type of the LDC_W and LDC2_W instructions.
+     */
+    static final int LDCW_INSN = 12;
+
+    /**
+     * The type of the IINC instruction.
+     */
+    static final int IINC_INSN = 13;
+
+    /**
+     * The type of the TABLESWITCH instruction.
+     */
+    static final int TABL_INSN = 14;
+
+    /**
+     * The type of the LOOKUPSWITCH instruction.
+     */
+    static final int LOOK_INSN = 15;
+
+    /**
+     * The type of the MULTIANEWARRAY instruction.
+     */
+    static final int MANA_INSN = 16;
+
+    /**
+     * The type of the WIDE instruction.
+     */
+    static final int WIDE_INSN = 17;
+
+    /**
+     * The instruction types of all JVM opcodes.
+     */
+    static final byte[] TYPE;
+
+    /**
+     * The type of CONSTANT_Class constant pool items.
+     */
+    static final int CLASS = 7;
+
+    /**
+     * The type of CONSTANT_Fieldref constant pool items.
+     */
+    static final int FIELD = 9;
+
+    /**
+     * The type of CONSTANT_Methodref constant pool items.
+     */
+    static final int METH = 10;
+
+    /**
+     * The type of CONSTANT_InterfaceMethodref constant pool items.
+     */
+    static final int IMETH = 11;
+
+    /**
+     * The type of CONSTANT_String constant pool items.
+     */
+    static final int STR = 8;
+
+    /**
+     * The type of CONSTANT_Integer constant pool items.
+     */
+    static final int INT = 3;
+
+    /**
+     * The type of CONSTANT_Float constant pool items.
+     */
+    static final int FLOAT = 4;
+
+    /**
+     * The type of CONSTANT_Long constant pool items.
+     */
+    static final int LONG = 5;
+
+    /**
+     * The type of CONSTANT_Double constant pool items.
+     */
+    static final int DOUBLE = 6;
+
+    /**
+     * The type of CONSTANT_NameAndType constant pool items.
+     */
+    static final int NAME_TYPE = 12;
+
+    /**
+     * The type of CONSTANT_Utf8 constant pool items.
+     */
+    static final int UTF8 = 1;
+
+    /**
+     * The type of CONSTANT_MethodType constant pool items.
+     */
+    static final int MTYPE = 16;
+
+    /**
+     * The type of CONSTANT_MethodHandle constant pool items.
+     */
+    static final int HANDLE = 15;
+
+    /**
+     * The type of CONSTANT_InvokeDynamic constant pool items.
+     */
+    static final int INDY = 18;
+
+    /**
+     * The base value for all CONSTANT_MethodHandle constant pool items.
+     * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into
+     * 9 different items.
+     */
+    static final int HANDLE_BASE = 20;
+
+    /**
+     * Normal type Item stored in the ClassWriter {@link ClassWriter#typeTable},
+     * instead of the constant pool, in order to avoid clashes with normal
+     * constant pool items in the ClassWriter constant pool's hash table.
+     */
+    static final int TYPE_NORMAL = 30;
+
+    /**
+     * Uninitialized type Item stored in the ClassWriter
+     * {@link ClassWriter#typeTable}, instead of the constant pool, in order to
+     * avoid clashes with normal constant pool items in the ClassWriter constant
+     * pool's hash table.
+     */
+    static final int TYPE_UNINIT = 31;
+
+    /**
+     * Merged type Item stored in the ClassWriter {@link ClassWriter#typeTable},
+     * instead of the constant pool, in order to avoid clashes with normal
+     * constant pool items in the ClassWriter constant pool's hash table.
+     */
+    static final int TYPE_MERGED = 32;
+
+    /**
+     * The type of BootstrapMethods items. These items are stored in a
+     * special class attribute named BootstrapMethods and
+     * not in the constant pool.
+     */
+    static final int BSM = 33;
+
+    /**
+     * The class reader from which this class writer was constructed, if any.
+     */
+    ClassReader cr;
+
+    /**
+     * Minor and major version numbers of the class to be generated.
+     */
+    int version;
+
+    /**
+     * Index of the next item to be added in the constant pool.
+     */
+    int index;
+
+    /**
+     * The constant pool of this class.
+     */
+    final ByteVector pool;
+
+    /**
+     * The constant pool's hash table data.
+     */
+    Item[] items;
+
+    /**
+     * The threshold of the constant pool's hash table.
+     */
+    int threshold;
+
+    /**
+     * A reusable key used to look for items in the {@link #items} hash table.
+     */
+    final Item key;
+
+    /**
+     * A reusable key used to look for items in the {@link #items} hash table.
+     */
+    final Item key2;
+
+    /**
+     * A reusable key used to look for items in the {@link #items} hash table.
+     */
+    final Item key3;
+
+    /**
+     * A reusable key used to look for items in the {@link #items} hash table.
+     */
+    final Item key4;
+
+    /**
+     * A type table used to temporarily store internal names that will not
+     * necessarily be stored in the constant pool. This type table is used by
+     * the control flow and data flow analysis algorithm used to compute stack
+     * map frames from scratch. This array associates to each index <tt>i</tt>
+     * the Item whose index is <tt>i</tt>. All Item objects stored in this
+     * array are also stored in the {@link #items} hash table. These two arrays
+     * allow to retrieve an Item from its index or, conversely, to get the index
+     * of an Item from its value. Each Item stores an internal name in its
+     * {@link Item#strVal1} field.
+     */
+    Item[] typeTable;
+
+    /**
+     * Number of elements in the {@link #typeTable} array.
+     */
+    private short typeCount;
+
+    /**
+     * The access flags of this class.
+     */
+    private int access;
+
+    /**
+     * The constant pool item that contains the internal name of this class.
+     */
+    private int name;
+
+    /**
+     * The internal name of this class.
+     */
+    String thisName;
+
+    /**
+     * The constant pool item that contains the signature of this class.
+     */
+    private int signature;
+
+    /**
+     * The constant pool item that contains the internal name of the super class
+     * of this class.
+     */
+    private int superName;
+
+    /**
+     * Number of interfaces implemented or extended by this class or interface.
+     */
+    private int interfaceCount;
+
+    /**
+     * The interfaces implemented or extended by this class or interface. More
+     * precisely, this array contains the indexes of the constant pool items
+     * that contain the internal names of these interfaces.
+     */
+    private int[] interfaces;
+
+    /**
+     * The index of the constant pool item that contains the name of the source
+     * file from which this class was compiled.
+     */
+    private int sourceFile;
+
+    /**
+     * The SourceDebug attribute of this class.
+     */
+    private ByteVector sourceDebug;
+
+    /**
+     * The constant pool item that contains the name of the enclosing class of
+     * this class.
+     */
+    private int enclosingMethodOwner;
+
+    /**
+     * The constant pool item that contains the name and descriptor of the
+     * enclosing method of this class.
+     */
+    private int enclosingMethod;
+
+    /**
+     * The runtime visible annotations of this class.
+     */
+    private AnnotationWriter anns;
+
+    /**
+     * The runtime invisible annotations of this class.
+     */
+    private AnnotationWriter ianns;
+
+    /**
+     * The non standard attributes of this class.
+     */
+    private Attribute attrs;
+
+    /**
+     * The number of entries in the InnerClasses attribute.
+     */
+    private int innerClassesCount;
+
+    /**
+     * The InnerClasses attribute.
+     */
+    private ByteVector innerClasses;
+
+    /**
+     * The number of entries in the BootstrapMethods attribute.
+     */
+    int bootstrapMethodsCount;
+
+    /**
+     * The BootstrapMethods attribute.
+     */
+    ByteVector bootstrapMethods;
+
+    /**
+     * The fields of this class. These fields are stored in a linked list of
+     * {@link FieldWriter} objects, linked to each other by their
+     * {@link FieldWriter#fv} field. This field stores the first element of
+     * this list.
+     */
+    FieldWriter firstField;
+
+    /**
+     * The fields of this class. These fields are stored in a linked list of
+     * {@link FieldWriter} objects, linked to each other by their
+     * {@link FieldWriter#fv} field. This field stores the last element of
+     * this list.
+     */
+    FieldWriter lastField;
+
+    /**
+     * The methods of this class. These methods are stored in a linked list of
+     * {@link MethodWriter} objects, linked to each other by their
+     * {@link MethodWriter#mv} field. This field stores the first element of
+     * this list.
+     */
+    MethodWriter firstMethod;
+
+    /**
+     * The methods of this class. These methods are stored in a linked list of
+     * {@link MethodWriter} objects, linked to each other by their
+     * {@link MethodWriter#mv} field. This field stores the last element of
+     * this list.
+     */
+    MethodWriter lastMethod;
+
+    /**
+     * <tt>true</tt> if the maximum stack size and number of local variables
+     * must be automatically computed.
+     */
+    private final boolean computeMaxs;
+
+    /**
+     * <tt>true</tt> if the stack map frames must be recomputed from scratch.
+     */
+    private final boolean computeFrames;
+
+    /**
+     * <tt>true</tt> if the stack map tables of this class are invalid. The
+     * {@link MethodWriter#resizeInstructions} method cannot transform existing
+     * stack map tables, and so produces potentially invalid classes when it is
+     * executed. In this case the class is reread and rewritten with the
+     * {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize
+     * stack map tables when this option is used).
+     */
+    boolean invalidFrames;
+
+    // ------------------------------------------------------------------------
+    // Static initializer
+    // ------------------------------------------------------------------------
+
+    /**
+     * Computes the instruction types of JVM opcodes.
+     */
+    static {
+        int i;
+        byte[] b = new byte[220];
+        String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"
+                + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+                + "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA"
+                + "AAAAGGGGGGGHIFBFAAFFAARQJJKKJJJJJJJJJJJJJJJJJJ";
+        for (i = 0; i < b.length; ++i) {
+            b[i] = (byte) (s.charAt(i) - 'A');
+        }
+        TYPE = b;
+
+        // code to generate the above string
+        //
+        // // SBYTE_INSN instructions
+        // b[Constants.NEWARRAY] = SBYTE_INSN;
+        // b[Constants.BIPUSH] = SBYTE_INSN;
+        //
+        // // SHORT_INSN instructions
+        // b[Constants.SIPUSH] = SHORT_INSN;
+        //
+        // // (IMPL)VAR_INSN instructions
+        // b[Constants.RET] = VAR_INSN;
+        // for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) {
+        // b[i] = VAR_INSN;
+        // }
+        // for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) {
+        // b[i] = VAR_INSN;
+        // }
+        // for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3
+        // b[i] = IMPLVAR_INSN;
+        // }
+        // for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3
+        // b[i] = IMPLVAR_INSN;
+        // }
+        //
+        // // TYPE_INSN instructions
+        // b[Constants.NEW] = TYPE_INSN;
+        // b[Constants.ANEWARRAY] = TYPE_INSN;
+        // b[Constants.CHECKCAST] = TYPE_INSN;
+        // b[Constants.INSTANCEOF] = TYPE_INSN;
+        //
+        // // (Set)FIELDORMETH_INSN instructions
+        // for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) {
+        // b[i] = FIELDORMETH_INSN;
+        // }
+        // b[Constants.INVOKEINTERFACE] = ITFMETH_INSN;
+        // b[Constants.INVOKEDYNAMIC] = INDYMETH_INSN;
+        //
+        // // LABEL(W)_INSN instructions
+        // for (i = Constants.IFEQ; i <= Constants.JSR; ++i) {
+        // b[i] = LABEL_INSN;
+        // }
+        // b[Constants.IFNULL] = LABEL_INSN;
+        // b[Constants.IFNONNULL] = LABEL_INSN;
+        // b[200] = LABELW_INSN; // GOTO_W
+        // b[201] = LABELW_INSN; // JSR_W
+        // // temporary opcodes used internally by ASM - see Label and
+        // MethodWriter
+        // for (i = 202; i < 220; ++i) {
+        // b[i] = LABEL_INSN;
+        // }
+        //
+        // // LDC(_W) instructions
+        // b[Constants.LDC] = LDC_INSN;
+        // b[19] = LDCW_INSN; // LDC_W
+        // b[20] = LDCW_INSN; // LDC2_W
+        //
+        // // special instructions
+        // b[Constants.IINC] = IINC_INSN;
+        // b[Constants.TABLESWITCH] = TABL_INSN;
+        // b[Constants.LOOKUPSWITCH] = LOOK_INSN;
+        // b[Constants.MULTIANEWARRAY] = MANA_INSN;
+        // b[196] = WIDE_INSN; // WIDE
+        //
+        // for (i = 0; i < b.length; ++i) {
+        // System.err.print((char)('A' + b[i]));
+        // }
+        // System.err.println();
+    }
+
+    // ------------------------------------------------------------------------
+    // Constructor
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructs a new {@link ClassWriter} object.
+     *
+     * @param flags option flags that can be used to modify the default behavior
+     *        of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
+     */
+    public ClassWriter(final int flags) {
+        super(Opcodes.ASM4);
+        index = 1;
+        pool = new ByteVector();
+        items = new Item[256];
+        threshold = (int) (0.75d * items.length);
+        key = new Item();
+        key2 = new Item();
+        key3 = new Item();
+        key4 = new Item();
+        this.computeMaxs = (flags & COMPUTE_MAXS) != 0;
+        this.computeFrames = (flags & COMPUTE_FRAMES) != 0;
+    }
+
+    /**
+     * Constructs a new {@link ClassWriter} object and enables optimizations for
+     * "mostly add" bytecode transformations. These optimizations are the
+     * following:
+     *
+     * <ul> <li>The constant pool from the original class is copied as is in the
+     * new class, which saves time. New constant pool entries will be added at
+     * the end if necessary, but unused constant pool entries <i>won't be
+     * removed</i>.</li> <li>Methods that are not transformed are copied as is
+     * in the new class, directly from the original class bytecode (i.e. without
+     * emitting visit events for all the method instructions), which saves a
+     * <i>lot</i> of time. Untransformed methods are detected by the fact that
+     * the {@link ClassReader} receives {@link MethodVisitor} objects that come
+     * from a {@link ClassWriter} (and not from any other {@link ClassVisitor}
+     * instance).</li> </ul>
+     *
+     * @param classReader the {@link ClassReader} used to read the original
+     *        class. It will be used to copy the entire constant pool from the
+     *        original class and also to copy other fragments of original
+     *        bytecode where applicable.
+     * @param flags option flags that can be used to modify the default behavior
+     *        of this class. <i>These option flags do not affect methods that
+     *        are copied as is in the new class. This means that the maximum
+     *        stack size nor the stack frames will be computed for these
+     *        methods</i>. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
+     */
+    public ClassWriter(final ClassReader classReader, final int flags) {
+        this(flags);
+        classReader.copyPool(this);
+        this.cr = classReader;
+    }
+
+    // ------------------------------------------------------------------------
+    // Implementation of the ClassVisitor abstract class
+    // ------------------------------------------------------------------------
+
+    @Override
+    public final void visit(
+        final int version,
+        final int access,
+        final String name,
+        final String signature,
+        final String superName,
+        final String[] interfaces)
+    {
+        this.version = version;
+        this.access = access;
+        this.name = newClass(name);
+        thisName = name;
+        if (ClassReader.SIGNATURES && signature != null) {
+            this.signature = newUTF8(signature);
+        }
+        this.superName = superName == null ? 0 : newClass(superName);
+        if (interfaces != null && interfaces.length > 0) {
+            interfaceCount = interfaces.length;
+            this.interfaces = new int[interfaceCount];
+            for (int i = 0; i < interfaceCount; ++i) {
+                this.interfaces[i] = newClass(interfaces[i]);
+            }
+        }
+    }
+
+    @Override
+    public final void visitSource(final String file, final String debug) {
+        if (file != null) {
+            sourceFile = newUTF8(file);
+        }
+        if (debug != null) {
+            sourceDebug = new ByteVector().putUTF8(debug);
+        }
+    }
+
+    @Override
+    public final void visitOuterClass(
+        final String owner,
+        final String name,
+        final String desc)
+    {
+        enclosingMethodOwner = newClass(owner);
+        if (name != null && desc != null) {
+            enclosingMethod = newNameType(name, desc);
+        }
+    }
+
+    @Override
+    public final AnnotationVisitor visitAnnotation(
+        final String desc,
+        final boolean visible)
+    {
+        if (!ClassReader.ANNOTATIONS) {
+            return null;
+        }
+        ByteVector bv = new ByteVector();
+        // write type, and reserve space for values count
+        bv.putShort(newUTF8(desc)).putShort(0);
+        AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2);
+        if (visible) {
+            aw.next = anns;
+            anns = aw;
+        } else {
+            aw.next = ianns;
+            ianns = aw;
+        }
+        return aw;
+    }
+
+    @Override
+    public final void visitAttribute(final Attribute attr) {
+        attr.next = attrs;
+        attrs = attr;
+    }
+
+    @Override
+    public final void visitInnerClass(
+        final String name,
+        final String outerName,
+        final String innerName,
+        final int access)
+    {
+        if (innerClasses == null) {
+            innerClasses = new ByteVector();
+        }
+        ++innerClassesCount;
+        innerClasses.putShort(name == null ? 0 : newClass(name));
+        innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
+        innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
+        innerClasses.putShort(access);
+    }
+
+    @Override
+    public final FieldVisitor visitField(
+        final int access,
+        final String name,
+        final String desc,
+        final String signature,
+        final Object value)
+    {
+        return new FieldWriter(this, access, name, desc, signature, value);
+    }
+
+    @Override
+    public final MethodVisitor visitMethod(
+        final int access,
+        final String name,
+        final String desc,
+        final String signature,
+        final String[] exceptions)
+    {
+        return new MethodWriter(this,
+                access,
+                name,
+                desc,
+                signature,
+                exceptions,
+                computeMaxs,
+                computeFrames);
+    }
+
+    @Override
+    public final void visitEnd() {
+    }
+
+    // ------------------------------------------------------------------------
+    // Other public methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the bytecode of the class that was build with this class writer.
+     *
+     * @return the bytecode of the class that was build with this class writer.
+     */
+    public byte[] toByteArray() {
+        if (index > Short.MAX_VALUE) {
+            throw new RuntimeException("Class file too large!");
+        }
+        // computes the real size of the bytecode of this class
+        int size = 24 + 2 * interfaceCount;
+        int nbFields = 0;
+        FieldWriter fb = firstField;
+        while (fb != null) {
+            ++nbFields;
+            size += fb.getSize();
+            fb = (FieldWriter) fb.fv;
+        }
+        int nbMethods = 0;
+        MethodWriter mb = firstMethod;
+        while (mb != null) {
+            ++nbMethods;
+            size += mb.getSize();
+            mb = (MethodWriter) mb.mv;
+        }
+        int attributeCount = 0;
+        if (bootstrapMethods != null) {  // we put it as first argument in order
+                                         // to improve a bit ClassReader.copyBootstrapMethods
+            ++attributeCount;
+            size += 8 + bootstrapMethods.length;
+            newUTF8("BootstrapMethods");
+        }
+        if (ClassReader.SIGNATURES && signature != 0) {
+            ++attributeCount;
+            size += 8;
+            newUTF8("Signature");
+        }
+        if (sourceFile != 0) {
+            ++attributeCount;
+            size += 8;
+            newUTF8("SourceFile");
+        }
+        if (sourceDebug != null) {
+            ++attributeCount;
+            size += sourceDebug.length + 4;
+            newUTF8("SourceDebugExtension");
+        }
+        if (enclosingMethodOwner != 0) {
+            ++attributeCount;
+            size += 10;
+            newUTF8("EnclosingMethod");
+        }
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            ++attributeCount;
+            size += 6;
+            newUTF8("Deprecated");
+        }
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0
+                && ((version & 0xFFFF) < Opcodes.V1_5 || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0))
+        {
+            ++attributeCount;
+            size += 6;
+            newUTF8("Synthetic");
+        }
+        if (innerClasses != null) {
+            ++attributeCount;
+            size += 8 + innerClasses.length;
+            newUTF8("InnerClasses");
+        }
+        if (ClassReader.ANNOTATIONS && anns != null) {
+            ++attributeCount;
+            size += 8 + anns.getSize();
+            newUTF8("RuntimeVisibleAnnotations");
+        }
+        if (ClassReader.ANNOTATIONS && ianns != null) {
+            ++attributeCount;
+            size += 8 + ianns.getSize();
+            newUTF8("RuntimeInvisibleAnnotations");
+        }
+        if (attrs != null) {
+            attributeCount += attrs.getCount();
+            size += attrs.getSize(this, null, 0, -1, -1);
+        }
+        size += pool.length;
+        // allocates a byte vector of this size, in order to avoid unnecessary
+        // arraycopy operations in the ByteVector.enlarge() method
+        ByteVector out = new ByteVector(size);
+        out.putInt(0xCAFEBABE).putInt(version);
+        out.putShort(index).putByteArray(pool.data, 0, pool.length);
+        int mask = Opcodes.ACC_DEPRECATED
+                | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+                | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC));
+        out.putShort(access & ~mask).putShort(name).putShort(superName);
+        out.putShort(interfaceCount);
+        for (int i = 0; i < interfaceCount; ++i) {
+            out.putShort(interfaces[i]);
+        }
+        out.putShort(nbFields);
+        fb = firstField;
+        while (fb != null) {
+            fb.put(out);
+            fb = (FieldWriter) fb.fv;
+        }
+        out.putShort(nbMethods);
+        mb = firstMethod;
+        while (mb != null) {
+            mb.put(out);
+            mb = (MethodWriter) mb.mv;
+        }
+        out.putShort(attributeCount);
+        if (bootstrapMethods != null) {   // should be the first class attribute ?
+            out.putShort(newUTF8("BootstrapMethods"));
+            out.putInt(bootstrapMethods.length + 2).putShort(bootstrapMethodsCount);
+            out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length);
+        }
+        if (ClassReader.SIGNATURES && signature != 0) {
+            out.putShort(newUTF8("Signature")).putInt(2).putShort(signature);
+        }
+        if (sourceFile != 0) {
+            out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);
+        }
+        if (sourceDebug != null) {
+            int len = sourceDebug.length - 2;
+            out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
+            out.putByteArray(sourceDebug.data, 2, len);
+        }
+        if (enclosingMethodOwner != 0) {
+            out.putShort(newUTF8("EnclosingMethod")).putInt(4);
+            out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
+        }
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            out.putShort(newUTF8("Deprecated")).putInt(0);
+        }
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0
+                && ((version & 0xFFFF) < Opcodes.V1_5 || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0))
+        {
+            out.putShort(newUTF8("Synthetic")).putInt(0);
+        }
+        if (innerClasses != null) {
+            out.putShort(newUTF8("InnerClasses"));
+            out.putInt(innerClasses.length + 2).putShort(innerClassesCount);
+            out.putByteArray(innerClasses.data, 0, innerClasses.length);
+        }
+        if (ClassReader.ANNOTATIONS && anns != null) {
+            out.putShort(newUTF8("RuntimeVisibleAnnotations"));
+            anns.put(out);
+        }
+        if (ClassReader.ANNOTATIONS && ianns != null) {
+            out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
+            ianns.put(out);
+        }
+        if (attrs != null) {
+            attrs.put(this, null, 0, -1, -1, out);
+        }
+        if (invalidFrames) {
+            ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
+            new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES);
+            return cw.toByteArray();
+        }
+        return out.data;
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods: constant pool management
+    // ------------------------------------------------------------------------
+
+    /**
+     * Adds a number or string constant to the constant pool of the class being
+     * build. Does nothing if the constant pool already contains a similar item.
+     *
+     * @param cst the value of the constant to be added to the constant pool.
+     *        This parameter must be an {@link Integer}, a {@link Float}, a
+     *        {@link Long}, a {@link Double}, a {@link String} or a
+     *        {@link Type}.
+     * @return a new or already existing constant item with the given value.
+     */
+    Item newConstItem(final Object cst) {
+        if (cst instanceof Integer) {
+            int val = ((Integer) cst).intValue();
+            return newInteger(val);
+        } else if (cst instanceof Byte) {
+            int val = ((Byte) cst).intValue();
+            return newInteger(val);
+        } else if (cst instanceof Character) {
+            int val = ((Character) cst).charValue();
+            return newInteger(val);
+        } else if (cst instanceof Short) {
+            int val = ((Short) cst).intValue();
+            return newInteger(val);
+        } else if (cst instanceof Boolean) {
+            int val = ((Boolean) cst).booleanValue() ? 1 : 0;
+            return newInteger(val);
+        } else if (cst instanceof Float) {
+            float val = ((Float) cst).floatValue();
+            return newFloat(val);
+        } else if (cst instanceof Long) {
+            long val = ((Long) cst).longValue();
+            return newLong(val);
+        } else if (cst instanceof Double) {
+            double val = ((Double) cst).doubleValue();
+            return newDouble(val);
+        } else if (cst instanceof String) {
+            return newString((String) cst);
+        } else if (cst instanceof Type) {
+            Type t = (Type) cst;
+            int s = t.getSort();
+            if (s == Type.ARRAY) {
+                return newClassItem(t.getDescriptor());
+            } else if (s == Type.OBJECT) {
+                return newClassItem(t.getInternalName());
+            } else { // s == Type.METHOD
+                return newMethodTypeItem(t.getDescriptor());
+            }
+        } else if (cst instanceof Handle) {
+            Handle h = (Handle) cst;
+            return newHandleItem(h.tag, h.owner, h.name, h.desc);
+        } else {
+            throw new IllegalArgumentException("value " + cst);
+        }
+    }
+
+    /**
+     * Adds a number or string constant to the constant pool of the class being
+     * build. Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param cst the value of the constant to be added to the constant pool.
+     *        This parameter must be an {@link Integer}, a {@link Float}, a
+     *        {@link Long}, a {@link Double} or a {@link String}.
+     * @return the index of a new or already existing constant item with the
+     *         given value.
+     */
+    public int newConst(final Object cst) {
+        return newConstItem(cst).index;
+    }
+
+    /**
+     * Adds an UTF8 string to the constant pool of the class being build. Does
+     * nothing if the constant pool already contains a similar item. <i>This
+     * method is intended for {@link Attribute} sub classes, and is normally not
+     * needed by class generators or adapters.</i>
+     *
+     * @param value the String value.
+     * @return the index of a new or already existing UTF8 item.
+     */
+    public int newUTF8(final String value) {
+        key.set(UTF8, value, null, null);
+        Item result = get(key);
+        if (result == null) {
+            pool.putByte(UTF8).putUTF8(value);
+            result = new Item(index++, key);
+            put(result);
+        }
+        return result.index;
+    }
+
+    /**
+     * Adds a class reference to the constant pool of the class being build.
+     * Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param value the internal name of the class.
+     * @return a new or already existing class reference item.
+     */
+    Item newClassItem(final String value) {
+        key2.set(CLASS, value, null, null);
+        Item result = get(key2);
+        if (result == null) {
+            pool.put12(CLASS, newUTF8(value));
+            result = new Item(index++, key2);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a class reference to the constant pool of the class being build.
+     * Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param value the internal name of the class.
+     * @return the index of a new or already existing class reference item.
+     */
+    public int newClass(final String value) {
+        return newClassItem(value).index;
+    }
+
+    /**
+     * Adds a method type reference to the constant pool of the class being
+     * build. Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param methodDesc method descriptor of the method type.
+     * @return a new or already existing method type reference item.
+     */
+    Item newMethodTypeItem(final String methodDesc) {
+        key2.set(MTYPE, methodDesc, null, null);
+        Item result = get(key2);
+        if (result == null) {
+            pool.put12(MTYPE, newUTF8(methodDesc));
+            result = new Item(index++, key2);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a method type reference to the constant pool of the class being
+     * build. Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param methodDesc method descriptor of the method type.
+     * @return the index of a new or already existing method type reference
+     *         item.
+     */
+    public int newMethodType(final String methodDesc) {
+        return newMethodTypeItem(methodDesc).index;
+    }
+
+    /**
+     * Adds a handle to the constant pool of the class being build. Does nothing
+     * if the constant pool already contains a similar item. <i>This method is
+     * intended for {@link Attribute} sub classes, and is normally not needed by
+     * class generators or adapters.</i>
+     *
+     * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
+     *        {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
+     *        {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
+     *        {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
+     *        {@link Opcodes#H_NEWINVOKESPECIAL} or
+     *        {@link Opcodes#H_INVOKEINTERFACE}.
+     * @param owner the internal name of the field or method owner class.
+     * @param name the name of the field or method.
+     * @param desc the descriptor of the field or method.
+     * @return a new or an already existing method type reference item.
+     */
+    Item newHandleItem(
+        final int tag,
+        final String owner,
+        final String name,
+        final String desc)
+    {
+        key4.set(HANDLE_BASE + tag, owner, name, desc);
+        Item result = get(key4);
+        if (result == null) {
+            if (tag <= Opcodes.H_PUTSTATIC) {
+                put112(HANDLE, tag, newField(owner, name, desc));
+            } else {
+                put112(HANDLE, tag, newMethod(owner,
+                        name,
+                        desc,
+                        tag == Opcodes.H_INVOKEINTERFACE));
+            }
+            result = new Item(index++, key4);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a handle to the constant pool of the class being
+     * build. Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
+     *        {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
+     *        {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
+     *        {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
+     *        {@link Opcodes#H_NEWINVOKESPECIAL} or
+     *        {@link Opcodes#H_INVOKEINTERFACE}.
+     * @param owner the internal name of the field or method owner class.
+     * @param name the name of the field or method.
+     * @param desc the descriptor of the field or method.
+     * @return the index of a new or already existing method type reference
+     *         item.
+     */
+    public int newHandle(
+        final int tag,
+        final String owner,
+        final String name,
+        final String desc)
+    {
+        return newHandleItem(tag, owner, name, desc).index;
+    }
+
+    /**
+     * Adds an invokedynamic reference to the constant pool of the class being
+     * build. Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param name name of the invoked method.
+     * @param desc descriptor of the invoke method.
+     * @param bsm the bootstrap method.
+     * @param bsmArgs the bootstrap method constant arguments.
+     *
+     * @return a new or an already existing invokedynamic type reference item.
+     */
+    Item newInvokeDynamicItem(
+        final String name,
+        final String desc,
+        final Handle bsm,
+        final Object... bsmArgs)
+    {
+        // cache for performance
+        ByteVector bootstrapMethods = this.bootstrapMethods;
+        if (bootstrapMethods == null) {
+            bootstrapMethods = this.bootstrapMethods = new ByteVector();
+        }
+
+        int position = bootstrapMethods.length; // record current position
+
+        int hashCode = bsm.hashCode();
+        bootstrapMethods.putShort(newHandle(bsm.tag,
+                bsm.owner,
+                bsm.name,
+                bsm.desc));
+
+        int argsLength = bsmArgs.length;
+        bootstrapMethods.putShort(argsLength);
+
+        for (int i = 0; i < argsLength; i++) {
+            Object bsmArg = bsmArgs[i];
+            hashCode ^= bsmArg.hashCode();
+            bootstrapMethods.putShort(newConst(bsmArg));
+        }
+
+        byte[] data = bootstrapMethods.data;
+        int length = (1 + 1 + argsLength) << 1; // (bsm + argCount + arguments)
+        hashCode &= 0x7FFFFFFF;
+        Item result = items[hashCode % items.length];
+        loop: while (result != null) {
+            if (result.type != BSM || result.hashCode != hashCode) {
+                result = result.next;
+                continue;
+            }
+
+            // because the data encode the size of the argument
+            // we don't need to test if these size are equals
+            int resultPosition = result.intVal;
+            for (int p = 0; p < length; p++) {
+                if (data[position + p] != data[resultPosition + p]) {
+                    result = result.next;
+                    continue loop;
+                }
+            }
+            break;
+        }
+
+        int bootstrapMethodIndex;
+        if (result != null) {
+            bootstrapMethodIndex = result.index;
+            bootstrapMethods.length = position; // revert to old position
+        } else {
+            bootstrapMethodIndex = bootstrapMethodsCount++;
+            result = new Item(bootstrapMethodIndex);
+            result.set(position, hashCode);
+            put(result);
+        }
+
+        // now, create the InvokeDynamic constant
+        key3.set(name, desc, bootstrapMethodIndex);
+        result = get(key3);
+        if (result == null) {
+            put122(INDY, bootstrapMethodIndex, newNameType(name, desc));
+            result = new Item(index++, key3);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds an invokedynamic reference to the constant pool of the class being
+     * build. Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param name name of the invoked method.
+     * @param desc descriptor of the invoke method.
+     * @param bsm the bootstrap method.
+     * @param bsmArgs the bootstrap method constant arguments.
+     *
+     * @return the index of a new or already existing invokedynamic
+     *         reference item.
+     */
+    public int newInvokeDynamic(
+        final String name,
+        final String desc,
+        final Handle bsm,
+        final Object... bsmArgs)
+    {
+        return newInvokeDynamicItem(name, desc, bsm, bsmArgs).index;
+    }
+
+    /**
+     * Adds a field reference to the constant pool of the class being build.
+     * Does nothing if the constant pool already contains a similar item.
+     *
+     * @param owner the internal name of the field's owner class.
+     * @param name the field's name.
+     * @param desc the field's descriptor.
+     * @return a new or already existing field reference item.
+     */
+    Item newFieldItem(final String owner, final String name, final String desc)
+    {
+        key3.set(FIELD, owner, name, desc);
+        Item result = get(key3);
+        if (result == null) {
+            put122(FIELD, newClass(owner), newNameType(name, desc));
+            result = new Item(index++, key3);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a field reference to the constant pool of the class being build.
+     * Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param owner the internal name of the field's owner class.
+     * @param name the field's name.
+     * @param desc the field's descriptor.
+     * @return the index of a new or already existing field reference item.
+     */
+    public int newField(final String owner, final String name, final String desc)
+    {
+        return newFieldItem(owner, name, desc).index;
+    }
+
+    /**
+     * Adds a method reference to the constant pool of the class being build.
+     * Does nothing if the constant pool already contains a similar item.
+     *
+     * @param owner the internal name of the method's owner class.
+     * @param name the method's name.
+     * @param desc the method's descriptor.
+     * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
+     * @return a new or already existing method reference item.
+     */
+    Item newMethodItem(
+        final String owner,
+        final String name,
+        final String desc,
+        final boolean itf)
+    {
+        int type = itf ? IMETH : METH;
+        key3.set(type, owner, name, desc);
+        Item result = get(key3);
+        if (result == null) {
+            put122(type, newClass(owner), newNameType(name, desc));
+            result = new Item(index++, key3);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a method reference to the constant pool of the class being build.
+     * Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param owner the internal name of the method's owner class.
+     * @param name the method's name.
+     * @param desc the method's descriptor.
+     * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
+     * @return the index of a new or already existing method reference item.
+     */
+    public int newMethod(
+        final String owner,
+        final String name,
+        final String desc,
+        final boolean itf)
+    {
+        return newMethodItem(owner, name, desc, itf).index;
+    }
+
+    /**
+     * Adds an integer to the constant pool of the class being build. Does
+     * nothing if the constant pool already contains a similar item.
+     *
+     * @param value the int value.
+     * @return a new or already existing int item.
+     */
+    Item newInteger(final int value) {
+        key.set(value);
+        Item result = get(key);
+        if (result == null) {
+            pool.putByte(INT).putInt(value);
+            result = new Item(index++, key);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a float to the constant pool of the class being build. Does nothing
+     * if the constant pool already contains a similar item.
+     *
+     * @param value the float value.
+     * @return a new or already existing float item.
+     */
+    Item newFloat(final float value) {
+        key.set(value);
+        Item result = get(key);
+        if (result == null) {
+            pool.putByte(FLOAT).putInt(key.intVal);
+            result = new Item(index++, key);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a long to the constant pool of the class being build. Does nothing
+     * if the constant pool already contains a similar item.
+     *
+     * @param value the long value.
+     * @return a new or already existing long item.
+     */
+    Item newLong(final long value) {
+        key.set(value);
+        Item result = get(key);
+        if (result == null) {
+            pool.putByte(LONG).putLong(value);
+            result = new Item(index, key);
+            index += 2;
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a double to the constant pool of the class being build. Does nothing
+     * if the constant pool already contains a similar item.
+     *
+     * @param value the double value.
+     * @return a new or already existing double item.
+     */
+    Item newDouble(final double value) {
+        key.set(value);
+        Item result = get(key);
+        if (result == null) {
+            pool.putByte(DOUBLE).putLong(key.longVal);
+            result = new Item(index, key);
+            index += 2;
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a string to the constant pool of the class being build. Does nothing
+     * if the constant pool already contains a similar item.
+     *
+     * @param value the String value.
+     * @return a new or already existing string item.
+     */
+    private Item newString(final String value) {
+        key2.set(STR, value, null, null);
+        Item result = get(key2);
+        if (result == null) {
+            pool.put12(STR, newUTF8(value));
+            result = new Item(index++, key2);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a name and type to the constant pool of the class being build. Does
+     * nothing if the constant pool already contains a similar item. <i>This
+     * method is intended for {@link Attribute} sub classes, and is normally not
+     * needed by class generators or adapters.</i>
+     *
+     * @param name a name.
+     * @param desc a type descriptor.
+     * @return the index of a new or already existing name and type item.
+     */
+    public int newNameType(final String name, final String desc) {
+        return newNameTypeItem(name, desc).index;
+    }
+
+    /**
+     * Adds a name and type to the constant pool of the class being build. Does
+     * nothing if the constant pool already contains a similar item.
+     *
+     * @param name a name.
+     * @param desc a type descriptor.
+     * @return a new or already existing name and type item.
+     */
+    Item newNameTypeItem(final String name, final String desc) {
+        key2.set(NAME_TYPE, name, desc, null);
+        Item result = get(key2);
+        if (result == null) {
+            put122(NAME_TYPE, newUTF8(name), newUTF8(desc));
+            result = new Item(index++, key2);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds the given internal name to {@link #typeTable} and returns its index.
+     * Does nothing if the type table already contains this internal name.
+     *
+     * @param type the internal name to be added to the type table.
+     * @return the index of this internal name in the type table.
+     */
+    int addType(final String type) {
+        key.set(TYPE_NORMAL, type, null, null);
+        Item result = get(key);
+        if (result == null) {
+            result = addType(key);
+        }
+        return result.index;
+    }
+
+    /**
+     * Adds the given "uninitialized" type to {@link #typeTable} and returns its
+     * index. This method is used for UNINITIALIZED types, made of an internal
+     * name and a bytecode offset.
+     *
+     * @param type the internal name to be added to the type table.
+     * @param offset the bytecode offset of the NEW instruction that created
+     *        this UNINITIALIZED type value.
+     * @return the index of this internal name in the type table.
+     */
+    int addUninitializedType(final String type, final int offset) {
+        key.type = TYPE_UNINIT;
+        key.intVal = offset;
+        key.strVal1 = type;
+        key.hashCode = 0x7FFFFFFF & (TYPE_UNINIT + type.hashCode() + offset);
+        Item result = get(key);
+        if (result == null) {
+            result = addType(key);
+        }
+        return result.index;
+    }
+
+    /**
+     * Adds the given Item to {@link #typeTable}.
+     *
+     * @param item the value to be added to the type table.
+     * @return the added Item, which a new Item instance with the same value as
+     *         the given Item.
+     */
+    private Item addType(final Item item) {
+        ++typeCount;
+        Item result = new Item(typeCount, key);
+        put(result);
+        if (typeTable == null) {
+            typeTable = new Item[16];
+        }
+        if (typeCount == typeTable.length) {
+            Item[] newTable = new Item[2 * typeTable.length];
+            System.arraycopy(typeTable, 0, newTable, 0, typeTable.length);
+            typeTable = newTable;
+        }
+        typeTable[typeCount] = result;
+        return result;
+    }
+
+    /**
+     * Returns the index of the common super type of the two given types. This
+     * method calls {@link #getCommonSuperClass} and caches the result in the
+     * {@link #items} hash table to speedup future calls with the same
+     * parameters.
+     *
+     * @param type1 index of an internal name in {@link #typeTable}.
+     * @param type2 index of an internal name in {@link #typeTable}.
+     * @return the index of the common super type of the two given types.
+     */
+    int getMergedType(final int type1, final int type2) {
+        key2.type = TYPE_MERGED;
+        key2.longVal = type1 | (((long) type2) << 32);
+        key2.hashCode = 0x7FFFFFFF & (TYPE_MERGED + type1 + type2);
+        Item result = get(key2);
+        if (result == null) {
+            String t = typeTable[type1].strVal1;
+            String u = typeTable[type2].strVal1;
+            key2.intVal = addType(getCommonSuperClass(t, u));
+            result = new Item((short) 0, key2);
+            put(result);
+        }
+        return result.intVal;
+    }
+
+    /**
+     * Returns the common super type of the two given types. The default
+     * implementation of this method <i>loads<i> the two given classes and uses
+     * the java.lang.Class methods to find the common super class. It can be
+     * overridden to compute this common super type in other ways, in particular
+     * without actually loading any class, or to take into account the class
+     * that is currently being generated by this ClassWriter, which can of
+     * course not be loaded since it is under construction.
+     *
+     * @param type1 the internal name of a class.
+     * @param type2 the internal name of another class.
+     * @return the internal name of the common super class of the two given
+     *         classes.
+     */
+    protected String getCommonSuperClass(final String type1, final String type2)
+    {
+        Class<?> c, d;
+        ClassLoader classLoader = getClass().getClassLoader();
+        try {
+            c = Class.forName(type1.replace('/', '.'), false, classLoader);
+            d = Class.forName(type2.replace('/', '.'), false, classLoader);
+        } catch (Exception e) {
+            throw new RuntimeException(e.toString());
+        }
+        if (c.isAssignableFrom(d)) {
+            return type1;
+        }
+        if (d.isAssignableFrom(c)) {
+            return type2;
+        }
+        if (c.isInterface() || d.isInterface()) {
+            return "java/lang/Object";
+        } else {
+            do {
+                c = c.getSuperclass();
+            } while (!c.isAssignableFrom(d));
+            return c.getName().replace('.', '/');
+        }
+    }
+
+    /**
+     * Returns the constant pool's hash table item which is equal to the given
+     * item.
+     *
+     * @param key a constant pool item.
+     * @return the constant pool's hash table item which is equal to the given
+     *         item, or <tt>null</tt> if there is no such item.
+     */
+    private Item get(final Item key) {
+        Item i = items[key.hashCode % items.length];
+        while (i != null && (i.type != key.type || !key.isEqualTo(i))) {
+            i = i.next;
+        }
+        return i;
+    }
+
+    /**
+     * Puts the given item in the constant pool's hash table. The hash table
+     * <i>must</i> not already contains this item.
+     *
+     * @param i the item to be added to the constant pool's hash table.
+     */
+    private void put(final Item i) {
+        if (index + typeCount > threshold) {
+            int ll = items.length;
+            int nl = ll * 2 + 1;
+            Item[] newItems = new Item[nl];
+            for (int l = ll - 1; l >= 0; --l) {
+                Item j = items[l];
+                while (j != null) {
+                    int index = j.hashCode % newItems.length;
+                    Item k = j.next;
+                    j.next = newItems[index];
+                    newItems[index] = j;
+                    j = k;
+                }
+            }
+            items = newItems;
+            threshold = (int) (nl * 0.75);
+        }
+        int index = i.hashCode % items.length;
+        i.next = items[index];
+        items[index] = i;
+    }
+
+    /**
+     * Puts one byte and two shorts into the constant pool.
+     *
+     * @param b a byte.
+     * @param s1 a short.
+     * @param s2 another short.
+     */
+    private void put122(final int b, final int s1, final int s2) {
+        pool.put12(b, s1).putShort(s2);
+    }
+
+    /**
+     * Puts two bytes and one short into the constant pool.
+     *
+     * @param b1 a byte.
+     * @param b2 another byte.
+     * @param s a short.
+     */
+    private void put112(final int b1, final int b2, final int s) {
+        pool.put11(b1, b2).putShort(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/Edge.java	Sat Oct 20 22:49:26 2012 +0100
@@ -0,0 +1,104 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * 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 jdk.internal.org.objectweb.asm;
+
+/**
+ * An edge in the control flow graph of a method body. See {@link Label Label}.
+ *
+ * @author Eric Bruneton
+ */
+class Edge {
+
+    /**
+     * Denotes a normal control flow graph edge.
+     */
+    static final int NORMAL = 0;
+
+    /**
+     * Denotes a control flow graph edge corresponding to an exception handler.
+     * More precisely any {@link Edge} whose {@link #info} is strictly positive
+     * corresponds to an exception handler. The actual value of {@link #info} is
+     * the index, in the {@link ClassWriter} type table, of the exception that
+     * is catched.
+     */
+    static final int EXCEPTION = 0x7FFFFFFF;
+
+    /**
+     * Information about this control flow graph edge. If
+     * {@link ClassWriter#COMPUTE_MAXS} is used this field is the (relative)
+     * stack size in the basic block from which this edge originates. This size
+     * is equal to the stack size at the "jump" instruction to which this edge
+     * corresponds, relatively to the stack size at the beginning of the
+     * originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used,
+     * this field is the kind of this control flow graph edge (i.e. NORMAL or
+     * EXCEPTION).
+     */
+    int info;
+
+    /**
+     * The successor block of the basic block from which this edge originates.
+     */
+    Label successor;
+
+    /**
+     * The next edge in the list of successors of the originating basic block.
+     * See {@link Label#successors successors}.
+     */
+    Edge next;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/FieldVisitor.java	Sat Oct 20 22:49:26 2012 +0100
@@ -0,0 +1,144 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * 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 jdk.internal.org.objectweb.asm;
+
+/**
+ * A visitor to visit a Java field. The methods of this class must be called
+ * in the following order: ( <tt>visitAnnotation</tt> |
+ * <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class FieldVisitor {
+
+    /**
+     * The ASM API version implemented by this visitor. The value of this field
+     * must be one of {@link Opcodes#ASM4}.
+     */
+    protected final int api;
+
+    /**
+     * The field visitor to which this visitor must delegate method calls. May
+     * be null.
+     */
+    protected FieldVisitor fv;
+
+    /**
+     * Constructs a new {@link FieldVisitor}.
+     *
+     * @param api the ASM API version implemented by this visitor. Must be one
+     *        of {@link Opcodes#ASM4}.
+     */
+    public FieldVisitor(final int api) {
+        this(api, null);
+    }
+
+    /**
+     * Constructs a new {@link FieldVisitor}.
+     *
+     * @param api the ASM API version implemented by this visitor. Must be one
+     *        of {@link Opcodes#ASM4}.
+     * @param fv the field visitor to which this visitor must delegate method
+     *        calls. May be null.
+     */
+    public FieldVisitor(final int api, final FieldVisitor fv) {
+        /*if (api != Opcodes.ASM4) {
+            throw new IllegalArgumentException();
+        }*/
+        this.api = api;
+        this.fv = fv;
+    }
+
+    /**
+     * Visits an annotation of the field.
+     *
+     * @param desc the class descriptor of the annotation class.
+     * @param visible <tt>true</tt> if the annotation is visible at runtime.
+     * @return a visitor to visit the annotation values, or <tt>null</tt> if
+     *         this visitor is not interested in visiting this annotation.
+     */
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        if (fv != null) {
+            return fv.visitAnnotation(desc, visible);
+        }
+        return null;
+    }
+
+    /**
+     * Visits a non standard attribute of the field.
+     *
+     * @param attr an attribute.
+     */
+    public void visitAttribute(Attribute attr) {
+        if (fv != null) {
+            fv.visitAttribute(attr);
+        }
+    }
+
+    /**
+     * Visits the end of the field. This method, which is the last one to be
+     * called, is used to inform the visitor that all the annotations and
+     * attributes of the field have been visited.
+     */
+    public void visitEnd() {
+        if (fv != null) {
+            fv.visitEnd();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/FieldWriter.java	Sat Oct 20 22:49:26 2012 +0100
@@ -0,0 +1,300 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * 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 jdk.internal.org.objectweb.asm;
+
+/**
+ * An {@link FieldVisitor} that generates Java fields in bytecode form.
+ *
+ * @author Eric Bruneton
+ */
+final class FieldWriter extends FieldVisitor {
+
+    /**
+     * The class writer to which this field must be added.
+     */
+    private final ClassWriter cw;
+
+    /**
+     * Access flags of this field.
+     */
+    private final int access;
+
+    /**
+     * The index of the constant pool item that contains the name of this
+     * method.
+     */
+    private final int name;
+
+    /**
+     * The index of the constant pool item that contains the descriptor of this
+     * field.
+     */
+    private final int desc;
+
+    /**
+     * The index of the constant pool item that contains the signature of this
+     * field.
+     */
+    private int signature;
+
+    /**
+     * The index of the constant pool item that contains the constant value of
+     * this field.
+     */
+    private int value;
+
+    /**
+     * The runtime visible annotations of this field. May be <tt>null</tt>.
+     */
+    private AnnotationWriter anns;
+
+    /**
+     * The runtime invisible annotations of this field. May be <tt>null</tt>.
+     */
+    private AnnotationWriter ianns;
+
+    /**
+     * The non standard attributes of this field. May be <tt>null</tt>.
+     */
+    private Attribute attrs;
+
+    // ------------------------------------------------------------------------
+    // Constructor
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructs a new {@link FieldWriter}.
+     *
+     * @param cw the class writer to which this field must be added.
+     * @param access the field's access flags (see {@link Opcodes}).
+     * @param name the field's name.
+     * @param desc the field's descriptor (see {@link Type}).
+     * @param signature the field's signature. May be <tt>null</tt>.
+     * @param value the field's constant value. May be <tt>null</tt>.
+     */
+    FieldWriter(
+        final ClassWriter cw,
+        final int access,
+        final String name,
+        final String desc,
+        final String signature,
+        final Object value)
+    {
+        super(Opcodes.ASM4);
+        if (cw.firstField == null) {
+            cw.firstField = this;
+        } else {
+            cw.lastField.fv = this;
+        }
+        cw.lastField = this;
+        this.cw = cw;
+        this.access = access;
+        this.name = cw.newUTF8(name);
+        this.desc = cw.newUTF8(desc);
+        if (ClassReader.SIGNATURES && signature != null) {
+            this.signature = cw.newUTF8(signature);
+        }
+        if (value != null) {
+            this.value = cw.newConstItem(value).index;
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Implementation of the FieldVisitor abstract class
+    // ------------------------------------------------------------------------
+
+    @Override
+    public AnnotationVisitor visitAnnotation(
+        final String desc,
+        final boolean visible)
+    {
+        if (!ClassReader.ANNOTATIONS) {
+            return null;
+        }
+        ByteVector bv = new ByteVector();
+        // write type, and reserve space for values count
+        bv.putShort(cw.newUTF8(desc)).putShort(0);
+        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
+        if (visible) {
+            aw.next = anns;
+            anns = aw;
+        } else {
+            aw.next = ianns;
+            ianns = aw;
+        }
+        return aw;
+    }
+
+    @Override
+    public void visitAttribute(final Attribute attr) {
+        attr.next = attrs;
+        attrs = attr;
+    }
+
+    @Override
+    public void visitEnd() {
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the size of this field.
+     *
+     * @return the size of this field.
+     */
+    int getSize() {
+        int size = 8;
+        if (value != 0) {
+            cw.newUTF8("ConstantValue");
+            size += 8;
+        }
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0
+                && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
+        {
+            cw.newUTF8("Synthetic");
+            size += 6;
+        }
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            cw.newUTF8("Deprecated");
+            size += 6;
+        }
+        if (ClassReader.SIGNATURES && signature != 0) {
+            cw.newUTF8("Signature");
+            size += 8;
+        }
+        if (ClassReader.ANNOTATIONS && anns != null) {
+            cw.newUTF8("RuntimeVisibleAnnotations");
+            size += 8 + anns.getSize();
+        }
+        if (ClassReader.ANNOTATIONS && ianns != null) {
+            cw.newUTF8("RuntimeInvisibleAnnotations");
+            size += 8 + ianns.getSize();
+        }
+        if (attrs != null) {
+            size += attrs.getSize(cw, null, 0, -1, -1);
+        }
+        return size;
+    }
+
+    /**
+     * Puts the content of this field into the given byte vector.
+     *
+     * @param out where the content of this field must be put.
+     */
+    void put(final ByteVector out) {
+        int mask = Opcodes.ACC_DEPRECATED
+                | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+                | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC));
+        out.putShort(access & ~mask).putShort(name).putShort(desc);
+        int attributeCount = 0;
+        if (value != 0) {
+            ++attributeCount;
+        }
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0
+                && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
+        {
+            ++attributeCount;
+        }
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            ++attributeCount;
+        }
+        if (ClassReader.SIGNATURES && signature != 0) {
+            ++attributeCount;
+        }
+        if (ClassReader.ANNOTATIONS && anns != null) {
+            ++attributeCount;
+        }
+        if (ClassReader.ANNOTATIONS && ianns != null) {
+            ++attributeCount;
+        }
+        if (attrs != null) {
+            attributeCount += attrs.getCount();
+        }
+        out.putShort(attributeCount);
+        if (value != 0) {
+            out.putShort(cw.newUTF8("ConstantValue"));
+            out.putInt(2).putShort(value);
+        }
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0
+                && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
+        {
+            out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+        }
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            out.putShort(cw.newUTF8("Deprecated")).putInt(0);
+        }
+        if (ClassReader.SIGNATURES && signature != 0) {
+            out.putShort(cw.newUTF8("Signature"));
+            out.putInt(2).putShort(signature);
+        }
+        if (ClassReader.ANNOTATIONS && anns != null) {
+            out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
+            anns.put(out);
+        }
+        if (ClassReader.ANNOTATIONS && ianns != null) {
+            out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
+            ianns.put(out);
+        }
+        if (attrs != null) {
+            attrs.put(cw, null, 0, -1, -1, out);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/Frame.java	Sat Oct 20 22:49:26 2012 +0100
@@ -0,0 +1,1464 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * 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 jdk.internal.org.objectweb.asm;
+
+/**
+ * Information about the input and output stack map frames of a basic block.
+ *
+ * @author Eric Bruneton
+ */
+final class Frame {
+
+    /*
+     * Frames are computed in a two steps process: during the visit of each
+     * instruction, the state of the frame at the end of current basic block is
+     * updated by simulating the action of the instruction on the previous state
+     * of this so called "output frame". In visitMaxs, a fix point algorithm is
+     * used to compute the "input frame" of each basic block, i.e. the stack map
+     * frame at the beginning of the basic block, starting from the input frame
+     * of the first basic block (which is computed from the method descriptor),
+     * and by using the previously computed output frames to compute the input
+     * state of the other blocks.
+     *
+     * All output and input frames are stored as arrays of integers. Reference
+     * and array types are represented by an index into a type table (which is
+     * not the same as the constant pool of the class, in order to avoid adding
+     * unnecessary constants in the pool - not all computed frames will end up
+     * being stored in the stack map table). This allows very fast type
+     * comparisons.
+     *
+     * Output stack map frames are computed relatively to the input frame of the
+     * basic block, which is not yet known when output frames are computed. It
+     * is therefore necessary to be able to represent abstract types such as
+     * "the type at position x in the input frame locals" or "the type at
+     * position x from the top of the input frame stack" or even "the type at
+     * position x in the input frame, with y more (or less) array dimensions".
+     * This explains the rather complicated type format used in output frames.
+     *
+     * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a
+     * signed number of array dimensions (from -8 to 7). KIND is either BASE,
+     * LOCAL or STACK. BASE is used for types that are not relative to the input
+     * frame. LOCAL is used for types that are relative to the input local
+     * variable types. STACK is used for types that are relative to the input
+     * stack types. VALUE depends on KIND. For LOCAL types, it is an index in
+     * the input local variable types. For STACK types, it is a position
+     * relatively to the top of input frame stack. For BASE types, it is either
+     * one of the constants defined in FrameVisitor, or for OBJECT and
+     * UNINITIALIZED types, a tag and an index in the type table.
+     *
+     * Output frames can contain types of any kind and with a positive or
+     * negative dimension (and even unassigned types, represented by 0 - which
+     * does not correspond to any valid type value). Input frames can only
+     * contain BASE types of positive or null dimension. In all cases the type
+     * table contains only internal type names (array type descriptors are
+     * forbidden - dimensions must be represented through the DIM field).
+     *
+     * The LONG and DOUBLE types are always represented by using two slots (LONG +
+     * TOP or DOUBLE + TOP), for local variable types as well as in the operand
+     * stack. This is necessary to be able to simulate DUPx_y instructions,
+     * whose effect would be dependent on the actual type values if types were
+     * always represented by a single slot in the stack (and this is not
+     * possible, since actual type values are not always known - cf LOCAL and
+     * STACK type kinds).
+     */
+
+    /**
+     * Mask to get the dimension of a frame type. This dimension is a signed
+     * integer between -8 and 7.
+     */
+    static final int DIM = 0xF0000000;
+
+    /**
+     * Constant to be added to a type to get a type with one more dimension.
+     */
+    static final int ARRAY_OF = 0x10000000;
+
+    /**
+     * Constant to be added to a type to get a type with one less dimension.
+     */
+    static final int ELEMENT_OF = 0xF0000000;
+
+    /**
+     * Mask to get the kind of a frame type.
+     *
+     * @see #BASE
+     * @see #LOCAL
+     * @see #STACK
+     */
+    static final int KIND = 0xF000000;
+
+    /**
+     * Flag used for LOCAL and STACK types. Indicates that if this type happens
+     * to be a long or double type (during the computations of input frames),
+     * then it must be set to TOP because the second word of this value has
+     * been reused to store other data in the basic block. Hence the first word
+     * no longer stores a valid long or double value.
+     */
+    static final int TOP_IF_LONG_OR_DOUBLE = 0x800000;
+
+    /**
+     * Mask to get the value of a frame type.
+     */
+    static final int VALUE = 0x7FFFFF;
+
+    /**
+     * Mask to get the kind of base types.
+     */
+    static final int BASE_KIND = 0xFF00000;
+
+    /**
+     * Mask to get the value of base types.
+     */
+    static final int BASE_VALUE = 0xFFFFF;
+
+    /**
+     * Kind of the types that are not relative to an input stack map frame.
+     */
+    static final int BASE = 0x1000000;
+
+    /**
+     * Base kind of the base reference types. The BASE_VALUE of such types is an
+     * index into the type table.
+     */
+    static final int OBJECT = BASE | 0x700000;
+
+    /**
+     * Base kind of the uninitialized base types. The BASE_VALUE of such types
+     * in an index into the type table (the Item at that index contains both an
+     * instruction offset and an internal class name).
+     */
+    static final int UNINITIALIZED = BASE | 0x800000;
+
+    /**
+     * Kind of the types that are relative to the local variable types of an
+     * input stack map frame. The value of such types is a local variable index.
+     */
+    private static final int LOCAL = 0x2000000;
+
+    /**
+     * Kind of the the types that are relative to the stack of an input stack
+     * map frame. The value of such types is a position relatively to the top of
+     * this stack.
+     */
+    private static final int STACK = 0x3000000;
+
+    /**
+     * The TOP type. This is a BASE type.
+     */
+    static final int TOP = BASE | 0;
+
+    /**
+     * The BOOLEAN type. This is a BASE type mainly used for array types.
+     */
+    static final int BOOLEAN = BASE | 9;
+
+    /**
+     * The BYTE type. This is a BASE type mainly used for array types.
+     */
+    static final int BYTE = BASE | 10;
+
+    /**
+     * The CHAR type. This is a BASE type mainly used for array types.
+     */
+    static final int CHAR = BASE | 11;
+
+    /**
+     * The SHORT type. This is a BASE type mainly used for array types.
+     */
+    static final int SHORT = BASE | 12;
+
+    /**
+     * The INTEGER type. This is a BASE type.
+     */
+    static final int INTEGER = BASE | 1;
+
+    /**
+     * The FLOAT type. This is a BASE type.
+     */
+    static final int FLOAT = BASE | 2;
+
+    /**
+     * The DOUBLE type. This is a BASE type.
+     */
+    static final int DOUBLE = BASE | 3;
+
+    /**
+     * The LONG type. This is a BASE type.
+     */
+    static final int LONG = BASE | 4;
+
+    /**
+     * The NULL type. This is a BASE type.
+     */
+    static final int NULL = BASE | 5;
+
+    /**
+     * The UNINITIALIZED_THIS type. This is a BASE type.
+     */
+    static final int UNINITIALIZED_THIS = BASE | 6;
+
+    /**
+     * The stack size variation corresponding to each JVM instruction. This
+     * stack variation is equal to the size of the values produced by an
+     * instruction, minus the size of the values consumed by this instruction.
+     */
+    static final int[] SIZE;
+
+    /**
+     * Computes the stack size variation corresponding to each JVM instruction.
+     */
+    static {
+        int i;
+        int[] b = new int[202];
+        String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD"
+                + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD"
+                + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED"
+                + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
+        for (i = 0; i < b.length; ++i) {
+            b[i] = s.charAt(i) - 'E';
+        }
+        SIZE = b;
+
+        // code to generate the above string
+        //
+        // int NA = 0; // not applicable (unused opcode or variable size opcode)
+        //
+        // b = new int[] {
+        // 0, //NOP, // visitInsn
+        // 1, //ACONST_NULL, // -
+        // 1, //ICONST_M1, // -
+        // 1, //ICONST_0, // -
+        // 1, //ICONST_1, // -
+        // 1, //ICONST_2, // -
+        // 1, //ICONST_3, // -
+        // 1, //ICONST_4, // -
+        // 1, //ICONST_5, // -
+        // 2, //LCONST_0, // -
+        // 2, //LCONST_1, // -
+        // 1, //FCONST_0, // -
+        // 1, //FCONST_1, // -
+        // 1, //FCONST_2, // -
+        // 2, //DCONST_0, // -
+        // 2, //DCONST_1, // -
+        // 1, //BIPUSH, // visitIntInsn
+        // 1, //SIPUSH, // -
+        // 1, //LDC, // visitLdcInsn
+        // NA, //LDC_W, // -
+        // NA, //LDC2_W, // -
+        // 1, //ILOAD, // visitVarInsn
+        // 2, //LLOAD, // -
+        // 1, //FLOAD, // -
+        // 2, //DLOAD, // -
+        // 1, //ALOAD, // -
+        // NA, //ILOAD_0, // -
+        // NA, //ILOAD_1, // -
+        // NA, //ILOAD_2, // -
+        // NA, //ILOAD_3, // -
+        // NA, //LLOAD_0, // -
+        // NA, //LLOAD_1, // -
+        // NA, //LLOAD_2, // -
+        // NA, //LLOAD_3, // -
+        // NA, //FLOAD_0, // -
+        // NA, //FLOAD_1, // -
+        // NA, //FLOAD_2, // -
+        // NA, //FLOAD_3, // -
+        // NA, //DLOAD_0, // -
+        // NA, //DLOAD_1, // -
+        // NA, //DLOAD_2, // -
+        // NA, //DLOAD_3, // -
+        // NA, //ALOAD_0, // -
+        // NA, //ALOAD_1, // -
+        // NA, //ALOAD_2, // -
+        // NA, //ALOAD_3, // -
+        // -1, //IALOAD, // visitInsn
+        // 0, //LALOAD, // -
+        // -1, //FALOAD, // -
+        // 0, //DALOAD, // -
+        // -1, //AALOAD, // -
+        // -1, //BALOAD, // -
+        // -1, //CALOAD, // -
+        // -1, //SALOAD, // -
+        // -1, //ISTORE, // visitVarInsn
+        // -2, //LSTORE, // -
+        // -1, //FSTORE, // -
+        // -2, //DSTORE, // -
+        // -1, //ASTORE, // -
+        // NA, //ISTORE_0, // -
+        // NA, //ISTORE_1, // -
+        // NA, //ISTORE_2, // -
+        // NA, //ISTORE_3, // -
+        // NA, //LSTORE_0, // -
+        // NA, //LSTORE_1, // -
+        // NA, //LSTORE_2, // -
+        // NA, //LSTORE_3, // -
+        // NA, //FSTORE_0, // -
+        // NA, //FSTORE_1, // -
+        // NA, //FSTORE_2, // -
+        // NA, //FSTORE_3, // -
+        // NA, //DSTORE_0, // -
+        // NA, //DSTORE_1, // -
+        // NA, //DSTORE_2, // -
+        // NA, //DSTORE_3, // -
+        // NA, //ASTORE_0, // -
+        // NA, //ASTORE_1, // -
+        // NA, //ASTORE_2, // -
+        // NA, //ASTORE_3, // -
+        // -3, //IASTORE, // visitInsn
+        // -4, //LASTORE, // -
+        // -3, //FASTORE, // -
+        // -4, //DASTORE, // -
+        // -3, //AASTORE, // -
+        // -3, //BASTORE, // -
+        // -3, //CASTORE, // -
+        // -3, //SASTORE, // -
+        // -1, //POP, // -
+        // -2, //POP2, // -
+        // 1, //DUP, // -
+        // 1, //DUP_X1, // -
+        // 1, //DUP_X2, // -
+        // 2, //DUP2, // -
+        // 2, //DUP2_X1, // -
+        // 2, //DUP2_X2, // -
+        // 0, //SWAP, // -
+        // -1, //IADD, // -
+        // -2, //LADD, // -
+        // -1, //FADD, // -
+        // -2, //DADD, // -
+        // -1, //ISUB, // -
+        // -2, //LSUB, // -
+        // -1, //FSUB, // -
+        // -2, //DSUB, // -
+        // -1, //IMUL, // -
+        // -2, //LMUL, // -
+        // -1, //FMUL, // -
+        // -2, //DMUL, // -
+        // -1, //IDIV, // -
+        // -2, //LDIV, // -
+        // -1, //FDIV, // -
+        // -2, //DDIV, // -
+        // -1, //IREM, // -
+        // -2, //LREM, // -
+        // -1, //FREM, // -
+        // -2, //DREM, // -
+        // 0, //INEG, // -
+        // 0, //LNEG, // -
+        // 0, //FNEG, // -
+        // 0, //DNEG, // -
+        // -1, //ISHL, // -
+        // -1, //LSHL, // -
+        // -1, //ISHR, // -
+        // -1, //LSHR, // -
+        // -1, //IUSHR, // -
+        // -1, //LUSHR, // -
+        // -1, //IAND, // -
+        // -2, //LAND, // -
+        // -1, //IOR, // -
+        // -2, //LOR, // -
+        // -1, //IXOR, // -
+        // -2, //LXOR, // -
+        // 0, //IINC, // visitIincInsn
+        // 1, //I2L, // visitInsn
+        // 0, //I2F, // -
+        // 1, //I2D, // -
+        // -1, //L2I, // -
+        // -1, //L2F, // -
+        // 0, //L2D, // -
+        // 0, //F2I, // -
+        // 1, //F2L, // -
+        // 1, //F2D, // -
+        // -1, //D2I, // -
+        // 0, //D2L, // -
+        // -1, //D2F, // -
+        // 0, //I2B, // -
+        // 0, //I2C, // -
+        // 0, //I2S, // -
+        // -3, //LCMP, // -
+        // -1, //FCMPL, // -
+        // -1, //FCMPG, // -
+        // -3, //DCMPL, // -
+        // -3, //DCMPG, // -
+        // -1, //IFEQ, // visitJumpInsn
+        // -1, //IFNE, // -
+        // -1, //IFLT, // -
+        // -1, //IFGE, // -
+        // -1, //IFGT, // -
+        // -1, //IFLE, // -
+        // -2, //IF_ICMPEQ, // -
+        // -2, //IF_ICMPNE, // -
+        // -2, //IF_ICMPLT, // -
+        // -2, //IF_ICMPGE, // -
+        // -2, //IF_ICMPGT, // -
+        // -2, //IF_ICMPLE, // -
+        // -2, //IF_ACMPEQ, // -
+        // -2, //IF_ACMPNE, // -
+        // 0, //GOTO, // -
+        // 1, //JSR, // -
+        // 0, //RET, // visitVarInsn
+        // -1, //TABLESWITCH, // visiTableSwitchInsn
+        // -1, //LOOKUPSWITCH, // visitLookupSwitch
+        // -1, //IRETURN, // visitInsn
+        // -2, //LRETURN, // -
+        // -1, //FRETURN, // -
+        // -2, //DRETURN, // -
+        // -1, //ARETURN, // -
+        // 0, //RETURN, // -
+        // NA, //GETSTATIC, // visitFieldInsn
+        // NA, //PUTSTATIC, // -
+        // NA, //GETFIELD, // -
+        // NA, //PUTFIELD, // -
+        // NA, //INVOKEVIRTUAL, // visitMethodInsn
+        // NA, //INVOKESPECIAL, // -
+        // NA, //INVOKESTATIC, // -
+        // NA, //INVOKEINTERFACE, // -
+        // NA, //INVOKEDYNAMIC, // visitInvokeDynamicInsn
+        // 1, //NEW, // visitTypeInsn
+        // 0, //NEWARRAY, // visitIntInsn
+        // 0, //ANEWARRAY, // visitTypeInsn
+        // 0, //ARRAYLENGTH, // visitInsn
+        // NA, //ATHROW, // -
+        // 0, //CHECKCAST, // visitTypeInsn
+        // 0, //INSTANCEOF, // -
+        // -1, //MONITORENTER, // visitInsn
+        // -1, //MONITOREXIT, // -
+        // NA, //WIDE, // NOT VISITED
+        // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn
+        // -1, //IFNULL, // visitJumpInsn
+        // -1, //IFNONNULL, // -
+        // NA, //GOTO_W, // -
+        // NA, //JSR_W, // -
+        // };
+        // for (i = 0; i < b.length; ++i) {
+        // System.err.print((char)('E' + b[i]));
+        // }
+        // System.err.println();
+    }
+
+    /**
+     * The label (i.e. basic block) to which these input and output stack map
+     * frames correspond.
+     */
+    Label owner;
+
+    /**
+     * The input stack map frame locals.
+     */
+    int[] inputLocals;
+
+    /**
+     * The input stack map frame stack.
+     */
+    int[] inputStack;
+
+    /**
+     * The output stack map frame locals.
+     */
+    private int[] outputLocals;
+
+    /**
+     * The output stack map frame stack.
+     */
+    private int[] outputStack;
+
+    /**
+     * Relative size of the output stack. The exact semantics of this field
+     * depends on the algorithm that is used.
+     *
+     * When only the maximum stack size is computed, this field is the size of
+     * the output stack relatively to the top of the input stack.
+     *
+     * When the stack map frames are completely computed, this field is the
+     * actual number of types in {@link #outputStack}.
+     */
+    private int outputStackTop;
+
+    /**
+     * Number of types that are initialized in the basic block.
+     *
+     * @see #initializations
+     */
+    private int initializationCount;
+
+    /**
+     * The types that are initialized in the basic block. A constructor
+     * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace
+     * <i>every occurence</i> of this type in the local variables and in the
+     * operand stack. This cannot be done during the first phase of the
+     * algorithm since, during this phase, the local variables and the operand
+     * stack are not completely computed. It is therefore necessary to store the
+     * types on which constructors are invoked in the basic block, in order to
+     * do this replacement during the second phase of the algorithm, where the
+     * frames are fully computed. Note that this array can contain types that
+     * are relative to input locals or to the input stack (see below for the
+     * description of the algorithm).
+     */
+    private int[] initializations;
+
+    /**
+     * Returns the output frame local variable type at the given index.
+     *
+     * @param local the index of the local that must be returned.
+     * @return the output frame local variable type at the given index.
+     */
+    private int get(final int local) {
+        if (outputLocals == null || local >= outputLocals.length) {
+            // this local has never been assigned in this basic block,
+            // so it is still equal to its value in the input frame
+            return LOCAL | local;
+        } else {
+            int type = outputLocals[local];
+            if (type == 0) {
+                // this local has never been assigned in this basic block,
+                // so it is still equal to its value in the input frame
+                type = outputLocals[local] = LOCAL | local;
+            }
+            return type;
+        }
+    }
+
+    /**
+     * Sets the output frame local variable type at the given index.
+     *
+     * @param local the index of the local that must be set.
+     * @param type the value of the local that must be set.
+     */
+    private void set(final int local, final int type) {
+        // creates and/or resizes the output local variables array if necessary
+        if (outputLocals == null) {
+            outputLocals = new int[10];
+        }
+        int n = outputLocals.length;
+        if (local >= n) {
+            int[] t = new int[Math.max(local + 1, 2 * n)];
+            System.arraycopy(outputLocals, 0, t, 0, n);
+            outputLocals = t;
+        }
+        // sets the local variable
+        outputLocals[local] = type;
+    }
+
+    /**
+     * Pushes a new type onto the output frame stack.
+     *
+     * @param type the type that must be pushed.
+     */
+    private void push(final int type) {
+        // creates and/or resizes the output stack array if necessary
+        if (outputStack == null) {
+            outputStack = new int[10];
+        }
+        int n = outputStack.length;
+        if (outputStackTop >= n) {
+            int[] t = new int[Math.max(outputStackTop + 1, 2 * n)];
+            System.arraycopy(outputStack, 0, t, 0, n);
+            outputStack = t;
+        }
+        // pushes the type on the output stack
+        outputStack[outputStackTop++] = type;
+        // updates the maximun height reached by the output stack, if needed
+        int top = owner.inputStackTop + outputStackTop;
+        if (top > owner.outputStackMax) {
+            owner.outputStackMax = top;
+        }
+    }
+
+    /**
+     * Pushes a new type onto the output frame stack.
+     *
+     * @param cw the ClassWriter to which this label belongs.
+     * @param desc the descriptor of the type to be pushed. Can also be a method
+     *        descriptor (in this case this method pushes its return type onto
+     *        the output frame stack).
+     */
+    private void push(final ClassWriter cw, final String desc) {
+        int type = type(cw, desc);
+        if (type != 0) {
+            push(type);
+            if (type == LONG || type == DOUBLE) {
+                push(TOP);
+            }
+        }
+    }
+
+    /**
+     * Returns the int encoding of the given type.
+     *
+     * @param cw the ClassWriter to which this label belongs.
+     * @param desc a type descriptor.
+     * @return the int encoding of the given type.
+     */
+    private static int type(final ClassWriter cw, final String desc) {
+        String t;
+        int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
+        switch (desc.charAt(index)) {
+            case 'V':
+                return 0;
+            case 'Z':
+            case 'C':
+            case 'B':
+            case 'S':
+            case 'I':
+                return INTEGER;
+            case 'F':
+                return FLOAT;
+            case 'J':
+                return LONG;
+            case 'D':
+                return DOUBLE;
+            case 'L':
+                // stores the internal name, not the descriptor!
+                t = desc.substring(index + 1, desc.length() - 1);
+                return OBJECT | cw.addType(t);
+                // case '[':
+            default:
+                // extracts the dimensions and the element type
+                int data;
+                int dims = index + 1;
+                while (desc.charAt(dims) == '[') {
+                    ++dims;
+                }
+                switch (desc.charAt(dims)) {
+                    case 'Z':
+                        data = BOOLEAN;
+                        break;
+                    case 'C':
+                        data = CHAR;
+                        break;
+                    case 'B':
+                        data = BYTE;
+                        break;
+                    case 'S':
+                        data = SHORT;
+                        break;
+                    case 'I':
+                        data = INTEGER;
+                        break;
+                    case 'F':
+                        data = FLOAT;
+                        break;
+                    case 'J':
+                        data = LONG;
+                        break;
+                    case 'D':
+                        data = DOUBLE;
+                        break;
+                    // case 'L':
+                    default:
+                        // stores the internal name, not the descriptor
+                        t = desc.substring(dims + 1, desc.length() - 1);
+                        data = OBJECT | cw.addType(t);
+                }
+                return (dims - index) << 28 | data;
+        }
+    }
+
+    /**
+     * Pops a type from the output frame stack and returns its value.
+     *
+     * @return the type that has been popped from the output frame stack.
+     */
+    private int pop() {
+        if (outputStackTop > 0) {
+            return outputStack[--outputStackTop];
+        } else {
+            // if the output frame stack is empty, pops from the input stack
+            return STACK | -(--owner.inputStackTop);
+        }
+    }
+
+    /**
+     * Pops the given number of types from the output frame stack.
+     *
+     * @param elements the number of types that must be popped.
+     */
+    private void pop(final int elements) {
+        if (outputStackTop >= elements) {
+            outputStackTop -= elements;
+        } else {
+            // if the number of elements to be popped is greater than the number
+            // of elements in the output stack, clear it, and pops the remaining
+            // elements from the input stack.
+            owner.inputStackTop -= elements - outputStackTop;
+            outputStackTop = 0;
+        }
+    }
+
+    /**
+     * Pops a type from the output frame stack.
+     *
+     * @param desc the descriptor of the type to be popped. Can also be a method
+     *        descriptor (in this case this method pops the types corresponding
+     *        to the method arguments).
+     */
+    private void pop(final String desc) {
+        char c = desc.charAt(0);
+        if (c == '(') {
+            pop((Type.getArgumentsAndReturnSizes(desc) >> 2) - 1);
+        } else if (c == 'J' || c == 'D') {
+            pop(2);
+        } else {
+            pop(1);
+        }
+    }
+
+    /**
+     * Adds a new type to the list of types on which a constructor is invoked in
+     * the basic block.
+     *
+     * @param var a type on a which a constructor is invoked.
+     */
+    private void init(final int var) {
+        // creates and/or resizes the initializations array if necessary
+        if (initializations == null) {
+            initializations = new int[2];
+        }
+        int n = initializations.length;
+        if (initializationCount >= n) {
+            int[] t = new int[Math.max(initializationCount + 1, 2 * n)];
+            System.arraycopy(initializations, 0, t, 0, n);
+            initializations = t;
+        }
+        // stores the type to be initialized
+        initializations[initializationCount++] = var;
+    }
+
+    /**
+     * Replaces the given type with the appropriate type if it is one of the
+     * types on which a constructor is invoked in the basic block.
+     *
+     * @param cw the ClassWriter to which this label belongs.
+     * @param t a type
+     * @return t or, if t is one of the types on which a constructor is invoked
+     *         in the basic block, the type corresponding to this constructor.
+     */
+    private int init(final ClassWriter cw, final int t) {
+        int s;
+        if (t == UNINITIALIZED_THIS) {
+            s = OBJECT | cw.addType(cw.thisName);
+        } else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) {
+            String type = cw.typeTable[t & BASE_VALUE].strVal1;
+            s = OBJECT | cw.addType(type);
+        } else {
+            return t;
+        }
+        for (int j = 0; j < initializationCount; ++j) {
+            int u = initializations[j];
+            int dim = u & DIM;
+            int kind = u & KIND;
+            if (kind == LOCAL) {
+                u = dim + inputLocals[u & VALUE];
+            } else if (kind == STACK) {
+                u = dim + inputStack[inputStack.length - (u & VALUE)];
+            }
+            if (t == u) {
+                return s;
+            }
+        }
+        return t;
+    }
+
+    /**
+     * Initializes the input frame of the first basic block from the method
+     * descriptor.
+     *
+     * @param cw the ClassWriter to which this label belongs.
+     * @param access the access flags of the method to which this label belongs.
+     * @param args the formal parameter types of this method.
+     * @param maxLocals the maximum number of local variables of this method.
+     */
+    void initInputFrame(
+        final ClassWriter cw,
+        final int access,
+        final Type[] args,
+        final int maxLocals)
+    {
+        inputLocals = new int[maxLocals];
+        inputStack = new int[0];
+        int i = 0;
+        if ((access & Opcodes.ACC_STATIC) == 0) {
+            if ((access & MethodWriter.ACC_CONSTRUCTOR) == 0) {
+                inputLocals[i++] = OBJECT | cw.addType(cw.thisName);
+            } else {
+                inputLocals[i++] = UNINITIALIZED_THIS;
+            }
+        }
+        for (int j = 0; j < args.length; ++j) {
+            int t = type(cw, args[j].getDescriptor());
+            inputLocals[i++] = t;
+            if (t == LONG || t == DOUBLE) {
+                inputLocals[i++] = TOP;
+            }
+        }
+        while (i < maxLocals) {
+            inputLocals[i++] = TOP;
+        }
+    }
+
+    /**
+     * Simulates the action of the given instruction on the output stack frame.
+     *
+     * @param opcode the opcode of the instruction.
+     * @param arg the operand of the instruction, if any.
+     * @param cw the class writer to which this label belongs.
+     * @param item the operand of the instructions, if any.
+     */
+    void execute(
+        final int opcode,
+        final int arg,
+        final ClassWriter cw,
+        final Item item)
+    {
+        int t1, t2, t3, t4;
+        switch (opcode) {
+            case Opcodes.NOP:
+            case Opcodes.INEG:
+            case Opcodes.LNEG:
+            case Opcodes.FNEG:
+            case Opcodes.DNEG:
+            case Opcodes.I2B:
+            case Opcodes.I2C:
+            case Opcodes.I2S:
+            case Opcodes.GOTO:
+            case Opcodes.RETURN:
+                break;
+            case Opcodes.ACONST_NULL:
+                push(NULL);
+                break;
+            case Opcodes.ICONST_M1:
+            case Opcodes.ICONST_0:
+            case Opcodes.ICONST_1:
+            case Opcodes.ICONST_2:
+            case Opcodes.ICONST_3:
+            case Opcodes.ICONST_4:
+            case Opcodes.ICONST_5:
+            case Opcodes.BIPUSH:
+            case Opcodes.SIPUSH:
+            case Opcodes.ILOAD:
+                push(INTEGER);
+                break;
+            case Opcodes.LCONST_0:
+            case Opcodes.LCONST_1:
+            case Opcodes.LLOAD:
+                push(LONG);
+                push(TOP);
+                break;
+            case Opcodes.FCONST_0:
+            case Opcodes.FCONST_1:
+            case Opcodes.FCONST_2:
+            case Opcodes.FLOAD:
+                push(FLOAT);
+                break;
+            case Opcodes.DCONST_0:
+            case Opcodes.DCONST_1:
+            case Opcodes.DLOAD:
+                push(DOUBLE);
+                push(TOP);
+                break;
+            case Opcodes.LDC:
+                switch (item.type) {
+                    case ClassWriter.INT:
+                        push(INTEGER);
+                        break;
+                    case ClassWriter.LONG:
+                        push(LONG);
+                        push(TOP);
+                        break;
+                    case ClassWriter.FLOAT:
+                        push(FLOAT);
+                        break;
+                    case ClassWriter.DOUBLE:
+                        push(DOUBLE);
+                        push(TOP);
+                        break;
+                    case ClassWriter.CLASS:
+                        push(OBJECT | cw.addType("java/lang/Class"));
+                        break;
+                    case ClassWriter.STR:
+                        push(OBJECT | cw.addType("java/lang/String"));
+                        break;
+                    case ClassWriter.MTYPE:
+                        push(OBJECT | cw.addType("java/lang/invoke/MethodType"));
+                        break;
+                    // case ClassWriter.HANDLE_BASE + [1..9]:
+                    default:
+                        push(OBJECT | cw.addType("java/lang/invoke/MethodHandle"));
+                }
+                break;
+            case Opcodes.ALOAD:
+                push(get(arg));
+                break;
+            case Opcodes.IALOAD:
+            case Opcodes.BALOAD:
+            case Opcodes.CALOAD:
+            case Opcodes.SALOAD:
+                pop(2);
+                push(INTEGER);
+                break;
+            case Opcodes.LALOAD:
+            case Opcodes.D2L:
+                pop(2);
+                push(LONG);
+                push(TOP);
+                break;
+            case Opcodes.FALOAD:
+                pop(2);
+                push(FLOAT);
+                break;
+            case Opcodes.DALOAD:
+            case Opcodes.L2D:
+                pop(2);
+                push(DOUBLE);
+                push(TOP);
+                break;
+            case Opcodes.AALOAD:
+                pop(1);
+                t1 = pop();
+                push(ELEMENT_OF + t1);
+                break;
+            case Opcodes.ISTORE:
+            case Opcodes.FSTORE:
+            case Opcodes.ASTORE:
+                t1 = pop();
+                set(arg, t1);
+                if (arg > 0) {
+                    t2 = get(arg - 1);
+                    // if t2 is of kind STACK or LOCAL we cannot know its size!
+                    if (t2 == LONG || t2 == DOUBLE) {
+                        set(arg - 1, TOP);
+                    } else if ((t2 & KIND) != BASE) {
+                        set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
+                    }
+                }
+                break;
+            case Opcodes.LSTORE:
+            case Opcodes.DSTORE:
+                pop(1);
+                t1 = pop();
+                set(arg, t1);
+                set(arg + 1, TOP);
+                if (arg > 0) {
+                    t2 = get(arg - 1);
+                    // if t2 is of kind STACK or LOCAL we cannot know its size!
+                    if (t2 == LONG || t2 == DOUBLE) {
+                        set(arg - 1, TOP);
+                    } else if ((t2 & KIND) != BASE) {
+                        set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
+                    }
+                }
+                break;
+            case Opcodes.IASTORE:
+            case Opcodes.BASTORE:
+            case Opcodes.CASTORE:
+            case Opcodes.SASTORE:
+            case Opcodes.FASTORE:
+            case Opcodes.AASTORE:
+                pop(3);
+                break;
+            case Opcodes.LASTORE:
+            case Opcodes.DASTORE:
+                pop(4);
+                break;
+            case Opcodes.POP:
+            case Opcodes.IFEQ:
+            case Opcodes.IFNE:
+            case Opcodes.IFLT:
+            case Opcodes.IFGE:
+            case Opcodes.IFGT:
+            case Opcodes.IFLE:
+            case Opcodes.IRETURN:
+            case Opcodes.FRETURN:
+            case Opcodes.ARETURN:
+            case Opcodes.TABLESWITCH:
+            case Opcodes.LOOKUPSWITCH:
+            case Opcodes.ATHROW:
+            case Opcodes.MONITORENTER:
+            case Opcodes.MONITOREXIT:
+            case Opcodes.IFNULL:
+            case Opcodes.IFNONNULL:
+                pop(1);
+                break;
+            case Opcodes.POP2:
+            case Opcodes.IF_ICMPEQ:
+            case Opcodes.IF_ICMPNE:
+            case Opcodes.IF_ICMPLT:
+            case Opcodes.IF_ICMPGE:
+            case Opcodes.IF_ICMPGT:
+            case Opcodes.IF_ICMPLE:
+            case Opcodes.IF_ACMPEQ:
+            case Opcodes.IF_ACMPNE:
+            case Opcodes.LRETURN:
+            case Opcodes.DRETURN:
+                pop(2);
+                break;
+            case Opcodes.DUP:
+                t1 = pop();
+                push(t1);
+                push(t1);
+                break;
+            case Opcodes.DUP_X1:
+                t1 = pop();
+                t2 = pop();
+                push(t1);
+                push(t2);
+                push(t1);
+                break;
+            case Opcodes.DUP_X2:
+                t1 = pop();
+                t2 = pop();
+                t3 = pop();
+                push(t1);
+                push(t3);
+                push(t2);
+                push(t1);
+                break;
+            case Opcodes.DUP2:
+                t1 = pop();
+                t2 = pop();
+                push(t2);
+                push(t1);
+                push(t2);
+                push(t1);
+                break;
+            case Opcodes.DUP2_X1:
+                t1 = pop();
+                t2 = pop();
+                t3 = pop();
+                push(t2);
+                push(t1);
+                push(t3);
+                push(t2);
+                push(t1);
+                break;
+            case Opcodes.DUP2_X2:
+                t1 = pop();
+                t2 = pop();
+                t3 = pop();
+                t4 = pop();
+                push(t2);
+                push(t1);
+                push(t4);
+                push(t3);
+                push(t2);
+                push(t1);
+                break;
+            case Opcodes.SWAP:
+                t1 = pop();
+                t2 = pop();
+                push(t1);
+                push(t2);
+                break;
+            case Opcodes.IADD:
+            case Opcodes.ISUB:
+            case Opcodes.IMUL:
+            case Opcodes.IDIV:
+            case Opcodes.IREM:
+            case Opcodes.IAND:
+            case Opcodes.IOR:
+            case Opcodes.IXOR:
+            case Opcodes.ISHL:
+            case Opcodes.ISHR:
+            case Opcodes.IUSHR:
+            case Opcodes.L2I:
+            case Opcodes.D2I:
+            case Opcodes.FCMPL:
+            case Opcodes.FCMPG:
+                pop(2);
+                push(INTEGER);
+                break;
+            case Opcodes.LADD:
+            case Opcodes.LSUB:
+            case Opcodes.LMUL:
+            case Opcodes.LDIV:
+            case Opcodes.LREM:
+            case Opcodes.LAND:
+            case Opcodes.LOR:
+            case Opcodes.LXOR:
+                pop(4);
+                push(LONG);
+                push(TOP);
+                break;
+            case Opcodes.FADD:
+            case Opcodes.FSUB:
+            case Opcodes.FMUL:
+            case Opcodes.FDIV:
+            case Opcodes.FREM:
+            case Opcodes.L2F:
+            case Opcodes.D2F:
+                pop(2);
+                push(FLOAT);
+                break;
+            case Opcodes.DADD:
+            case Opcodes.DSUB:
+            case Opcodes.DMUL:
+            case Opcodes.DDIV:
+            case Opcodes.DREM:
+                pop(4);
+                push(DOUBLE);
+                push(TOP);
+                break;
+            case Opcodes.LSHL:
+            case Opcodes.LSHR:
+            case Opcodes.LUSHR:
+                pop(3);
+                push(LONG);
+                push(TOP);
+                break;
+            case Opcodes.IINC:
+                set(arg, INTEGER);
+                break;
+            case Opcodes.I2L:
+            case Opcodes.F2L:
+                pop(1);
+                push(LONG);
+                push(TOP);
+                break;
+            case Opcodes.I2F:
+                pop(1);
+                push(FLOAT);
+                break;
+            case Opcodes.I2D:
+            case Opcodes.F2D:
+                pop(1);
+                push(DOUBLE);
+                push(TOP);
+                break;
+            case Opcodes.F2I:
+            case Opcodes.ARRAYLENGTH:
+            case Opcodes.INSTANCEOF:
+                pop(1);
+                push(INTEGER);
+                break;
+            case Opcodes.LCMP:
+            case Opcodes.DCMPL:
+            case Opcodes.DCMPG:
+                pop(4);
+                push(INTEGER);
+                break;
+            case Opcodes.JSR:
+            case Opcodes.RET:
+                throw new RuntimeException("JSR/RET are not supported with computeFrames option");
+            case Opcodes.GETSTATIC:
+                push(cw, item.strVal3);
+                break;
+            case Opcodes.PUTSTATIC:
+                pop(item.strVal3);
+                break;
+            case Opcodes.GETFIELD:
+                pop(1);
+                push(cw, item.strVal3);
+                break;
+            case Opcodes.PUTFIELD:
+                pop(item.strVal3);
+                pop();
+                break;
+            case Opcodes.INVOKEVIRTUAL:
+            case Opcodes.INVOKESPECIAL:
+            case Opcodes.INVOKESTATIC:
+            case Opcodes.INVOKEINTERFACE:
+                pop(item.strVal3);
+                if (opcode != Opcodes.INVOKESTATIC) {
+                    t1 = pop();
+                    if (opcode == Opcodes.INVOKESPECIAL
+                            && item.strVal2.charAt(0) == '<')
+                    {
+                        init(t1);
+                    }
+                }
+                push(cw, item.strVal3);
+                break;
+            case Opcodes.INVOKEDYNAMIC:
+                pop(item.strVal2);
+                push(cw, item.strVal2);
+                break;
+            case Opcodes.NEW:
+                push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
+                break;
+            case Opcodes.NEWARRAY:
+                pop();
+                switch (arg) {
+                    case Opcodes.T_BOOLEAN:
+                        push(ARRAY_OF | BOOLEAN);
+                        break;
+                    case Opcodes.T_CHAR:
+                        push(ARRAY_OF | CHAR);
+                        break;
+                    case Opcodes.T_BYTE:
+                        push(ARRAY_OF | BYTE);
+                        break;
+                    case Opcodes.T_SHORT:
+                        push(ARRAY_OF | SHORT);
+                        break;
+                    case Opcodes.T_INT:
+                        push(ARRAY_OF | INTEGER);
+                        break;
+                    case Opcodes.T_FLOAT:
+                        push(ARRAY_OF | FLOAT);
+                        break;
+                    case Opcodes.T_DOUBLE:
+                        push(ARRAY_OF | DOUBLE);
+                        break;
+                    // case Opcodes.T_LONG:
+                    default:
+                        push(ARRAY_OF | LONG);
+                        break;
+                }
+                break;
+            case Opcodes.ANEWARRAY:
+                String s = item.strVal1;
+                pop();
+                if (s.charAt(0) == '[') {
+                    push(cw, '[' + s);
+                } else {
+                    push(ARRAY_OF | OBJECT | cw.addType(s));
+                }
+                break;
+            case Opcodes.CHECKCAST:
+                s = item.strVal1;
+                pop();
+                if (s.charAt(0) == '[') {
+                    push(cw, s);
+                } else {
+                    push(OBJECT | cw.addType(s));
+                }
+                break;
+            // case Opcodes.MULTIANEWARRAY:
+            default:
+                pop(arg);
+                push(cw, item.strVal1);
+                break;
+        }
+    }
+
+    /**
+     * Merges the input frame of the given basic block with the input and output
+     * frames of this basic block. Returns <tt>true</tt> if the input frame of
+     * the given label has been changed by this operation.
+     *
+     * @param cw the ClassWriter to which this label belongs.
+     * @param frame the basic block whose input frame must be updated.
+     * @param edge the kind of the {@link Edge} between this label and 'label'.
+     *        See {@link Edge#info}.
+     * @return <tt>true</tt> if the input frame of the given label has been
+     *         changed by this operation.
+     */
+    boolean merge(final ClassWriter cw, final Frame frame, final int edge) {
+        boolean changed = false;
+        int i, s, dim, kind, t;
+
+        int nLocal = inputLocals.length;
+        int nStack = inputStack.length;
+        if (frame.inputLocals == null) {
+            frame.inputLocals = new int[nLocal];
+            changed = true;
+        }
+
+        for (i = 0; i < nLocal; ++i) {
+            if (outputLocals != null && i < outputLocals.length) {
+                s = outputLocals[i];
+                if (s == 0) {
+                    t = inputLocals[i];
+                } else {
+                    dim = s & DIM;
+                    kind = s & KIND;
+                    if (kind == BASE) {
+                        t = s;
+                    } else {
+                        if (kind == LOCAL) {
+                            t = dim + inputLocals[s & VALUE];
+                        } else {
+                            t = dim + inputStack[nStack - (s & VALUE)];
+                        }
+                        if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 && (t == LONG || t == DOUBLE)) {
+                            t = TOP;
+                        }
+                    }
+                }
+            } else {
+                t = inputLocals[i];
+            }
+            if (initializations != null) {
+                t = init(cw, t);
+            }
+            changed |= merge(cw, t, frame.inputLocals, i);
+        }
+
+        if (edge > 0) {
+            for (i = 0; i < nLocal; ++i) {
+                t = inputLocals[i];
+                changed |= merge(cw, t, frame.inputLocals, i);
+            }
+            if (frame.inputStack == null) {
+                frame.inputStack = new int[1];
+                changed = true;
+            }
+            changed |= merge(cw, edge, frame.inputStack, 0);
+            return changed;
+        }
+
+        int nInputStack = inputStack.length + owner.inputStackTop;
+        if (frame.inputStack == null) {
+            frame.inputStack = new int[nInputStack + outputStackTop];
+            changed = true;
+        }
+
+        for (i = 0; i < nInputStack; ++i) {
+            t = inputStack[i];
+            if (initializations != null) {
+                t = init(cw, t);
+            }
+            changed |= merge(cw, t, frame.inputStack, i);
+        }
+        for (i = 0; i < outputStackTop; ++i) {
+            s = outputStack[i];
+            dim = s & DIM;
+            kind = s & KIND;
+            if (kind == BASE) {
+                t = s;
+            } else {
+                if (kind == LOCAL) {
+                    t = dim + inputLocals[s & VALUE];
+                } else {
+                    t = dim + inputStack[nStack - (s & VALUE)];
+                }
+                if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 && (t == LONG || t == DOUBLE)) {
+                    t = TOP;
+                }
+            }
+            if (initializations != null) {
+                t = init(cw, t);
+            }
+            changed |= merge(cw, t, frame.inputStack, nInputStack + i);
+        }
+        return changed;
+    }
+
+    /**
+     * Merges the type at the given index in the given type array with the given
+     * type. Returns <tt>true</tt> if the type array has been modified by this
+     * operation.
+     *
+     * @param cw the ClassWriter to which this label belongs.
+     * @param t the type with which the type array element must be merged.
+     * @param types an array of types.
+     * @param index the index of the type that must be merged in 'types'.
+     * @return <tt>true</tt> if the type array has been modified by this
+     *         operation.
+     */
+    private static boolean merge(
+        final ClassWriter cw,
+        int t,
+        final int[] types,
+        final int index)
+    {
+        int u = types[index];
+        if (u == t) {
+            // if the types are equal, merge(u,t)=u, so there is no change
+            return false;
+        }
+        if ((t & ~DIM) == NULL) {
+            if (u == NULL) {
+                return false;
+            }
+            t = NULL;
+        }
+        if (u == 0) {
+            // if types[index] has never been assigned, merge(u,t)=t
+            types[index] = t;
+            return true;
+        }
+        int v;
+        if ((u & BASE_KIND) == OBJECT || (u & DIM) != 0) {
+            // if u is a reference type of any dimension
+            if (t == NULL) {
+                // if t is the NULL type, merge(u,t)=u, so there is no change
+                return false;
+            } else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) {
+                if ((u & BASE_KIND) == OBJECT) {
+                    // if t is also a reference type, and if u and t have the
+                    // same dimension merge(u,t) = dim(t) | common parent of the
+                    // element types of u and t
+                    v = (t & DIM) | OBJECT
+                            | cw.getMergedType(t & BASE_VALUE, u & BASE_VALUE);
+                } else {
+                    // if u and t are array types, but not with the same element
+                    // type, merge(u,t)=java/lang/Object
+                    v = OBJECT | cw.addType("java/lang/Object");
+                }
+            } else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) {
+                // if t is any other reference or array type,
+                // merge(u,t)=java/lang/Object
+                v = OBJECT | cw.addType("java/lang/Object");
+            } else {
+                // if t is any other type, merge(u,t)=TOP
+                v = TOP;
+            }
+        } else if (u == NULL) {
+            // if u is the NULL type, merge(u,t)=t,
+            // or TOP if t is not a reference type
+            v = (t & BASE_KIND) == OBJECT || (t & DIM) != 0 ? t : TOP;
+        } else {
+            // if u is any other type, merge(u,t)=TOP whatever t
+            v = TOP;
+        }
+        if (u != v) {
+            types[index] = v;
+            return true;
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/Handle.java	Sat Oct 20 22:49:26 2012 +0100
@@ -0,0 +1,188 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * 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 jdk.internal.org.objectweb.asm;
+
+/**
+ * A reference to a field or a method.
+ *
+ * @author Remi Forax
+ * @author Eric Bruneton
+ */
+public final class Handle {
+
+    /**
+     * The kind of field or method designated by this Handle. Should be
+     * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
+     * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
+     * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
+     * {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or
+     * {@link Opcodes#H_INVOKEINTERFACE}.
+     */
+    final int tag;
+
+    /**
+     * The internal name of the field or method designed by this handle.
+     */
+    final String owner;
+
+    /**
+     * The name of the field or method designated by this handle.
+     */
+    final String name;
+
+    /**
+     * The descriptor of the field or method designated by this handle.
+     */
+    final String desc;
+
+    /**
+     * Constructs a new field or method handle.
+     *
+     * @param tag the kind of field or method designated by this Handle. Must be
+     *        {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
+     *        {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
+     *        {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
+     *        {@link Opcodes#H_INVOKESPECIAL},
+     *        {@link Opcodes#H_NEWINVOKESPECIAL} or
+     *        {@link Opcodes#H_INVOKEINTERFACE}.
+     * @param owner the internal name of the field or method designed by this
+     *        handle.
+     * @param name the name of the field or method designated by this handle.
+     * @param desc the descriptor of the field or method designated by this
+     *        handle.
+     */
+    public Handle(int tag, String owner, String name, String desc) {
+        this.tag = tag;
+        this.owner = owner;
+        this.name = name;
+        this.desc = desc;
+    }
+
+    /**
+     * Returns the kind of field or method designated by this handle.
+     *
+     * @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
+     *         {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
+     *         {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
+     *         {@link Opcodes#H_INVOKESPECIAL},
+     *         {@link Opcodes#H_NEWINVOKESPECIAL} or
+     *         {@link Opcodes#H_INVOKEINTERFACE}.
+     */
+    public int getTag() {
+        return tag;
+    }
+
+    /**
+     * Returns the internal name of the field or method designed by this
+     * handle.
+     *
+     * @return the internal name of the field or method designed by this
+     *         handle.
+     */
+    public String getOwner() {
+        return owner;
+    }
+
+    /**
+     * Returns the name of the field or method designated by this handle.
+     *
+     * @return the name of the field or method designated by this handle.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns the descriptor of the field or method designated by this handle.
+     *
+     * @return the descriptor of the field or method designated by this handle.
+     */
+    public String getDesc() {
+        return desc;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (!(obj instanceof Handle)) {
+            return false;
+        }
+        Handle h = (Handle) obj;
+        return tag == h.tag && owner.equals(h.owner)
+                && name.equals(h.name) && desc.equals(h.desc);
+    }
+
+    @Override
+    public int hashCode() {
+        return tag + owner.hashCode() * name.hashCode() * desc.hashCode();
+    }
+
+    /**
+     * Returns the textual representation of this handle. The textual
+     * representation is: <pre>owner '.' name desc ' ' '(' tag ')'</pre>. As
+     * this format is unambiguous, it can be parsed if necessary.
+     */
+    @Override
+    public String toString() {
+        return owner + '.' + name + desc + " (" + tag + ')';
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/Handler.java	Sat Oct 20 22:49:26 2012 +0100
@@ -0,0 +1,147 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * 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 jdk.internal.org.objectweb.asm;
+
+/**
+ * Information about an exception handler block.
+ *
+ * @author Eric Bruneton
+ */
+class Handler {
+
+    /**
+     * Beginning of the exception handler's scope (inclusive).
+     */
+    Label start;
+
+    /**
+     * End of the exception handler's scope (exclusive).
+     */
+    Label end;
+
+    /**
+     * Beginning of the exception handler's code.
+     */
+    Label handler;
+
+    /**
+     * Internal name of the type of exceptions handled by this handler, or
+     * <tt>null</tt> to catch any exceptions.
+     */
+    String desc;
+
+    /**
+     * Constant pool index of the internal name of the type of exceptions
+     * handled by this handler, or 0 to catch any exceptions.
+     */
+    int type;
+
+    /**
+     * Next exception handler block info.
+     */
+    Handler next;
+
+    /**
+     * Removes the range between start and end from the given exception
+     * handlers.
+     *
+     * @param h an exception handler list.
+     * @param start the start of the range to be removed.
+     * @param end the end of the range to be removed. Maybe null.
+     * @return the exception handler list with the start-end range removed.
+     */
+    static Handler remove(Handler h, Label start, Label end) {
+        if (h == null) {
+            return null;
+        } else {
+            h.next = remove(h.next, start, end);
+        }
+        int hstart = h.start.position;
+        int hend = h.end.position;
+        int s = start.position;
+        int e = end == null ? Integer.MAX_VALUE : end.position;
+        // if [hstart,hend[ and [s,e[ intervals intersect...
+        if (s < hend && e > hstart) {
+            if (s <= hstart) {
+                if (e >= hend) {
+                    // [hstart,hend[ fully included in [s,e[, h removed
+                    h = h.next;
+                } else {
+                    // [hstart,hend[ minus [s,e[ = [e,hend[
+                    h.start = end;
+                }
+            } else if (e >= hend) {
+                // [hstart,hend[ minus [s,e[ = [hstart,s[
+                h.end = start;
+            } else {
+                // [hstart,hend[ minus [s,e[ = [hstart,s[ + [e,hend[
+                Handler g = new Handler();
+                g.start = end;
+                g.end = h.end;
+                g.handler = h.handler;
+                g.desc = h.desc;
+                g.type = h.type;
+                g.next = h.next;
+                h.end = start;
+                h.next = g;
+            }
+        }
+        return h;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/Item.java	Sat Oct 20 22:49:26 2012 +0100
@@ -0,0 +1,326 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * 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 jdk.internal.org.objectweb.asm;
+
+/**
+ * A constant pool item. Constant pool items can be created with the 'newXXX'
+ * methods in the {@link ClassWriter} class.
+ *
+ * @author Eric Bruneton
+ */
+final class Item {
+
+    /**
+     * Index of this item in the constant pool.
+     */
+    int index;
+
+    /**
+     * Type of this constant pool item. A single class is used to represent all
+     * constant pool item types, in order to minimize the bytecode size of this
+     * package. The value of this field is one of {@link ClassWriter#INT},
+     * {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT},
+     * {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8},
+     * {@link ClassWriter#STR}, {@link ClassWriter#CLASS},
+     * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
+     * {@link ClassWriter#METH}, {@link ClassWriter#IMETH},
+     * {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
+     *
+     * MethodHandle constant 9 variations are stored using a range
+     * of 9 values from {@link ClassWriter#HANDLE_BASE} + 1 to
+     * {@link ClassWriter#HANDLE_BASE} + 9.
+     *
+     * Special Item types are used for Items that are stored in the ClassWriter
+     * {@link ClassWriter#typeTable}, instead of the constant pool, in order to
+     * avoid clashes with normal constant pool items in the ClassWriter constant
+     * pool's hash table. These special item types are
+     * {@link ClassWriter#TYPE_NORMAL}, {@link ClassWriter#TYPE_UNINIT} and
+     * {@link ClassWriter#TYPE_MERGED}.
+     */
+    int type;
+
+    /**
+     * Value of this item, for an integer item.
+     */
+    int intVal;
+
+    /**
+     * Value of this item, for a long item.
+     */
+    long longVal;
+
+    /**
+     * First part of the value of this item, for items that do not hold a
+     * primitive value.
+     */
+    String strVal1;
+
+    /**
+     * Second part of the value of this item, for items that do not hold a
+     * primitive value.
+     */
+    String strVal2;
+
+    /**
+     * Third part of the value of this item, for items that do not hold a
+     * primitive value.
+     */
+    String strVal3;
+
+    /**
+     * The hash code value of this constant pool item.
+     */
+    int hashCode;
+
+    /**
+     * Link to another constant pool item, used for collision lists in the
+     * constant pool's hash table.
+     */
+    Item next;
+
+    /**
+     * Constructs an uninitialized {@link Item}.
+     */
+    Item() {
+    }
+
+    /**
+     * Constructs an uninitialized {@link Item} for constant pool element at
+     * given position.
+     *
+     * @param index index of the item to be constructed.
+     */
+    Item(final int index) {
+        this.index = index;
+    }
+
+    /**
+     * Constructs a copy of the given item.
+     *
+     * @param index index of the item to be constructed.
+     * @param i the item that must be copied into the item to be constructed.
+     */
+    Item(final int index, final Item i) {
+        this.index = index;
+        type = i.type;
+        intVal = i.intVal;
+        longVal = i.longVal;
+        strVal1 = i.strVal1;
+        strVal2 = i.strVal2;
+        strVal3 = i.strVal3;
+        hashCode = i.hashCode;
+    }
+
+    /**
+     * Sets this item to an integer item.
+     *
+     * @param intVal the value of this item.
+     */
+    void set(final int intVal) {
+        this.type = ClassWriter.INT;
+        this.intVal = intVal;
+        this.hashCode = 0x7FFFFFFF & (type + intVal);
+    }
+
+    /**
+     * Sets this item to a long item.
+     *
+     * @param longVal the value of this item.
+     */
+    void set(final long longVal) {
+        this.type = ClassWriter.LONG;
+        this.longVal = longVal;
+        this.hashCode = 0x7FFFFFFF & (type + (int) longVal);
+    }
+
+    /**
+     * Sets this item to a float item.
+     *
+     * @param floatVal the value of this item.
+     */
+    void set(final float floatVal) {
+        this.type = ClassWriter.FLOAT;
+        this.intVal = Float.floatToRawIntBits(floatVal);
+        this.hashCode = 0x7FFFFFFF & (type + (int) floatVal);
+    }
+
+    /**
+     * Sets this item to a double item.
+     *
+     * @param doubleVal the value of this item.
+     */
+    void set(final double doubleVal) {
+        this.type = ClassWriter.DOUBLE;
+        this.longVal = Double.doubleToRawLongBits(doubleVal);
+        this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal);
+    }
+
+    /**
+     * Sets this item to an item that do not hold a primitive value.
+     *
+     * @param type the type of this item.
+     * @param strVal1 first part of the value of this item.
+     * @param strVal2 second part of the value of this item.
+     * @param strVal3 third part of the value of this item.
+     */
+    void set(
+        final int type,
+        final String strVal1,
+        final String strVal2,
+        final String strVal3)
+    {
+        this.type = type;
+        this.strVal1 = strVal1;
+        this.strVal2 = strVal2;
+        this.strVal3 = strVal3;
+        switch (type) {
+            case ClassWriter.UTF8:
+            case ClassWriter.STR:
+            case ClassWriter.CLASS:
+            case ClassWriter.MTYPE:
+            case ClassWriter.TYPE_NORMAL:
+                hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
+                return;
+            case ClassWriter.NAME_TYPE:
+                hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+                        * strVal2.hashCode());
+                return;
+                // ClassWriter.FIELD:
+                // ClassWriter.METH:
+                // ClassWriter.IMETH:
+                // ClassWriter.HANDLE_BASE + 1..9
+            default:
+                hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+                        * strVal2.hashCode() * strVal3.hashCode());
+        }
+    }
+
+    /**
+     * Sets the item to an InvokeDynamic item.
+     *
+     * @param name invokedynamic's name.
+     * @param desc invokedynamic's desc.
+     * @param bsmIndex zero based index into the class attribute BootrapMethods.
+     */
+    void set(String name, String desc, int bsmIndex) {
+        this.type = ClassWriter.INDY;
+        this.longVal = bsmIndex;
+        this.strVal1 = name;
+        this.strVal2 = desc;
+        this.hashCode = 0x7FFFFFFF & (ClassWriter.INDY + bsmIndex
+                * strVal1.hashCode() * strVal2.hashCode());
+    }
+
+    /**
+     * Sets the item to a BootstrapMethod item.
+     *
+     * @param position position in byte in the class attribute BootrapMethods.
+     * @param hashCode hashcode of the item. This hashcode is processed from
+     *        the hashcode of the bootstrap method and the hashcode of
+     *        all bootstrap arguments.
+     */
+    void set(int position, int hashCode) {
+        this.type = ClassWriter.BSM;
+        this.intVal = position;
+        this.hashCode = hashCode;
+    }
+
+    /**
+     * Indicates if the given item is equal to this one. <i>This method assumes
+     * that the two items have the same {@link #type}</i>.
+     *
+     * @param i the item to be compared to this one. Both items must have the
+     *       same {@link #type}.
+     * @return <tt>true</tt> if the given item if equal to this one,
+     *         <tt>false</tt> otherwise.
+     */
+    boolean isEqualTo(final Item i) {
+        switch (type) {
+            case ClassWriter.UTF8:
+            case ClassWriter.STR:
+            case ClassWriter.CLASS:
+            case ClassWriter.MTYPE:
+            case ClassWriter.TYPE_NORMAL:
+                return i.strVal1.equals(strVal1);
+            case ClassWriter.TYPE_MERGED:
+            case ClassWriter.LONG:
+            case ClassWriter.DOUBLE:
+                return i.longVal == longVal;
+            case ClassWriter.INT:
+            case ClassWriter.FLOAT:
+                return i.intVal == intVal;
+            case ClassWriter.TYPE_UNINIT:
+                return i.intVal == intVal && i.strVal1.equals(strVal1);
+            case ClassWriter.NAME_TYPE:
+                return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
+            case ClassWriter.INDY:
+                return i.longVal == longVal && i.strVal1.equals(strVal1)
+                        && i.strVal2.equals(strVal2);
+
+            // case ClassWriter.FIELD:
+            // case ClassWriter.METH:
+            // case ClassWriter.IMETH:
+            // case ClassWriter.HANDLE_BASE + 1..9
+            default:
+                return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2)
+                        && i.strVal3.equals(strVal3);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/Label.java	Sat Oct 20 22:49:26 2012 +0100
@@ -0,0 +1,584 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * 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 jdk.internal.org.objectweb.asm;
+
+/**
+ * A label represents a position in the bytecode of a method. Labels are used
+ * for jump, goto, and switch instructions, and for try catch blocks. A label
+ * designates the <i>instruction</i> that is just after. Note however that
+ * there can be other elements between a label and the instruction it
+ * designates (such as other labels, stack map frames, line numbers, etc.).
+ *
+ * @author Eric Bruneton
+ */
+public class Label {
+
+    /**
+     * Indicates if this label is only used for debug attributes. Such a label
+     * is not the start of a basic block, the target of a jump instruction, or
+     * an exception handler. It can be safely ignored in control flow graph
+     * analysis algorithms (for optimization purposes).
+     */
+    static final int DEBUG = 1;
+
+    /**
+     * Indicates if the position of this label is known.
+     */
+    static final int RESOLVED = 2;
+
+    /**
+     * Indicates if this label has been updated, after instruction resizing.
+     */
+    static final int RESIZED = 4;
+
+    /**
+     * Indicates if this basic block has been pushed in the basic block stack.
+     * See {@link MethodWriter#visitMaxs visitMaxs}.
+     */
+    static final int PUSHED = 8;
+
+    /**
+     * Indicates if this label is the target of a jump instruction, or the start
+     * of an exception handler.
+     */
+    static final int TARGET = 16;
+
+    /**
+     * Indicates if a stack map frame must be stored for this label.
+     */
+    static final int STORE = 32;
+
+    /**
+     * Indicates if this label corresponds to a reachable basic block.
+     */
+    static final int REACHABLE = 64;
+
+    /**
+     * Indicates if this basic block ends with a JSR instruction.
+     */
+    static final int JSR = 128;
+
+    /**
+     * Indicates if this basic block ends with a RET instruction.
+     */
+    static final int RET = 256;
+
+    /**
+     * Indicates if this basic block is the start of a subroutine.
+     */
+    static final int SUBROUTINE = 512;
+
+    /**
+     * Indicates if this subroutine basic block has been visited by a
+     * visitSubroutine(null, ...) call.
+     */
+    static final int VISITED = 1024;
+
+    /**
+     * Indicates if this subroutine basic block has been visited by a
+     * visitSubroutine(!null, ...) call.
+     */
+    static final int VISITED2 = 2048;
+
+    /**
+     * Field used to associate user information to a label. Warning: this field
+     * is used by the ASM tree package. In order to use it with the ASM tree
+     * package you must override the {@link
+     * jdk.internal.org.objectweb.asm.tree.MethodNode#getLabelNode} method.
+     */
+    public Object info;
+
+    /**
+     * Flags that indicate the status of this label.
+     *
+     * @see #DEBUG
+     * @see #RESOLVED
+     * @see #RESIZED
+     * @see #PUSHED
+     * @see #TARGET
+     * @see #STORE
+     * @see #REACHABLE
+     * @see #JSR
+     * @see #RET
+     */
+    int status;
+
+    /**
+     * The line number corresponding to this label, if known.
+     */
+    int line;
+
+    /**
+     * The position of this label in the code, if known.
+     */
+    int position;
+
+    /**
+     * Number of forward references to this label, times two.
+     */
+    private int referenceCount;
+
+    /**
+     * Informations about forward references. Each forward reference is
+     * described by two consecutive integers in this array: the first one is the
+     * position of the first byte of the bytecode instruction that contains the
+     * forward reference, while the second is the position of the first byte of
+     * the forward reference itself. In fact the sign of the first integer
+     * indicates if this reference uses 2 or 4 bytes, and its absolute value
+     * gives the position of the bytecode instruction. This array is also used
+     * as a bitset to store the subroutines to which a basic block belongs. This
+     * information is needed in {@linked  MethodWriter#visitMaxs}, after all
+     * forward references have been resolved. Hence the same array can be used
+     * for both purposes without problems.
+     */
+    private int[] srcAndRefPositions;
+
+    // ------------------------------------------------------------------------
+
+    /*
+     * Fields for the control flow and data flow graph analysis algorithms (used
+     * to compute the maximum stack size or the stack map frames). A control
+     * flow graph contains one node per "basic block", and one edge per "jump"
+     * from one basic block to another. Each node (i.e., each basic block) is
+     * represented by the Label object that corresponds to the first instruction
+     * of this basic block. Each node also stores the list of its successors in
+     * the graph, as a linked list of Edge objects.
+     *
+     * The control flow analysis algorithms used to compute the maximum stack
+     * size or the stack map frames are similar and use two steps. The first
+     * step, during the visit of each instruction, builds information about the
+     * state of the local variables and the operand stack at the end of each
+     * basic block, called the "output frame", <i>relatively</i> to the frame
+     * state at the beginning of the basic block, which is called the "input
+     * frame", and which is <i>unknown</i> during this step. The second step,
+     * in {@link MethodWriter#visitMaxs}, is a fix point algorithm that
+     * computes information about the input frame of each basic block, from the
+     * input state of the first basic block (known from the method signature),
+     * and by the using the previously computed relative output frames.
+     *
+     * The algorithm used to compute the maximum stack size only computes the
+     * relative output and absolute input stack heights, while the algorithm
+     * used to compute stack map frames computes relative output frames and
+     * absolute input frames.
+     */
+
+    /**
+     * Start of the output stack relatively to the input stack. The exact
+     * semantics of this field depends on the algorithm that is used.
+     *
+     * When only the maximum stack size is computed, this field is the number of
+     * elements in the input stack.
+     *
+     * When the stack map frames are completely computed, this field is the
+     * offset of the first output stack element relatively to the top of the
+     * input stack. This offset is always negative or null. A null offset means
+     * that the output stack must be appended to the input stack. A -n offset
+     * means that the first n output stack elements must replace the top n input
+     * stack elements, and that the other elements must be appended to the input
+     * stack.
+     */
+    int inputStackTop;
+
+    /**
+     * Maximum height reached by the output stack, relatively to the top of the
+     * input stack. This maximum is always positive or null.
+     */
+    int outputStackMax;
+
+    /**
+     * Information about the input and output stack map frames of this basic
+     * block. This field is only used when {@link ClassWriter#COMPUTE_FRAMES}
+     * option is used.
+     */
+    Frame frame;
+
+    /**
+     * The successor of this label, in the order they are visited. This linked
+     * list does not include labels used for debug info only. If
+     * {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it
+     * does not contain successive labels that denote the same bytecode position
+     * (in this case only the first label appears in this list).
+     */
+    Label successor;
+
+    /**
+     * The successors of this node in the control flow graph. These successors
+     * are stored in a linked list of {@link Edge Edge} objects, linked to each
+     * other by their {@link Edge#next} field.
+     */
+    Edge successors;
+
+    /**
+     * The next basic block in the basic block stack. This stack is used in the
+     * main loop of the fix point algorithm used in the second step of the
+     * control flow analysis algorithms. It is also used in
+     * {@link #visitSubroutine} to avoid using a recursive method.
+     *
+     * @see MethodWriter#visitMaxs
+     */
+    Label next;
+
+    // ------------------------------------------------------------------------
+    // Constructor
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructs a new label.
+     */
+    public Label() {
+    }
+
+    // ------------------------------------------------------------------------
+    // Methods to compute offsets and to manage forward references
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the offset corresponding to this label. This offset is computed
+     * from the start of the method's bytecode. <i>This method is intended for
+     * {@link Attribute} sub classes, and is normally not needed by class
+     * generators or adapters.</i>
+     *
+     * @return the offset corresponding to this label.
+     * @throws IllegalStateException if this label is not resolved yet.
+     */
+    public int getOffset() {
+        if ((status & RESOLVED) == 0) {
+            throw new IllegalStateException("Label offset position has not been resolved yet");
+        }
+        return position;
+    }
+
+    /**
+     * Puts a reference to this label in the bytecode of a method. If the
+     * position of the label is known, the offset is computed and written
+     * directly. Otherwise, a null offset is written and a new forward reference
+     * is declared for this label.
+     *
+     * @param owner the code writer that calls this method.
+     * @param out the bytecode of the method.
+     * @param source the position of first byte of the bytecode instruction that
+     *        contains this label.
+     * @param wideOffset <tt>true</tt> if the reference must be stored in 4
+     *        bytes, or <tt>false</tt> if it must be stored with 2 bytes.
+     * @throws IllegalArgumentException if this label has not been created by
+     *         the given code writer.
+     */
+    void put(
+        final MethodWriter owner,
+        final ByteVector out,
+        final int source,
+        final boolean wideOffset)
+    {
+        if ((status & RESOLVED) == 0) {
+            if (wideOffset) {
+                addReference(-1 - source, out.length);
+                out.putInt(-1);
+            } else {
+                addReference(source, out.length);
+                out.putShort(-1);
+            }
+        } else {
+            if (wideOffset) {
+                out.putInt(position - source);
+            } else {
+                out.putShort(position - source);
+            }
+        }
+    }
+
+    /**
+     * Adds a forward reference to this label. This method must be called only
+     * for a true forward reference, i.e. only if this label is not resolved
+     * yet. For backward references, the offset of the reference can be, and
+     * must be, computed and stored directly.
+     *
+     * @param sourcePosition the position of the referencing instruction. This
+     *        position will be used to compute the offset of this forward
+     *        reference.
+     * @param referencePosition the position where the offset for this forward
+     *        reference must be stored.
+     */
+    private void addReference(
+        final int sourcePosition,
+        final int referencePosition)
+    {
+        if (srcAndRefPositions == null) {
+            srcAndRefPositions = new int[6];
+        }
+        if (referenceCount >= srcAndRefPositions.length) {
+            int[] a = new int[srcAndRefPositions.length + 6];
+            System.arraycopy(srcAndRefPositions,
+                    0,
+                    a,
+                    0,
+                    srcAndRefPositions.length);
+            srcAndRefPositions = a;
+        }
+        srcAndRefPositions[referenceCount++] = sourcePosition;
+        srcAndRefPositions[referenceCount++] = referencePosition;
+    }
+
+    /**
+     * Resolves all forward references to this label. This method must be called
+     * when this label is added to the bytecode of the method, i.e. when its
+     * position becomes known. This method fills in the blanks that where left
+     * in the bytecode by each forward reference previously added to this label.
+     *
+     * @param owner the code writer that calls this method.
+     * @param position the position of this label in the bytecode.
+     * @param data the bytecode of the method.
+     * @return <tt>true</tt> if a blank that was left for this label was to
+     *         small to store the offset. In such a case the corresponding jump
+     *         instruction is replaced with a pseudo instruction (using unused
+     *         opcodes) using an unsigned two bytes offset. These pseudo
+     *         instructions will need to be replaced with true instructions with
+     *         wider offsets (4 bytes instead of 2). This is done in
+     *         {@link MethodWriter#resizeInstructions}.
+     * @throws IllegalArgumentException if this label has already been resolved,
+     *         or if it has not been created by the given code writer.
+     */
+    boolean resolve(
+        final MethodWriter owner,
+        final int position,
+        final byte[] data)
+    {
+        boolean needUpdate = false;
+        this.status |= RESOLVED;
+        this.position = position;
+        int i = 0;
+        while (i < referenceCount) {
+            int source = srcAndRefPositions[i++];
+            int reference = srcAndRefPositions[i++];
+            int offset;
+            if (source >= 0) {
+                offset = position - source;
+                if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
+                    /*
+                     * changes the opcode of the jump instruction, in order to
+                     * be able to find it later (see resizeInstructions in
+                     * MethodWriter). These temporary opcodes are similar to
+                     * jump instruction opcodes, except that the 2 bytes offset
+                     * is unsigned (and can therefore represent values from 0 to
+                     * 65535, which is sufficient since the size of a method is
+                     * limited to 65535 bytes).
+                     */
+                    int opcode = data[reference - 1] & 0xFF;
+                    if (opcode <= Opcodes.JSR) {
+                        // changes IFEQ ... JSR to opcodes 202 to 217
+                        data[reference - 1] = (byte) (opcode + 49);
+                    } else {
+                        // changes IFNULL and IFNONNULL to opcodes 218 and 219
+                        data[reference - 1] = (byte) (opcode + 20);
+                    }
+                    needUpdate = true;
+                }
+                data[reference++] = (byte) (offset >>> 8);
+                data[reference] = (byte) offset;
+            } else {
+                offset = position + source + 1;
+                data[reference++] = (byte) (offset >>> 24);
+                data[reference++] = (byte) (offset >>> 16);
+                data[reference++] = (byte) (offset >>> 8);
+                data[reference] = (byte) offset;
+            }
+        }
+        return needUpdate;
+    }
+
+    /**
+     * Returns the first label of the series to which this label belongs. For an
+     * isolated label or for the first label in a series of successive labels,
+     * this method returns the label itself. For other labels it returns the
+     * first label of the series.
+     *
+     * @return the first label of the series to which this label belongs.
+     */
+    Label getFirst() {
+        return !ClassReader.FRAMES || frame == null ? this : frame.owner;
+    }
+
+    // ------------------------------------------------------------------------
+    // Methods related to subroutines
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns true is this basic block belongs to the given subroutine.
+     *
+     * @param id a subroutine id.
+     * @return true is this basic block belongs to the given subroutine.
+     */
+    boolean inSubroutine(final long id) {
+        if ((status & Label.VISITED) != 0) {
+            return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0;
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if this basic block and the given one belong to a common
+     * subroutine.
+     *
+     * @param block another basic block.
+     * @return true if this basic block and the given one belong to a common
+     *         subroutine.
+     */
+    boolean inSameSubroutine(final Label block) {
+        if ((status & VISITED) == 0 || (block.status & VISITED) == 0) {
+            return false;
+        }
+        for (int i = 0; i < srcAndRefPositions.length; ++i) {
+            if ((srcAndRefPositions[i] & block.srcAndRefPositions[i]) != 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Marks this basic block as belonging to the given subroutine.
+     *
+     * @param id a subroutine id.
+     * @param nbSubroutines the total number of subroutines in the method.
+     */
+    void addToSubroutine(final long id, final int nbSubroutines) {
+        if ((status & VISITED) == 0) {
+            status |= VISITED;
+            srcAndRefPositions = new int[(nbSubroutines - 1) / 32 + 1];
+        }
+        srcAndRefPositions[(int) (id >>> 32)] |= (int) id;
+    }
+
+    /**
+     * Finds the basic blocks that belong to a given subroutine, and marks these
+     * blocks as belonging to this subroutine. This method follows the control
+     * flow graph to find all the blocks that are reachable from the current
+     * block WITHOUT following any JSR target.
+     *
+     * @param JSR a JSR block that jumps to this subroutine. If this JSR is not
+     *        null it is added to the successor of the RET blocks found in the
+     *        subroutine.
+     * @param id the id of this subroutine.
+     * @param nbSubroutines the total number of subroutines in the method.
+     */
+    void visitSubroutine(final Label JSR, final long id, final int nbSubroutines)
+    {
+        // user managed stack of labels, to avoid using a recursive method
+        // (recursivity can lead to stack overflow with very large methods)
+        Label stack = this;
+        while (stack != null) {
+            // removes a label l from the stack
+            Label l = stack;
+            stack = l.next;
+            l.next = null;
+
+            if (JSR != null) {
+                if ((l.status & VISITED2) != 0) {
+                    continue;
+                }
+                l.status |= VISITED2;
+                // adds JSR to the successors of l, if it is a RET block
+                if ((l.status & RET) != 0) {
+                    if (!l.inSameSubroutine(JSR)) {
+                        Edge e = new Edge();
+                        e.info = l.inputStackTop;
+                        e.successor = JSR.successors.successor;
+                        e.next = l.successors;
+                        l.successors = e;
+                    }
+                }
+            } else {
+                // if the l block already belongs to subroutine 'id', continue
+                if (l.inSubroutine(id)) {
+                    continue;
+                }
+                // marks the l block as belonging to subroutine 'id'
+                l.addToSubroutine(id, nbSubroutines);
+            }
+            // pushes each successor of l on the stack, except JSR targets
+            Edge e = l.successors;
+            while (e != null) {
+                // if the l block is a JSR block, then 'l.successors.next' leads
+                // to the JSR target (see {@link #visitJumpInsn}) and must
+                // therefore not be followed
+                if ((l.status & Label.JSR) == 0 || e != l.successors.next) {
+                    // pushes e.successor on the stack if it not already added
+                    if (e.successor.next == null) {
+                        e.successor.next = stack;
+                        stack = e.successor;
+                    }
+                }
+                e = e.next;
+            }
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Overriden Object methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns a string representation of this label.
+     *
+     * @return a string representation of this label.
+     */
+    @Override
+    public String toString() {
+        return "L" + System.identityHashCode(this);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java	Sat Oct 20 22:49:26 2012 +0100
@@ -0,0 +1,617 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * 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 jdk.internal.org.objectweb.asm;
+
+/**
+ * A visitor to visit a Java method. The methods of this class must be
+ * called in the following order: [ <tt>visitAnnotationDefault</tt> ] (
+ * <tt>visitAnnotation</tt> | <tt>visitParameterAnnotation</tt> |
+ * <tt>visitAttribute</tt> )* [ <tt>visitCode</tt> ( <tt>visitFrame</tt> |
+ * <tt>visit</tt><i>X</i>Insn</tt> | <tt>visitLabel</tt> | <tt>visitTryCatchBlock</tt> |
+ * <tt>visitLocalVariable</tt> | <tt>visitLineNumber</tt> )* <tt>visitMaxs</tt> ]
+ * <tt>visitEnd</tt>. In addition, the <tt>visit</tt><i>X</i>Insn</tt>
+ * and <tt>visitLabel</tt> methods must be called in the sequential order of
+ * the bytecode instructions of the visited code, <tt>visitTryCatchBlock</tt>
+ * must be called <i>before</i> the labels passed as arguments have been
+ * visited, and the <tt>visitLocalVariable</tt> and <tt>visitLineNumber</tt>
+ * methods must be called <i>after</i> the labels passed as arguments have been
+ * visited.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class MethodVisitor {
+
+    /**
+     * The ASM API version implemented by this visitor. The value of this field
+     * must be one of {@link Opcodes#ASM4}.
+     */
+    protected final int api;
+
+    /**
+     * The method visitor to which this visitor must delegate method calls. May
+     * be null.
+     */
+    protected MethodVisitor mv;
+
+    /**
+     * Constructs a new {@link MethodVisitor}.
+     *
+     * @param api the ASM API version implemented by this visitor. Must be one
+     *        of {@link Opcodes#ASM4}.
+     */
+    public MethodVisitor(final int api) {
+        this(api, null);
+    }
+
+    /**
+     * Constructs a new {@link MethodVisitor}.
+     *
+     * @param api the ASM API version implemented by this visitor. Must be one
+     *        of {@link Opcodes#ASM4}.
+     * @param mv the method visitor to which this visitor must delegate method
+     *        calls. May be null.
+     */
+    public MethodVisitor(final int api, final MethodVisitor mv) {
+        /*if (api != Opcodes.ASM4) {
+            throw new IllegalArgumentException();
+        }*/
+        this.api = api;
+        this.mv = mv;
+    }
+
+    // -------------------------------------------------------------------------
+    // Annotations and non standard attributes
+    // -------------------------------------------------------------------------
+
+    /**
+     * Visits the default value of this annotation interface method.
+     *
+     * @return a visitor to the visit the actual default value of this
+     *         annotation interface method, or <tt>null</tt> if this visitor
+     *         is not interested in visiting this default value. The 'name'
+     *         parameters passed to the methods of this annotation visitor are
+     *         ignored. Moreover, exacly one visit method must be called on this
+     *         annotation visitor, followed by visitEnd.
+     */
+    public AnnotationVisitor visitAnnotationDefault() {
+        if (mv != null) {
+            return mv.visitAnnotationDefault();
+        }
+        return null;
+    }
+
+    /**
+     * Visits an annotation of this method.
+     *
+     * @param desc the class descriptor of the annotation class.
+     * @param visible <tt>true</tt> if the annotation is visible at runtime.
+     * @return a visitor to visit the annotation values, or <tt>null</tt> if
+     *         this visitor is not interested in visiting this annotation.
+     */
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        if (mv != null) {
+            return mv.visitAnnotation(desc, visible);
+        }
+        return null;
+    }
+
+    /**
+     * Visits an annotation of a parameter this method.
+     *
+     * @param parameter the parameter index.
+     * @param desc the class descriptor of the annotation class.
+     * @param visible <tt>true</tt> if the annotation is visible at runtime.
+     * @return a visitor to visit the annotation values, or <tt>null</tt> if
+     *         this visitor is not interested in visiting this annotation.
+     */
+    public AnnotationVisitor visitParameterAnnotation(
+        int parameter,
+        String desc,
+        boolean visible)
+    {
+        if (mv != null) {
+            return mv.visitParameterAnnotation(parameter, desc, visible);
+        }
+        return null;
+    }
+
+    /**
+     * Visits a non standard attribute of this method.
+     *
+     * @param attr an attribute.
+     */
+    public void visitAttribute(Attribute attr) {
+        if (mv != null) {
+            mv.visitAttribute(attr);
+        }
+    }
+
+    /**
+     * Starts the visit of the method's code, if any (i.e. non abstract method).
+     */
+    public void visitCode() {
+        if (mv != null) {
+            mv.visitCode();
+        }
+    }
+
+    /**
+     * Visits the current state of the local variables and operand stack
+     * elements. This method must(*) be called <i>just before</i> any
+     * instruction <b>i</b> that follows an unconditional branch instruction
+     * such as GOTO or THROW, that is the target of a jump instruction, or that
+     * starts an exception handler block. The visited types must describe the
+     * values of the local variables and of the operand stack elements <i>just
+     * before</i> <b>i</b> is executed. <br> <br> (*) this is mandatory only
+     * for classes whose version is greater than or equal to
+     * {@link Opcodes#V1_6 V1_6}. <br> <br> Packed frames are basically
+     * "deltas" from the state of the previous frame (very first frame is
+     * implicitly defined by the method's parameters and access flags): <ul>
+     * <li>{@link Opcodes#F_SAME} representing frame with exactly the same
+     * locals as the previous frame and with the empty stack.</li> <li>{@link Opcodes#F_SAME1}
+     * representing frame with exactly the same locals as the previous frame and
+     * with single value on the stack (<code>nStack</code> is 1 and
+     * <code>stack[0]</code> contains value for the type of the stack item).</li>
+     * <li>{@link Opcodes#F_APPEND} representing frame with current locals are
+     * the same as the locals in the previous frame, except that additional
+     * locals are defined (<code>nLocal</code> is 1, 2 or 3 and
+     * <code>local</code> elements contains values representing added types).</li>
+     * <li>{@link Opcodes#F_CHOP} representing frame with current locals are
+     * the same as the locals in the previous frame, except that the last 1-3
+     * locals are absent and with the empty stack (<code>nLocals</code> is 1,
+     * 2 or 3). </li> <li>{@link Opcodes#F_FULL} representing complete frame
+     * data.</li> </li> </ul>
+     *
+     * @param type the type of this stack map frame. Must be
+     *        {@link Opcodes#F_NEW} for expanded frames, or
+     *        {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
+     *        {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
+     *        {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed
+     *        frames.
+     * @param nLocal the number of local variables in the visited frame.
+     * @param local the local variable types in this frame. This array must not
+     *        be modified. Primitive types are represented by
+     *        {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
+     *        {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+     *        {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
+     *        {@link Opcodes#UNINITIALIZED_THIS} (long and double are
+     *        represented by a single element). Reference types are represented
+     *        by String objects (representing internal names), and uninitialized
+     *        types by Label objects (this label designates the NEW instruction
+     *        that created this uninitialized value).
+     * @param nStack the number of operand stack elements in the visited frame.
+     * @param stack the operand stack types in this frame. This array must not
+     *        be modified. Its content has the same format as the "local" array.
+     * @throws IllegalStateException if a frame is visited just after another
+     *        one, without any instruction between the two (unless this frame
+     *        is a Opcodes#F_SAME frame, in which case it is silently ignored).
+     */
+    public void visitFrame(
+        int type,
+        int nLocal,
+        Object[] local,
+        int nStack,
+        Object[] stack)
+    {
+        if (mv != null) {
+            mv.visitFrame(type, nLocal, local, nStack, stack);
+        }
+    }
+
+    // -------------------------------------------------------------------------
+    // Normal instructions
+    // -------------------------------------------------------------------------
+
+    /**
+     * Visits a zero operand instruction.
+     *
+     * @param opcode the opcode of the instruction to be visited. This opcode is
+     *        either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2,
+     *        ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, FCONST_0,
+     *        FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD, FALOAD,
+     *        DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE, FASTORE,
+     *        DASTORE, AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2, DUP,
+     *        DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP, IADD, LADD, FADD,
+     *        DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV,
+     *        FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL,
+     *        LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR,
+     *        I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B,
+     *        I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN,
+     *        FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW,
+     *        MONITORENTER, or MONITOREXIT.
+     */
+    public void visitInsn(int opcode) {
+        if (mv != null) {
+            mv.visitInsn(opcode);
+        }
+    }
+
+    /**
+     * Visits an instruction with a single int operand.
+     *
+     * @param opcode the opcode of the instruction to be visited. This opcode is
+     *        either BIPUSH, SIPUSH or NEWARRAY.
+     * @param operand the operand of the instruction to be visited.<br> When
+     *        opcode is BIPUSH, operand value should be between Byte.MIN_VALUE
+     *        and Byte.MAX_VALUE.<br> When opcode is SIPUSH, operand value
+     *        should be between Short.MIN_VALUE and Short.MAX_VALUE.<br> When
+     *        opcode is NEWARRAY, operand value should be one of
+     *        {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR},
+     *        {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE},
+     *        {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT},
+     *        {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.
+     */
+    public void visitIntInsn(int opcode, int operand) {
+        if (mv != null) {
+            mv.visitIntInsn(opcode, operand);
+        }
+    }
+
+    /**
+     * Visits a local variable instruction. A local variable instruction is an
+     * instruction that loads or stores the value of a local variable.
+     *
+     * @param opcode the opcode of the local variable instruction to be visited.
+     *        This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE,
+     *        LSTORE, FSTORE, DSTORE, ASTORE or RET.
+     * @param var the operand of the instruction to be visited. This operand is
+     *        the index of a local variable.
+     */
+    public void visitVarInsn(int opcode, int var) {
+        if (mv != null) {
+            mv.visitVarInsn(opcode, var);
+        }
+    }
+
+    /**
+     * Visits a type instruction. A type instruction is an instruction that
+     * takes the internal name of a class as parameter.
+     *
+     * @param opcode the opcode of the type instruction to be visited. This
+     *        opcode is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
+     * @param type the operand of the instruction to be visited. This operand
+     *        must be the internal name of an object or array class (see {@link
+     *        Type#getInternalName() getInternalName}).
+     */
+    public void visitTypeInsn(int opcode, String type) {
+        if (mv != null) {
+            mv.visitTypeInsn(opcode, type);
+        }
+    }
+
+    /**
+     * Visits a field instruction. A field instruction is an instruction that
+     * loads or stores the value of a field of an object.
+     *
+     * @param opcode the opcode of the type instruction to be visited. This
+     *        opcode is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
+     * @param owner the internal name of the field's owner class (see {@link
+     *        Type#getInternalName() getInternalName}).
+     * @param name the field's name.
+     * @param desc the field's descriptor (see {@link Type Type}).
+     */
+    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
+        if (mv != null) {
+            mv.visitFieldInsn(opcode, owner, name, desc);
+        }
+    }
+
+    /**
+     * Visits a method instruction. A method instruction is an instruction that
+     * invokes a method.
+     *
+     * @param opcode the opcode of the type instruction to be visited. This
+     *        opcode is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC
+     *        or INVOKEINTERFACE.
+     * @param owner the internal name of the method's owner class (see {@link
+     *        Type#getInternalName() getInternalName}).
+     * @param name the method's name.
+     * @param desc the method's descriptor (see {@link Type Type}).
+     */
+    public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+        if (mv != null) {
+            mv.visitMethodInsn(opcode, owner, name, desc);
+        }
+    }
+
+    /**
+     * Visits an invokedynamic instruction.
+     *
+     * @param name the method's name.
+     * @param desc the method's descriptor (see {@link Type Type}).
+     * @param bsm the bootstrap method.
+     * @param bsmArgs the bootstrap method constant arguments. Each argument
+     *        must be an {@link Integer}, {@link Float}, {@link Long},
+     *        {@link Double}, {@link String}, {@link Type} or {@link Handle}
+     *        value. This method is allowed to modify the content of the array
+     *        so a caller should expect that this array may change.
+     */
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
+        if (mv != null) {
+            mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+        }
+    }
+
+    /**
+     * Visits a jump instruction. A jump instruction is an instruction that may
+     * jump to another instruction.
+     *
+     * @param opcode the opcode of the type instruction to be visited. This
+     *        opcode is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
+     *        IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ,
+     *        IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
+     * @param label the operand of the instruction to be visited. This operand
+     *        is a label that designates the instruction to which the jump
+     *        instruction may jump.
+     */
+    public void visitJumpInsn(int opcode, Label label) {
+        if (mv != null) {
+            mv.visitJumpInsn(opcode, label);
+        }
+    }
+
+    /**
+     * Visits a label. A label designates the instruction that will be visited
+     * just after it.
+     *
+     * @param label a {@link Label Label} object.
+     */
+    public void visitLabel(Label label) {
+        if (mv != null) {
+            mv.visitLabel(label);
+        }
+    }
+
+    // -------------------------------------------------------------------------
+    // Special instructions
+    // -------------------------------------------------------------------------
+
+    /**
+     * Visits a LDC instruction. Note that new constant types may be added in
+     * future versions of the Java Virtual Machine. To easily detect new
+     * constant types, implementations of this method should check for
+     * unexpected constant types, like this:
+     * <pre>
+     * if (cst instanceof Integer) {
+     *   // ...
+     * } else if (cst instanceof Float) {
+     *   // ...
+     * } else if (cst instanceof Long) {
+     *   // ...
+     * } else if (cst instanceof Double) {
+     *   // ...
+     * } else if (cst instanceof String) {
+     *   // ...
+     * } else if (cst instanceof Type) {
+     *   int sort = ((Type) cst).getSort();
+     *   if (sort == Type.OBJECT) {
+     *     // ...
+     *   } else if (sort == Type.ARRAY) {
+     *     // ...
+     *   } else if (sort == Type.METHOD) {
+     *     // ...
+     *   } else {
+     *     // throw an exception
+     *   }
+     * } else if (cst instanceof Handle) {
+     *   // ...
+     * } else {
+     *   // throw an exception
+     * }</pre>
+     *
+     * @param cst the constant to be loaded on the stack. This parameter must be
+     *        a non null {@link Integer}, a {@link Float}, a {@link Long}, a
+     *        {@link Double}, a {@link String}, a {@link Type} of OBJECT or ARRAY
+     *        sort for <tt>.class</tt> constants, for classes whose version is
+     *        49.0, a {@link Type} of METHOD sort or a {@link Handle} for
+     *        MethodType and MethodHandle constants, for classes whose version
+     *        is 51.0.
+     */
+    public void visitLdcInsn(Object cst) {
+        if (mv != null) {
+            mv.visitLdcInsn(cst);
+        }
+    }
+
+    /**
+     * Visits an IINC instruction.
+     *
+     * @param var index of the local variable to be incremented.
+     * @param increment amount to increment the local variable by.
+     */
+    public void visitIincInsn(int var, int increment) {
+        if (mv != null) {
+            mv.visitIincInsn(var, increment);
+        }
+    }
+
+    /**
+     * Visits a TABLESWITCH instruction.
+     *
+     * @param min the minimum key value.
+     * @param max the maximum key value.
+     * @param dflt beginning of the default handler block.
+     * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
+     *        the beginning of the handler block for the <tt>min + i</tt> key.
+     */
+    public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
+        if (mv != null) {
+            mv.visitTableSwitchInsn(min, max, dflt, labels);
+        }
+    }
+
+    /**
+     * Visits a LOOKUPSWITCH instruction.
+     *
+     * @param dflt beginning of the default handler block.
+     * @param keys the values of the keys.
+     * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
+     *        the beginning of the handler block for the <tt>keys[i]</tt> key.
+     */
+    public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
+        if (mv != null) {
+            mv.visitLookupSwitchInsn(dflt, keys, labels);
+        }
+    }
+
+    /**
+     * Visits a MULTIANEWARRAY instruction.
+     *
+     * @param desc an array type descriptor (see {@link Type Type}).
+     * @param dims number of dimensions of the array to allocate.
+     */
+    public void visitMultiANewArrayInsn(String desc, int dims) {
+        if (mv != null) {
+            mv.visitMultiANewArrayInsn(desc, dims);
+        }
+    }
+
+    // -------------------------------------------------------------------------
+    // Exceptions table entries, debug information, max stack and max locals
+    // -------------------------------------------------------------------------
+
+    /**
+     * Visits a try catch block.
+     *
+     * @param start beginning of the exception handler's scope (inclusive).
+     * @param end end of the exception handler's scope (exclusive).
+     * @param handler beginning of the exception handler's code.
+     * @param type internal name of the type of exceptions handled by the
+     *        handler, or <tt>null</tt> to catch any exceptions (for "finally"
+     *        blocks).
+     * @throws IllegalArgumentException if one of the labels has already been
+     *         visited by this visitor (by the {@link #visitLabel visitLabel}
+     *         method).
+     */
+    public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
+        if (mv != null) {
+            mv.visitTryCatchBlock(start, end, handler, type);
+        }
+    }
+
+    /**
+     * Visits a local variable declaration.
+     *
+     * @param name the name of a local variable.
+     * @param desc the type descriptor of this local variable.
+     * @param signature the type signature of this local variable. May be
+     *        <tt>null</tt> if the local variable type does not use generic
+     *        types.
+     * @param start the first instruction corresponding to the scope of this
+     *        local variable (inclusive).
+     * @param end the last instruction corresponding to the scope of this local
+     *        variable (exclusive).
+     * @param index the local variable's index.
+     * @throws IllegalArgumentException if one of the labels has not already
+     *         been visited by this visitor (by the
+     *         {@link #visitLabel visitLabel} method).
+     */
+    public void visitLocalVariable(
+        String name,
+        String desc,