changeset 59290:fa409cbc32ad

Merge
author psadhukhan
date Tue, 10 Dec 2019 10:44:09 +0530
parents aa0f481d0024 b2e191f03473
children 6e16ceda3b96
files make/launcher/Launcher-jdk.pack.gmk make/lib/Lib-jdk.pack.gmk src/java.base/share/classes/com/sun/java/util/jar/pack/AdaptiveCoding.java src/java.base/share/classes/com/sun/java/util/jar/pack/Attribute.java src/java.base/share/classes/com/sun/java/util/jar/pack/BandStructure.java src/java.base/share/classes/com/sun/java/util/jar/pack/ClassReader.java src/java.base/share/classes/com/sun/java/util/jar/pack/ClassWriter.java src/java.base/share/classes/com/sun/java/util/jar/pack/Code.java src/java.base/share/classes/com/sun/java/util/jar/pack/Coding.java src/java.base/share/classes/com/sun/java/util/jar/pack/CodingChooser.java src/java.base/share/classes/com/sun/java/util/jar/pack/CodingMethod.java src/java.base/share/classes/com/sun/java/util/jar/pack/ConstantPool.java src/java.base/share/classes/com/sun/java/util/jar/pack/Constants.java src/java.base/share/classes/com/sun/java/util/jar/pack/Driver.java src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource.java src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource_ja.java src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource_zh_CN.java src/java.base/share/classes/com/sun/java/util/jar/pack/FixedList.java src/java.base/share/classes/com/sun/java/util/jar/pack/Fixups.java src/java.base/share/classes/com/sun/java/util/jar/pack/Histogram.java src/java.base/share/classes/com/sun/java/util/jar/pack/Instruction.java src/java.base/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java src/java.base/share/classes/com/sun/java/util/jar/pack/Package.java src/java.base/share/classes/com/sun/java/util/jar/pack/PackageReader.java src/java.base/share/classes/com/sun/java/util/jar/pack/PackageWriter.java src/java.base/share/classes/com/sun/java/util/jar/pack/PackerImpl.java src/java.base/share/classes/com/sun/java/util/jar/pack/PopulationCoding.java src/java.base/share/classes/com/sun/java/util/jar/pack/PropMap.java src/java.base/share/classes/com/sun/java/util/jar/pack/TLGlobals.java src/java.base/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java src/java.base/share/classes/com/sun/java/util/jar/pack/Utils.java src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties src/java.base/share/classes/com/sun/java/util/jar/pack/package-info.java src/java.base/share/classes/java/util/jar/Pack200.java src/jdk.pack/share/classes/module-info.java src/jdk.pack/share/man/pack200.1 src/jdk.pack/share/man/unpack200.1 src/jdk.pack/share/native/common-unpack/bands.cpp src/jdk.pack/share/native/common-unpack/bands.h src/jdk.pack/share/native/common-unpack/bytes.cpp src/jdk.pack/share/native/common-unpack/bytes.h src/jdk.pack/share/native/common-unpack/coding.cpp src/jdk.pack/share/native/common-unpack/coding.h src/jdk.pack/share/native/common-unpack/constants.h src/jdk.pack/share/native/common-unpack/defines.h src/jdk.pack/share/native/common-unpack/unpack.cpp src/jdk.pack/share/native/common-unpack/unpack.h src/jdk.pack/share/native/common-unpack/utils.cpp src/jdk.pack/share/native/common-unpack/utils.h src/jdk.pack/share/native/common-unpack/zip.cpp src/jdk.pack/share/native/common-unpack/zip.h src/jdk.pack/share/native/libunpack/jni.cpp src/jdk.pack/share/native/unpack200/main.cpp src/jdk.pack/windows/native/unpack200/unpack200_proto.exe.manifest test/jdk/ProblemList.txt test/jdk/java/util/jar/Pack200/SecurityTest.java test/jdk/tools/jar/DeprecateOptionN.java test/jdk/tools/pack200/AttributeTests.java test/jdk/tools/pack200/BandIntegrity.java test/jdk/tools/pack200/CommandLineTests.java test/jdk/tools/pack200/DeprecatePack200.java test/jdk/tools/pack200/InstructionTests.java test/jdk/tools/pack200/ModuleAttributes.java test/jdk/tools/pack200/MultiRelease.java test/jdk/tools/pack200/Pack200Props.java test/jdk/tools/pack200/Pack200Test.java test/jdk/tools/pack200/PackChecksum.java test/jdk/tools/pack200/PackTestZip64.java test/jdk/tools/pack200/PackTestZip64Manual.java test/jdk/tools/pack200/PackageVersionTest.java test/jdk/tools/pack200/RepackTest.java test/jdk/tools/pack200/T7007157.java test/jdk/tools/pack200/TestExceptions.java test/jdk/tools/pack200/TestNormal.java test/jdk/tools/pack200/TimeStamp.java test/jdk/tools/pack200/UnpackerMemoryTest.java test/jdk/tools/pack200/Utils.java test/jdk/tools/pack200/badattr.jar test/jdk/tools/pack200/pack200-verifier/data/README test/jdk/tools/pack200/pack200-verifier/data/golden.jar test/jdk/tools/pack200/pack200-verifier/make/build.xml test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/ClassCompare.java test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/Globals.java test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/JarFileCompare.java test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/Main.java test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/VerifyTreeSet.java test/jdk/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java test/jdk/tools/pack200/pack200-verifier/src/xmlkit/CommandLineParser.java test/jdk/tools/pack200/pack200-verifier/src/xmlkit/TokenList.java test/jdk/tools/pack200/pack200-verifier/src/xmlkit/XMLKit.java test/jdk/tools/pack200/typeannos/Lambda.java test/jdk/tools/pack200/typeannos/Readme.txt test/jdk/tools/pack200/typeannos/TargetTypes.java test/jdk/tools/pack200/typeannos/TestTypeAnnotations.java test/jdk/tools/pack200/typeannos/TypeUseTarget.java
diffstat 382 files changed, 1829 insertions(+), 51074 deletions(-) [+]
line wrap: on
line diff
--- a/make/autoconf/compare.sh.in	Mon Dec 09 14:59:33 2019 -0800
+++ b/make/autoconf/compare.sh.in	Tue Dec 10 10:44:09 2019 +0530
@@ -67,7 +67,6 @@
 export TAR="@TAR@"
 export TEE="@TEE@"
 export UNIQ="@UNIQ@"
-export UNPACK200="@FIXPATH@ @BOOT_JDK@/bin/unpack200"
 export UNARCHIVE="@UNZIP@ -q -o"
 
 export TOPDIR="@TOPDIR@"
--- a/make/common/Modules.gmk	Mon Dec 09 14:59:33 2019 -0800
+++ b/make/common/Modules.gmk	Tue Dec 10 10:44:09 2019 +0530
@@ -129,7 +129,6 @@
 JRE_TOOL_MODULES += \
     jdk.jdwp.agent \
     jdk.incubator.jpackage \
-    jdk.pack \
     jdk.scripting.nashorn.shell \
     #
 
@@ -170,7 +169,6 @@
     jdk.naming.dns \
     jdk.naming.rmi \
     jdk.net \
-    jdk.pack \
     jdk.rmic \
     jdk.scripting.nashorn \
     jdk.sctp \
--- a/make/gendata/Gendata-jdk.compiler.gmk	Mon Dec 09 14:59:33 2019 -0800
+++ b/make/gendata/Gendata-jdk.compiler.gmk	Tue Dec 10 10:44:09 2019 +0530
@@ -45,6 +45,7 @@
 CT_DATA_DESCRIPTION += $(TOPDIR)/make/data/symbols/symbols
 
 COMPILECREATESYMBOLS_ADD_EXPORTS := \
+    --add-exports java.base/jdk.internal=java.compiler.interim,jdk.compiler.interim \
     --add-exports jdk.compiler.interim/com.sun.tools.javac.api=ALL-UNNAMED \
     --add-exports jdk.compiler.interim/com.sun.tools.javac.code=ALL-UNNAMED \
     --add-exports jdk.compiler.interim/com.sun.tools.javac.util=ALL-UNNAMED \
@@ -58,6 +59,7 @@
     INCLUDES := build/tools/symbolgenerator com/sun/tools/classfile, \
     BIN := $(BUILDTOOLS_OUTPUTDIR)/create_symbols, \
     ADD_JAVAC_FLAGS := $(INTERIM_LANGTOOLS_ARGS) \
+        --patch-module java.base=$(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim \
         $(COMPILECREATESYMBOLS_ADD_EXPORTS), \
 ))
 
--- a/make/launcher/Launcher-jdk.pack.gmk	Mon Dec 09 14:59:33 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-#
-# Copyright (c) 2011, 2019, 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.
-#
-
-include LauncherCommon.gmk
-
-$(eval $(call SetupBuildLauncher, pack200, \
-    MAIN_MODULE := java.base, \
-    MAIN_CLASS := com.sun.java.util.jar.pack.Driver, \
-))
-
-################################################################################
-# The order of the object files on the link command line affects the size of the resulting
-# binary (at least on linux) which causes the size to differ between old and new build.
-
-# Tell the compiler not to export any functions unless declared so in
-# the source code. On Windows, this is the default and cannot be changed.
-# On Mac, we have always exported all symbols, probably due to oversight
-# and/or misunderstanding. To emulate this, don't hide any symbols
-# by default.
-# On AIX/xlc we need at least xlc 13.1 for the symbol hiding (see JDK-8214063)
-# Also provide an override for non-conformant libraries.
-ifeq ($(TOOLCHAIN_TYPE), gcc)
-  CXXFLAGS_JDKEXE += -fvisibility=hidden
-  LDFLAGS_JDKEXE += -Wl,--exclude-libs,ALL
-else ifeq ($(TOOLCHAIN_TYPE), clang)
-  ifeq ($(call isTargetOs, macosx), false)
-    CXXFLAGS_JDKEXE += -fvisibility=hidden
-  endif
-else ifeq ($(TOOLCHAIN_TYPE), solstudio)
-  CXXFLAGS_JDKEXE += -xldscope=hidden
-endif
-
-UNPACKEXE_SRC := $(TOPDIR)/src/jdk.pack/share/native/common-unpack \
-    $(TOPDIR)/src/jdk.pack/share/native/unpack200
-UNPACKEXE_CFLAGS := -I$(TOPDIR)/src/jdk.pack/share/native/common-unpack \
-    -I$(TOPDIR)/src/java.base/share/native/libjava \
-    -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjava
-
-ifeq ($(USE_EXTERNAL_LIBZ), true)
-  UNPACKEXE_CFLAGS += -DSYSTEM_ZLIB
-  UNPACKEXE_LIBS := -lz
-else
-  UNPACKEXE_CFLAGS += -I$(TOPDIR)/src/java.base/share/native/libzip/zlib
-  UNPACKEXE_ZIPOBJS := $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/zcrc32$(OBJ_SUFFIX) \
-      $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/deflate$(OBJ_SUFFIX) \
-      $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/trees$(OBJ_SUFFIX) \
-      $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/zadler32$(OBJ_SUFFIX) \
-      $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/compress$(OBJ_SUFFIX) \
-      $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/zutil$(OBJ_SUFFIX) \
-      $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/inflate$(OBJ_SUFFIX) \
-      $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/infback$(OBJ_SUFFIX) \
-      $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/inftrees$(OBJ_SUFFIX) \
-      $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/inffast$(OBJ_SUFFIX)
-
-endif
-
-$(eval $(call SetupJdkExecutable, BUILD_UNPACKEXE, \
-    NAME := unpack200, \
-    SRC := $(UNPACKEXE_SRC), \
-    TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
-    OPTIMIZATION := LOW, \
-    CFLAGS := $(UNPACKEXE_CFLAGS) $(CXXFLAGS_JDKEXE) -DFULL, \
-    CFLAGS_release := -DPRODUCT, \
-    CFLAGS_linux := -fPIC, \
-    CFLAGS_solaris := -KPIC, \
-    CFLAGS_macosx := -fPIC, \
-    DISABLED_WARNINGS_clang := format-nonliteral, \
-    DISABLED_WARNINGS_solstudio := wunreachable, \
-    LDFLAGS := $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \
-        $(call SET_SHARED_LIBRARY_ORIGIN), \
-    LIBS := $(UNPACKEXE_LIBS) $(LIBCXX), \
-    OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpackexe, \
-    MANIFEST := $(TOPDIR)/src/jdk.pack/windows/native/unpack200/unpack200_proto.exe.manifest, \
-    MANIFEST_VERSION := $(VERSION_NUMBER_FOUR_POSITIONS), \
-    EXTRA_OBJECT_FILES := $(UNPACKEXE_ZIPOBJS) \
-))
-
-TARGETS += $(BUILD_UNPACKEXE)
-
-################################################################################
--- a/make/lib/Lib-jdk.pack.gmk	Mon Dec 09 14:59:33 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-#
-# Copyright (c) 2011, 2018, 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.
-#
-
-include LibCommon.gmk
-
-################################################################################
-
-$(eval $(call SetupJdkLibrary, BUILD_LIBUNPACK, \
-    NAME := unpack, \
-    EXTRA_SRC := common-unpack, \
-    TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
-    OPTIMIZATION := LOW, \
-    CFLAGS := $(CXXFLAGS_JDKLIB) \
-        -DNO_ZLIB -DUNPACK_JNI -DFULL, \
-    CFLAGS_release := -DPRODUCT, \
-    EXTRA_HEADER_DIRS := $(call GetJavaHeaderDir, java.base), \
-    DISABLED_WARNINGS_gcc := implicit-fallthrough, \
-    DISABLED_WARNINGS_clang := format-nonliteral, \
-    DISABLED_WARNINGS_solstudio := wunreachable, \
-    LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \
-        $(call SET_SHARED_LIBRARY_ORIGIN), \
-    LDFLAGS_windows := -map:$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpack.map -debug, \
-    LIBS_unix := -ljvm $(LIBCXX) -ljava, \
-    LIBS_windows := jvm.lib $(WIN_JAVA_LIB), \
-))
-
-$(BUILD_LIBUNPACK): $(call FindLib, java.base, java)
-
-TARGETS += $(BUILD_LIBUNPACK)
-
-################################################################################
--- a/make/nashorn/element-list	Mon Dec 09 14:59:33 2019 -0800
+++ b/make/nashorn/element-list	Tue Dec 10 10:44:09 2019 +0530
@@ -260,7 +260,6 @@
 module:jdk.net
 jdk.net
 jdk.nio
-module:jdk.pack
 module:jdk.rmic
 module:jdk.scripting.nashorn
 jdk.nashorn.api.scripting
--- a/make/scripts/compare.sh	Mon Dec 09 14:59:33 2019 -0800
+++ b/make/scripts/compare.sh	Tue Dec 10 10:44:09 2019 +0530
@@ -529,31 +529,6 @@
         (cd $OTHER_UNZIPDIR && $JIMAGE extract $OTHER_ZIP)
     fi
 
-    # Find all archives inside and unzip them as well to compare the contents rather than
-    # the archives. pie.jar.pack.gz i app3.war is corrupt, skip it.
-    EXCEPTIONS="pie.jar.pack.gz jdk.pack"
-    for pack in $($FIND $THIS_UNZIPDIR \( -name "*.pack" -o -name "*.pack.gz" \) -a \
-                        ! -name pie.jar.pack.gz -a ! -name jdk.pack); do
-        ($UNPACK200 $pack $pack.jar)
-        # Filter out the unzipped archives from the diff below.
-        EXCEPTIONS="$EXCEPTIONS $pack $pack.jar"
-    done
-    for pack in $($FIND $OTHER_UNZIPDIR \( -name "*.pack" -o -name "*.pack.gz" \) -a \
-                        ! -name pie.jar.pack.gz -a ! -name jdk.pack); do
-        ($UNPACK200 $pack $pack.jar)
-        EXCEPTIONS="$EXCEPTIONS $pack $pack.jar"
-    done
-    for zip in $($FIND $THIS_UNZIPDIR -name "*.jar" -o -name "*.zip"); do
-        $MKDIR $zip.unzip
-        (cd $zip.unzip && $UNARCHIVE $zip)
-        EXCEPTIONS="$EXCEPTIONS $zip"
-    done
-    for zip in $($FIND $OTHER_UNZIPDIR -name "*.jar" -o -name "*.zip"); do
-        $MKDIR $zip.unzip
-        (cd $zip.unzip && $UNARCHIVE $zip)
-        EXCEPTIONS="$EXCEPTIONS $zip"
-    done
-
     CONTENTS_DIFF_FILE=$WORK_DIR/$ZIP_FILE.diff
     # On solaris, there is no -q option.
     if [ "$OPENJDK_TARGET_OS" = "solaris" ]; then
--- a/make/scripts/compare_exceptions.sh.incl	Mon Dec 09 14:59:33 2019 -0800
+++ b/make/scripts/compare_exceptions.sh.incl	Tue Dec 10 10:44:09 2019 +0530
@@ -50,9 +50,7 @@
   SORT_SYMBOLS="
       ./lib/libfontmanager.so
       ./lib/libjimage.so
-      ./lib/libunpack.so
       ./lib/server/libjvm.so
-      ./bin/unpack200
       ./hotspot/gtest/server/libjvm.so
       "
   KNOWN_DIS_DIFF="
--- a/src/hotspot/cpu/x86/assembler_x86.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/cpu/x86/assembler_x86.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -7232,7 +7232,7 @@
 }
 
 void Assembler::evpclmulqdq(XMMRegister dst, XMMRegister nds, XMMRegister src, int mask, int vector_len) {
-  assert(VM_Version::supports_vpclmulqdq(), "Requires vector carryless multiplication support");
+  assert(VM_Version::supports_avx512_vpclmulqdq(), "Requires vector carryless multiplication support");
   InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
   attributes.set_is_evex_instruction();
   int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
--- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -374,22 +374,41 @@
   __ cmpptr(rbx, 0); // rbx contains the incoming method for c2i adapters.
   __ jcc(Assembler::equal, bad_call);
 
+#ifdef _LP64
+  Register tmp1 = rscratch1;
+  Register tmp2 = rscratch2;
+#else
+  Register tmp1 = rax;
+  Register tmp2 = rcx;
+  __ push(tmp1);
+  __ push(tmp2);
+#endif // _LP64
+
   // Pointer chase to the method holder to find out if the method is concurrently unloading.
   Label method_live;
-  __ load_method_holder_cld(rscratch1, rbx);
+  __ load_method_holder_cld(tmp1, rbx);
 
-  // Is it a strong CLD?
-  __ movl(rscratch2, Address(rscratch1, ClassLoaderData::keep_alive_offset()));
-  __ cmpptr(rscratch2, 0);
+   // Is it a strong CLD?
+  __ cmpl(Address(tmp1, ClassLoaderData::keep_alive_offset()), 0);
   __ jcc(Assembler::greater, method_live);
 
-  // Is it a weak but alive CLD?
-  __ movptr(rscratch1, Address(rscratch1, ClassLoaderData::holder_offset()));
-  __ resolve_weak_handle(rscratch1, rscratch2);
-  __ cmpptr(rscratch1, 0);
+   // Is it a weak but alive CLD?
+  __ movptr(tmp1, Address(tmp1, ClassLoaderData::holder_offset()));
+  __ resolve_weak_handle(tmp1, tmp2);
+  __ cmpptr(tmp1, 0);
   __ jcc(Assembler::notEqual, method_live);
 
+#ifndef _LP64
+  __ pop(tmp2);
+  __ pop(tmp1);
+#endif
+
   __ bind(bad_call);
   __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
   __ bind(method_live);
+
+#ifndef _LP64
+  __ pop(tmp2);
+  __ pop(tmp1);
+#endif
 }
--- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -395,52 +395,6 @@
   __ block_comment("load_reference_barrier_native { ");
 }
 
-#ifdef _LP64
-void ShenandoahBarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) {
-  // Use default version
-  BarrierSetAssembler::c2i_entry_barrier(masm);
-}
-#else
-void ShenandoahBarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) {
-  BarrierSetNMethod* bs = BarrierSet::barrier_set()->barrier_set_nmethod();
-  if (bs == NULL) {
-    return;
-  }
-
-  Label bad_call;
-  __ cmpptr(rbx, 0); // rbx contains the incoming method for c2i adapters.
-  __ jcc(Assembler::equal, bad_call);
-
-  Register tmp1 = rax;
-  Register tmp2 = rcx;
-
-  __ push(tmp1);
-  __ push(tmp2);
-
-  // Pointer chase to the method holder to find out if the method is concurrently unloading.
-  Label method_live;
-  __ load_method_holder_cld(tmp1, rbx);
-
-   // Is it a strong CLD?
-  __ cmpl(Address(tmp1, ClassLoaderData::keep_alive_offset()), 0);
-  __ jcc(Assembler::greater, method_live);
-
-   // Is it a weak but alive CLD?
-  __ movptr(tmp1, Address(tmp1, ClassLoaderData::holder_offset()));
-  __ resolve_weak_handle(tmp1, tmp2);
-  __ cmpptr(tmp1, 0);
-  __ jcc(Assembler::notEqual, method_live);
-  __ pop(tmp2);
-  __ pop(tmp1);
-
-  __ bind(bad_call);
-  __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
-  __ bind(method_live);
-  __ pop(tmp2);
-  __ pop(tmp1);
-}
-#endif
-
 void ShenandoahBarrierSetAssembler::storeval_barrier(MacroAssembler* masm, Register dst, Register tmp) {
   if (ShenandoahStoreValEnqueueBarrier) {
     storeval_barrier_impl(masm, dst, tmp);
--- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp	Tue Dec 10 10:44:09 2019 +0530
@@ -86,8 +86,6 @@
                         Address dst, Register val, Register tmp1, Register tmp2);
   virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env,
                                              Register obj, Register tmp, Label& slowpath);
-  virtual void c2i_entry_barrier(MacroAssembler* masm);
-
   virtual void barrier_stubs_init();
 
 };
--- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -8945,34 +8945,6 @@
   shrl(len, 4);
   jcc(Assembler::zero, L_tail_restore);
 
-  // Fold total 512 bits of polynomial on each iteration
-  if (VM_Version::supports_vpclmulqdq()) {
-    Label Parallel_loop, L_No_Parallel;
-
-    cmpl(len, 8);
-    jccb(Assembler::less, L_No_Parallel);
-
-    movdqu(xmm0, ExternalAddress(StubRoutines::x86::crc_by128_masks_addr() + 32));
-    evmovdquq(xmm1, Address(buf, 0), Assembler::AVX_512bit);
-    movdl(xmm5, crc);
-    evpxorq(xmm1, xmm1, xmm5, Assembler::AVX_512bit);
-    addptr(buf, 64);
-    subl(len, 7);
-    evshufi64x2(xmm0, xmm0, xmm0, 0x00, Assembler::AVX_512bit); //propagate the mask from 128 bits to 512 bits
-
-    BIND(Parallel_loop);
-    fold_128bit_crc32_avx512(xmm1, xmm0, xmm5, buf, 0);
-    addptr(buf, 64);
-    subl(len, 4);
-    jcc(Assembler::greater, Parallel_loop);
-
-    vextracti64x2(xmm2, xmm1, 0x01);
-    vextracti64x2(xmm3, xmm1, 0x02);
-    vextracti64x2(xmm4, xmm1, 0x03);
-    jmp(L_fold_512b);
-
-    BIND(L_No_Parallel);
-  }
   // Fold crc into first bytes of vector
   movdqa(xmm1, Address(buf, 0));
   movdl(rax, xmm1);
--- a/src/hotspot/cpu/x86/vm_version_x86.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/cpu/x86/vm_version_x86.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -691,7 +691,7 @@
     _features &= ~CPU_AVX512BW;
     _features &= ~CPU_AVX512VL;
     _features &= ~CPU_AVX512_VPOPCNTDQ;
-    _features &= ~CPU_VPCLMULQDQ;
+    _features &= ~CPU_AVX512_VPCLMULQDQ;
     _features &= ~CPU_VAES;
   }
 
--- a/src/hotspot/cpu/x86/vm_version_x86.hpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/cpu/x86/vm_version_x86.hpp	Tue Dec 10 10:44:09 2019 +0530
@@ -245,7 +245,7 @@
                            : 1,
                       gfni : 1,
                       vaes : 1,
-                vpclmulqdq : 1,
+         avx512_vpclmulqdq : 1,
                avx512_vnni : 1,
              avx512_bitalg : 1,
                            : 1,
@@ -338,7 +338,7 @@
 #define CPU_FMA ((uint64_t)UCONST64(0x800000000))      // FMA instructions
 #define CPU_VZEROUPPER ((uint64_t)UCONST64(0x1000000000))       // Vzeroupper instruction
 #define CPU_AVX512_VPOPCNTDQ ((uint64_t)UCONST64(0x2000000000)) // Vector popcount
-#define CPU_VPCLMULQDQ ((uint64_t)UCONST64(0x4000000000)) //Vector carryless multiplication
+#define CPU_AVX512_VPCLMULQDQ ((uint64_t)UCONST64(0x4000000000)) //Vector carryless multiplication
 #define CPU_VAES ((uint64_t)UCONST64(0x8000000000))    // Vector AES instructions
 #define CPU_VNNI ((uint64_t)UCONST64(0x10000000000))   // Vector Neural Network Instructions
 
@@ -561,8 +561,8 @@
           result |= CPU_AVX512VL;
         if (_cpuid_info.sef_cpuid7_ecx.bits.avx512_vpopcntdq != 0)
           result |= CPU_AVX512_VPOPCNTDQ;
-        if (_cpuid_info.sef_cpuid7_ecx.bits.vpclmulqdq != 0)
-          result |= CPU_VPCLMULQDQ;
+        if (_cpuid_info.sef_cpuid7_ecx.bits.avx512_vpclmulqdq != 0)
+          result |= CPU_AVX512_VPCLMULQDQ;
         if (_cpuid_info.sef_cpuid7_ecx.bits.vaes != 0)
           result |= CPU_VAES;
         if (_cpuid_info.sef_cpuid7_ecx.bits.avx512_vnni != 0)
@@ -855,7 +855,7 @@
   static bool supports_fma()        { return (_features & CPU_FMA) != 0 && supports_avx(); }
   static bool supports_vzeroupper() { return (_features & CPU_VZEROUPPER) != 0; }
   static bool supports_vpopcntdq()  { return (_features & CPU_AVX512_VPOPCNTDQ) != 0; }
-  static bool supports_vpclmulqdq() { return (_features & CPU_VPCLMULQDQ) != 0; }
+  static bool supports_avx512_vpclmulqdq() { return (_features & CPU_AVX512_VPCLMULQDQ) != 0; }
   static bool supports_vaes()       { return (_features & CPU_VAES) != 0; }
   static bool supports_vnni()       { return (_features & CPU_VNNI) != 0; }
 
--- a/src/hotspot/share/classfile/javaClasses.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/classfile/javaClasses.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -2709,62 +2709,58 @@
     java_lang_StackTraceElement::set_fileName(element(), NULL);
     java_lang_StackTraceElement::set_lineNumber(element(), -1);
   } else {
-    // Fill in source file name and line number.
-    Symbol* source = Backtrace::get_source_file_name(holder, version);
-    oop source_file = java_lang_Class::source_file(java_class());
-    if (source != NULL) {
-      // Class was not redefined. We can trust its cache if set,
-      // else we have to initialize it.
-      if (source_file == NULL) {
-        source_file = StringTable::intern(source, CHECK);
-        java_lang_Class::set_source_file(java_class(), source_file);
-      }
-    } else {
-      // Class was redefined. Dump the cache if it was set.
-      if (source_file != NULL) {
-        source_file = NULL;
-        java_lang_Class::set_source_file(java_class(), source_file);
-      }
-    }
+    Symbol* source;
+    oop source_file;
+    int line_number;
+    decode_file_and_line(java_class, holder, version, method, bci, source, source_file, line_number, CHECK);
+
     java_lang_StackTraceElement::set_fileName(element(), source_file);
-
-    int line_number = Backtrace::get_line_number(method(), bci);
     java_lang_StackTraceElement::set_lineNumber(element(), line_number);
   }
 }
 
+void java_lang_StackTraceElement::decode_file_and_line(Handle java_class,
+                                                       InstanceKlass* holder,
+                                                       int version,
+                                                       const methodHandle& method,
+                                                       int bci,
+                                                       Symbol*& source,
+                                                       oop& source_file,
+                                                       int& line_number, TRAPS) {
+  // Fill in source file name and line number.
+  source = Backtrace::get_source_file_name(holder, version);
+  source_file = java_lang_Class::source_file(java_class());
+  if (source != NULL) {
+    // Class was not redefined. We can trust its cache if set,
+    // else we have to initialize it.
+    if (source_file == NULL) {
+      source_file = StringTable::intern(source, CHECK);
+      java_lang_Class::set_source_file(java_class(), source_file);
+    }
+  } else {
+    // Class was redefined. Dump the cache if it was set.
+    if (source_file != NULL) {
+      source_file = NULL;
+      java_lang_Class::set_source_file(java_class(), source_file);
+    }
+  }
+  line_number = Backtrace::get_line_number(method(), bci);
+}
+
 #if INCLUDE_JVMCI
-void java_lang_StackTraceElement::decode(Handle mirror, methodHandle method, int bci, Symbol*& methodname, Symbol*& filename, int& line_number) {
-  int method_id = method->orig_method_idnum();
-  int cpref = method->name_index();
-  decode(mirror, method_id, method->constants()->version(), bci, cpref, methodname, filename, line_number);
-}
-
-void java_lang_StackTraceElement::decode(Handle mirror, int method_id, int version, int bci, int cpref, Symbol*& methodname, Symbol*& filename, int& line_number) {
-  // Fill in class name
-  InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror()));
-  Method* method = holder->method_with_orig_idnum(method_id, version);
-
-  // The method can be NULL if the requested class version is gone
-  Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref);
-
-  // Fill in method name
-  methodname = sym;
-
-  if (!version_matches(method, version)) {
-    // If the method was redefined, accurate line number information isn't available
-    filename = NULL;
-    line_number = -1;
-  } else {
-    // Fill in source file name and line number.
-    // Use a specific ik version as a holder since the mirror might
-    // refer to a version that is now obsolete and no longer accessible
-    // via the previous versions list.
-    holder = holder->get_klass_version(version);
-    assert(holder != NULL, "sanity check");
-    filename = holder->source_file_name();
-    line_number = Backtrace::get_line_number(method, bci);
-  }
+void java_lang_StackTraceElement::decode(const methodHandle& method, int bci,
+                                         Symbol*& filename, int& line_number, TRAPS) {
+  ResourceMark rm(THREAD);
+  HandleMark hm(THREAD);
+
+  filename = NULL;
+  line_number = -1;
+
+  oop source_file;
+  int version = method->constants()->version();
+  InstanceKlass* holder = method->method_holder();
+  Handle java_class(THREAD, holder->java_mirror());
+  decode_file_and_line(java_class, holder, version, method, bci, filename, source_file, line_number, CHECK);
 }
 #endif // INCLUDE_JVMCI
 
--- a/src/hotspot/share/classfile/javaClasses.hpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/classfile/javaClasses.hpp	Tue Dec 10 10:44:09 2019 +0530
@@ -1401,6 +1401,10 @@
   static void set_lineNumber(oop element, int value);
   static void set_declaringClassObject(oop element, oop value);
 
+  static void decode_file_and_line(Handle java_mirror, InstanceKlass* holder, int version,
+                                   const methodHandle& method, int bci,
+                                   Symbol*& source, oop& source_file, int& line_number, TRAPS);
+
  public:
   // Create an instance of StackTraceElement
   static oop create(const methodHandle& method, int bci, TRAPS);
@@ -1412,8 +1416,7 @@
   static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
 
 #if INCLUDE_JVMCI
-  static void decode(Handle mirror, int method, int version, int bci, int cpref, Symbol*& methodName, Symbol*& fileName, int& lineNumber);
-  static void decode(Handle mirror, methodHandle method, int bci, Symbol*& methodName, Symbol*& fileName, int& lineNumber);
+  static void decode(const methodHandle& method, int bci, Symbol*& fileName, int& lineNumber, TRAPS);
 #endif
 
   // Debugging
--- a/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -597,12 +597,15 @@
   Node* adr = access.addr().node();
   Node* obj = access.base();
 
+  bool anonymous = (decorators & C2_UNSAFE_ACCESS) != 0;
   bool mismatched = (decorators & C2_MISMATCHED) != 0;
   bool unknown = (decorators & ON_UNKNOWN_OOP_REF) != 0;
   bool in_heap = (decorators & IN_HEAP) != 0;
+  bool in_native = (decorators & IN_NATIVE) != 0;
   bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
   bool is_unordered = (decorators & MO_UNORDERED) != 0;
-  bool need_cpu_mem_bar = !is_unordered || mismatched || !in_heap;
+  bool is_mixed = !in_heap && !in_native;
+  bool need_cpu_mem_bar = !is_unordered || mismatched || is_mixed;
 
   Node* top = Compile::current()->top();
   Node* offset = adr->is_AddP() ? adr->in(AddPNode::Offset) : top;
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -98,6 +98,7 @@
 #include "runtime/threadSMR.hpp"
 #include "runtime/vmThread.hpp"
 #include "utilities/align.hpp"
+#include "utilities/bitMap.inline.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/stack.inline.hpp"
 
@@ -2347,6 +2348,10 @@
   heap_region_iterate(&blk);
 }
 
+void G1CollectedHeap::keep_alive(oop obj) {
+  G1BarrierSet::enqueue(obj);
+}
+
 void G1CollectedHeap::heap_region_iterate(HeapRegionClosure* cl) const {
   _hrm->iterate(cl);
 }
@@ -2366,6 +2371,10 @@
   _collection_set.iterate(cl);
 }
 
+void G1CollectedHeap::collection_set_par_iterate_all(HeapRegionClosure* cl, HeapRegionClaimer* hr_claimer, uint worker_id) {
+  _collection_set.par_iterate(cl, hr_claimer, worker_id, workers()->active_workers());
+}
+
 void G1CollectedHeap::collection_set_iterate_increment_from(HeapRegionClosure *cl, HeapRegionClaimer* hr_claimer, uint worker_id) {
   _collection_set.iterate_incremental_part_from(cl, hr_claimer, worker_id, workers()->active_workers());
 }
@@ -4079,7 +4088,6 @@
   assert(!hr->is_free(), "the region should not be free");
   assert(!hr->is_empty(), "the region should not be empty");
   assert(_hrm->is_available(hr->hrm_index()), "region should be committed");
-  assert(free_list != NULL, "pre-condition");
 
   if (G1VerifyBitmaps) {
     MemRegion mr(hr->bottom(), hr->end());
@@ -4094,7 +4102,9 @@
   }
   hr->hr_clear(skip_remset, true /* clear_space */, locked /* locked */);
   _policy->remset_tracker()->update_at_free(hr);
-  free_list->add_ordered(hr);
+  if (free_list != NULL) {
+    free_list->add_ordered(hr);
+  }
 }
 
 void G1CollectedHeap::free_humongous_region(HeapRegion* hr,
@@ -4128,281 +4138,282 @@
 }
 
 class G1FreeCollectionSetTask : public AbstractGangTask {
-private:
-
-  // Closure applied to all regions in the collection set to do work that needs to
-  // be done serially in a single thread.
-  class G1SerialFreeCollectionSetClosure : public HeapRegionClosure {
-  private:
-    G1EvacuationInfo* _evacuation_info;
-    const size_t* _surviving_young_words;
-
-    // Bytes used in successfully evacuated regions before the evacuation.
-    size_t _before_used_bytes;
-    // Bytes used in unsucessfully evacuated regions before the evacuation
-    size_t _after_used_bytes;
-
-    size_t _bytes_allocated_in_old_since_last_gc;
-
-    size_t _failure_used_words;
-    size_t _failure_waste_words;
-
-    FreeRegionList _local_free_list;
+  // Helper class to keep statistics for the collection set freeing
+  class FreeCSetStats {
+    size_t _before_used_bytes;   // Usage in regions successfully evacutate
+    size_t _after_used_bytes;    // Usage in regions failing evacuation
+    size_t _bytes_allocated_in_old_since_last_gc; // Size of young regions turned into old
+    size_t _failure_used_words;  // Live size in failed regions
+    size_t _failure_waste_words; // Wasted size in failed regions
+    size_t _rs_length;           // Remembered set size
+    uint _regions_freed;         // Number of regions freed
   public:
-    G1SerialFreeCollectionSetClosure(G1EvacuationInfo* evacuation_info, const size_t* surviving_young_words) :
-      HeapRegionClosure(),
-      _evacuation_info(evacuation_info),
-      _surviving_young_words(surviving_young_words),
-      _before_used_bytes(0),
-      _after_used_bytes(0),
-      _bytes_allocated_in_old_since_last_gc(0),
-      _failure_used_words(0),
-      _failure_waste_words(0),
-      _local_free_list("Local Region List for CSet Freeing") {
+    FreeCSetStats() :
+        _before_used_bytes(0),
+        _after_used_bytes(0),
+        _bytes_allocated_in_old_since_last_gc(0),
+        _failure_used_words(0),
+        _failure_waste_words(0),
+        _rs_length(0),
+        _regions_freed(0) { }
+
+    void merge_stats(FreeCSetStats* other) {
+      assert(other != NULL, "invariant");
+      _before_used_bytes += other->_before_used_bytes;
+      _after_used_bytes += other->_after_used_bytes;
+      _bytes_allocated_in_old_since_last_gc += other->_bytes_allocated_in_old_since_last_gc;
+      _failure_used_words += other->_failure_used_words;
+      _failure_waste_words += other->_failure_waste_words;
+      _rs_length += other->_rs_length;
+      _regions_freed += other->_regions_freed;
+    }
+
+    void report(G1CollectedHeap* g1h, G1EvacuationInfo* evacuation_info) {
+      evacuation_info->set_regions_freed(_regions_freed);
+      evacuation_info->increment_collectionset_used_after(_after_used_bytes);
+
+      g1h->decrement_summary_bytes(_before_used_bytes);
+      g1h->alloc_buffer_stats(G1HeapRegionAttr::Old)->add_failure_used_and_waste(_failure_used_words, _failure_waste_words);
+
+      G1Policy *policy = g1h->policy();
+      policy->add_bytes_allocated_in_old_since_last_gc(_bytes_allocated_in_old_since_last_gc);
+      policy->record_rs_length(_rs_length);
+      policy->cset_regions_freed();
+    }
+
+    void account_failed_region(HeapRegion* r) {
+      size_t used_words = r->marked_bytes() / HeapWordSize;
+      _failure_used_words += used_words;
+      _failure_waste_words += HeapRegion::GrainWords - used_words;
+      _after_used_bytes += r->used();
+
+      // When moving a young gen region to old gen, we "allocate" that whole
+      // region there. This is in addition to any already evacuated objects.
+      // Notify the policy about that. Old gen regions do not cause an
+      // additional allocation: both the objects still in the region and the
+      // ones already moved are accounted for elsewhere.
+      if (r->is_young()) {
+        _bytes_allocated_in_old_since_last_gc += HeapRegion::GrainBytes;
+      }
+    }
+
+    void account_evacuated_region(HeapRegion* r) {
+      _before_used_bytes += r->used();
+      _regions_freed += 1;
+    }
+
+    void account_rs_length(HeapRegion* r) {
+      _rs_length += r->rem_set()->occupied();
     }
+  };
+
+  // Closure applied to all regions in the collection set.
+  class FreeCSetClosure : public HeapRegionClosure {
+    // Helper to send JFR events for regions.
+    class JFREventForRegion {
+      EventGCPhaseParallel _event;
+    public:
+      JFREventForRegion(HeapRegion* region, uint worker_id) : _event() {
+        _event.set_gcId(GCId::current());
+        _event.set_gcWorkerId(worker_id);
+        if (region->is_young()) {
+          _event.set_name(G1GCPhaseTimes::phase_name(G1GCPhaseTimes::YoungFreeCSet));
+        } else {
+          _event.set_name(G1GCPhaseTimes::phase_name(G1GCPhaseTimes::NonYoungFreeCSet));
+        }
+      }
+
+      ~JFREventForRegion() {
+        _event.commit();
+      }
+    };
+
+    // Helper to do timing for region work.
+    class TimerForRegion {
+      Tickspan& _time;
+      Ticks     _start_time;
+    public:
+      TimerForRegion(Tickspan& time) : _time(time), _start_time(Ticks::now()) { }
+      ~TimerForRegion() {
+        _time += Ticks::now() - _start_time;
+      }
+    };
+
+    // FreeCSetClosure members
+    G1CollectedHeap* _g1h;
+    const size_t*    _surviving_young_words;
+    uint             _worker_id;
+    Tickspan         _young_time;
+    Tickspan         _non_young_time;
+    FreeCSetStats*   _stats;
+
+    void assert_in_cset(HeapRegion* r) {
+      assert(r->young_index_in_cset() != 0 &&
+             (uint)r->young_index_in_cset() <= _g1h->collection_set()->young_region_length(),
+             "Young index %u is wrong for region %u of type %s with %u young regions",
+             r->young_index_in_cset(), r->hrm_index(), r->get_type_str(), _g1h->collection_set()->young_region_length());
+    }
+
+    void handle_evacuated_region(HeapRegion* r) {
+      assert(!r->is_empty(), "Region %u is an empty region in the collection set.", r->hrm_index());
+      stats()->account_evacuated_region(r);
+
+      // Free the region and and its remembered set.
+      _g1h->free_region(r, NULL, false /* skip_remset */, true /* skip_hot_card_cache */, true  /* locked */);
+    }
+
+    void handle_failed_region(HeapRegion* r) {
+      // Do some allocation statistics accounting. Regions that failed evacuation
+      // are always made old, so there is no need to update anything in the young
+      // gen statistics, but we need to update old gen statistics.
+      stats()->account_failed_region(r);
+
+      // Update the region state due to the failed evacuation.
+      r->handle_evacuation_failure();
+
+      // Add region to old set, need to hold lock.
+      MutexLocker x(OldSets_lock, Mutex::_no_safepoint_check_flag);
+      _g1h->old_set_add(r);
+    }
+
+    Tickspan& timer_for_region(HeapRegion* r) {
+      return r->is_young() ? _young_time : _non_young_time;
+    }
+
+    FreeCSetStats* stats() {
+      return _stats;
+    }
+  public:
+    FreeCSetClosure(const size_t* surviving_young_words,
+                    uint worker_id,
+                    FreeCSetStats* stats) :
+        HeapRegionClosure(),
+        _g1h(G1CollectedHeap::heap()),
+        _surviving_young_words(surviving_young_words),
+        _worker_id(worker_id),
+        _young_time(),
+        _non_young_time(),
+        _stats(stats) { }
 
     virtual bool do_heap_region(HeapRegion* r) {
-      G1CollectedHeap* g1h = G1CollectedHeap::heap();
-
-      assert(r->in_collection_set(), "Region %u should be in collection set.", r->hrm_index());
-      g1h->clear_region_attr(r);
+      assert(r->in_collection_set(), "Invariant: %u missing from CSet", r->hrm_index());
+      JFREventForRegion event(r, _worker_id);
+      TimerForRegion timer(timer_for_region(r));
+
+      _g1h->clear_region_attr(r);
+      stats()->account_rs_length(r);
 
       if (r->is_young()) {
-        assert(r->young_index_in_cset() != 0 && (uint)r->young_index_in_cset() <= g1h->collection_set()->young_region_length(),
-               "Young index %u is wrong for region %u of type %s with %u young regions",
-               r->young_index_in_cset(),
-               r->hrm_index(),
-               r->get_type_str(),
-               g1h->collection_set()->young_region_length());
-        size_t words_survived = _surviving_young_words[r->young_index_in_cset()];
-        r->record_surv_words_in_group(words_survived);
-      }
-
-      if (!r->evacuation_failed()) {
-        assert(!r->is_empty(), "Region %u is an empty region in the collection set.", r->hrm_index());
-        _before_used_bytes += r->used();
-        g1h->free_region(r,
-                         &_local_free_list,
-                         true, /* skip_remset */
-                         true, /* skip_hot_card_cache */
-                         true  /* locked */);
+        assert_in_cset(r);
+        r->record_surv_words_in_group(_surviving_young_words[r->young_index_in_cset()]);
       } else {
-        r->uninstall_surv_rate_group();
-        r->clear_young_index_in_cset();
-        r->set_evacuation_failed(false);
-        // When moving a young gen region to old gen, we "allocate" that whole region
-        // there. This is in addition to any already evacuated objects. Notify the
-        // policy about that.
-        // Old gen regions do not cause an additional allocation: both the objects
-        // still in the region and the ones already moved are accounted for elsewhere.
-        if (r->is_young()) {
-          _bytes_allocated_in_old_since_last_gc += HeapRegion::GrainBytes;
-        }
-        // The region is now considered to be old.
-        r->set_old();
-        // Do some allocation statistics accounting. Regions that failed evacuation
-        // are always made old, so there is no need to update anything in the young
-        // gen statistics, but we need to update old gen statistics.
-        size_t used_words = r->marked_bytes() / HeapWordSize;
-
-        _failure_used_words += used_words;
-        _failure_waste_words += HeapRegion::GrainWords - used_words;
-
-        g1h->old_set_add(r);
-        _after_used_bytes += r->used();
+        _g1h->hot_card_cache()->reset_card_counts(r);
       }
+
+      if (r->evacuation_failed()) {
+        handle_failed_region(r);
+      } else {
+        handle_evacuated_region(r);
+      }
+      assert(!_g1h->is_on_master_free_list(r), "sanity");
+
       return false;
     }
 
-    void complete_work() {
-      G1CollectedHeap* g1h = G1CollectedHeap::heap();
-
-      _evacuation_info->set_regions_freed(_local_free_list.length());
-      _evacuation_info->increment_collectionset_used_after(_after_used_bytes);
-
-      g1h->prepend_to_freelist(&_local_free_list);
-      g1h->decrement_summary_bytes(_before_used_bytes);
-
-      G1Policy* policy = g1h->policy();
-      policy->add_bytes_allocated_in_old_since_last_gc(_bytes_allocated_in_old_since_last_gc);
-
-      g1h->alloc_buffer_stats(G1HeapRegionAttr::Old)->add_failure_used_and_waste(_failure_used_words, _failure_waste_words);
-    }
-  };
-
-  G1CollectionSet* _collection_set;
-  G1SerialFreeCollectionSetClosure _cl;
-  const size_t* _surviving_young_words;
-
-  size_t _rs_length;
-
-  volatile jint _serial_work_claim;
-
-  struct WorkItem {
-    uint region_idx;
-    bool is_young;
-    bool evacuation_failed;
-
-    WorkItem(HeapRegion* r) {
-      region_idx = r->hrm_index();
-      is_young = r->is_young();
-      evacuation_failed = r->evacuation_failed();
+    void report_timing(Tickspan parallel_time) {
+      G1GCPhaseTimes* pt = _g1h->phase_times();
+      pt->record_time_secs(G1GCPhaseTimes::ParFreeCSet, _worker_id, parallel_time.seconds());
+      if (_young_time.value() > 0) {
+        pt->record_time_secs(G1GCPhaseTimes::YoungFreeCSet, _worker_id, _young_time.seconds());
+      }
+      if (_non_young_time.value() > 0) {
+        pt->record_time_secs(G1GCPhaseTimes::NonYoungFreeCSet, _worker_id, _non_young_time.seconds());
+      }
     }
   };
 
-  volatile size_t _parallel_work_claim;
-  size_t _num_work_items;
-  WorkItem* _work_items;
-
-  void do_serial_work() {
-    // Need to grab the lock to be allowed to modify the old region list.
-    MutexLocker x(OldSets_lock, Mutex::_no_safepoint_check_flag);
-    _collection_set->iterate(&_cl);
-  }
-
-  void do_parallel_work_for_region(uint region_idx, bool is_young, bool evacuation_failed) {
-    G1CollectedHeap* g1h = G1CollectedHeap::heap();
-
-    HeapRegion* r = g1h->region_at(region_idx);
-    assert(!g1h->is_on_master_free_list(r), "sanity");
-
-    Atomic::add(&_rs_length, r->rem_set()->occupied());
-
-    if (!is_young) {
-      g1h->hot_card_cache()->reset_card_counts(r);
-    }
-
-    if (!evacuation_failed) {
-      r->rem_set()->clear_locked();
-    }
+  // G1FreeCollectionSetTask members
+  G1CollectedHeap*  _g1h;
+  G1EvacuationInfo* _evacuation_info;
+  FreeCSetStats*    _worker_stats;
+  HeapRegionClaimer _claimer;
+  const size_t*     _surviving_young_words;
+  uint              _active_workers;
+
+  FreeCSetStats* worker_stats(uint worker) {
+    return &_worker_stats[worker];
   }
 
-  class G1PrepareFreeCollectionSetClosure : public HeapRegionClosure {
-  private:
-    size_t _cur_idx;
-    WorkItem* _work_items;
-  public:
-    G1PrepareFreeCollectionSetClosure(WorkItem* work_items) : HeapRegionClosure(), _cur_idx(0), _work_items(work_items) { }
-
-    virtual bool do_heap_region(HeapRegion* r) {
-      _work_items[_cur_idx++] = WorkItem(r);
-      return false;
+  void report_statistics() {
+    // Merge the accounting
+    FreeCSetStats total_stats;
+    for (uint worker = 0; worker < _active_workers; worker++) {
+      total_stats.merge_stats(worker_stats(worker));
     }
-  };
-
-  void prepare_work() {
-    G1PrepareFreeCollectionSetClosure cl(_work_items);
-    _collection_set->iterate(&cl);
+    total_stats.report(_g1h, _evacuation_info);
   }
 
-  void complete_work() {
-    _cl.complete_work();
-
-    G1Policy* policy = G1CollectedHeap::heap()->policy();
-    policy->record_rs_length(_rs_length);
-    policy->cset_regions_freed();
-  }
 public:
-  G1FreeCollectionSetTask(G1CollectionSet* collection_set, G1EvacuationInfo* evacuation_info, const size_t* surviving_young_words) :
-    AbstractGangTask("G1 Free Collection Set"),
-    _collection_set(collection_set),
-    _cl(evacuation_info, surviving_young_words),
-    _surviving_young_words(surviving_young_words),
-    _rs_length(0),
-    _serial_work_claim(0),
-    _parallel_work_claim(0),
-    _num_work_items(collection_set->region_length()),
-    _work_items(NEW_C_HEAP_ARRAY(WorkItem, _num_work_items, mtGC)) {
-    prepare_work();
+  G1FreeCollectionSetTask(G1EvacuationInfo* evacuation_info, const size_t* surviving_young_words, uint active_workers) :
+      AbstractGangTask("G1 Free Collection Set"),
+      _g1h(G1CollectedHeap::heap()),
+      _evacuation_info(evacuation_info),
+      _worker_stats(NEW_C_HEAP_ARRAY(FreeCSetStats, active_workers, mtGC)),
+      _claimer(active_workers),
+      _surviving_young_words(surviving_young_words),
+      _active_workers(active_workers) {
+    for (uint worker = 0; worker < active_workers; worker++) {
+      ::new (&_worker_stats[worker]) FreeCSetStats();
+    }
   }
 
   ~G1FreeCollectionSetTask() {
-    complete_work();
-    FREE_C_HEAP_ARRAY(WorkItem, _work_items);
+    Ticks serial_time = Ticks::now();
+    report_statistics();
+    for (uint worker = 0; worker < _active_workers; worker++) {
+      _worker_stats[worker].~FreeCSetStats();
+    }
+    FREE_C_HEAP_ARRAY(FreeCSetStats, _worker_stats);
+    _g1h->phase_times()->record_serial_free_cset_time_ms((Ticks::now() - serial_time).seconds() * 1000.0);
   }
 
-  // Chunk size for work distribution. The chosen value has been determined experimentally
-  // to be a good tradeoff between overhead and achievable parallelism.
-  static uint chunk_size() { return 32; }
-
   virtual void work(uint worker_id) {
-    G1GCPhaseTimes* timer = G1CollectedHeap::heap()->phase_times();
-
-    // Claim serial work.
-    if (_serial_work_claim == 0) {
-      jint value = Atomic::add(&_serial_work_claim, 1) - 1;
-      if (value == 0) {
-        double serial_time = os::elapsedTime();
-        do_serial_work();
-        timer->record_serial_free_cset_time_ms((os::elapsedTime() - serial_time) * 1000.0);
-      }
-    }
-
-    // Start parallel work.
-    double young_time = 0.0;
-    bool has_young_time = false;
-    double non_young_time = 0.0;
-    bool has_non_young_time = false;
-
-    while (true) {
-      size_t end = Atomic::add(&_parallel_work_claim, chunk_size());
-      size_t cur = end - chunk_size();
-
-      if (cur >= _num_work_items) {
-        break;
-      }
-
-      EventGCPhaseParallel event;
-      double start_time = os::elapsedTime();
-
-      end = MIN2(end, _num_work_items);
-
-      for (; cur < end; cur++) {
-        bool is_young = _work_items[cur].is_young;
-
-        do_parallel_work_for_region(_work_items[cur].region_idx, is_young, _work_items[cur].evacuation_failed);
-
-        double end_time = os::elapsedTime();
-        double time_taken = end_time - start_time;
-        if (is_young) {
-          young_time += time_taken;
-          has_young_time = true;
-          event.commit(GCId::current(), worker_id, G1GCPhaseTimes::phase_name(G1GCPhaseTimes::YoungFreeCSet));
-        } else {
-          non_young_time += time_taken;
-          has_non_young_time = true;
-          event.commit(GCId::current(), worker_id, G1GCPhaseTimes::phase_name(G1GCPhaseTimes::NonYoungFreeCSet));
-        }
-        start_time = end_time;
-      }
-    }
-
-    if (has_young_time) {
-      timer->record_time_secs(G1GCPhaseTimes::YoungFreeCSet, worker_id, young_time);
-    }
-    if (has_non_young_time) {
-      timer->record_time_secs(G1GCPhaseTimes::NonYoungFreeCSet, worker_id, non_young_time);
-    }
+    EventGCPhaseParallel event;
+    Ticks start = Ticks::now();
+    FreeCSetClosure cl(_surviving_young_words, worker_id, worker_stats(worker_id));
+    _g1h->collection_set_par_iterate_all(&cl, &_claimer, worker_id);
+
+    // Report the total parallel time along with some more detailed metrics.
+    cl.report_timing(Ticks::now() - start);
+    event.commit(GCId::current(), worker_id, G1GCPhaseTimes::phase_name(G1GCPhaseTimes::ParFreeCSet));
   }
 };
 
 void G1CollectedHeap::free_collection_set(G1CollectionSet* collection_set, G1EvacuationInfo& evacuation_info, const size_t* surviving_young_words) {
   _eden.clear();
 
-  double free_cset_start_time = os::elapsedTime();
-
+  // The free collections set is split up in two tasks, the first
+  // frees the collection set and records what regions are free,
+  // and the second one rebuilds the free list. This proved to be
+  // more efficient than adding a sorted list to another.
+
+  Ticks free_cset_start_time = Ticks::now();
   {
-    uint const num_regions = _collection_set.region_length();
-    uint const num_chunks = MAX2(num_regions / G1FreeCollectionSetTask::chunk_size(), 1U);
-    uint const num_workers = MIN2(workers()->active_workers(), num_chunks);
-
-    G1FreeCollectionSetTask cl(collection_set, &evacuation_info, surviving_young_words);
-
-    log_debug(gc, ergo)("Running %s using %u workers for collection set length %u",
-                        cl.name(), num_workers, num_regions);
+    uint const num_cs_regions = _collection_set.region_length();
+    uint const num_workers = clamp(num_cs_regions, 1u, workers()->active_workers());
+    G1FreeCollectionSetTask cl(&evacuation_info, surviving_young_words, num_workers);
+
+    log_debug(gc, ergo)("Running %s using %u workers for collection set length %u (%u)",
+                        cl.name(), num_workers, num_cs_regions, num_regions());
     workers()->run_task(&cl, num_workers);
   }
-  phase_times()->record_total_free_cset_time_ms((os::elapsedTime() - free_cset_start_time) * 1000.0);
+
+  Ticks free_cset_end_time = Ticks::now();
+  phase_times()->record_total_free_cset_time_ms((free_cset_end_time - free_cset_start_time).seconds() * 1000.0);
+
+  // Now rebuild the free region list.
+  hrm()->rebuild_free_list(workers());
+  phase_times()->record_total_rebuild_freelist_time_ms((Ticks::now() - free_cset_end_time).seconds() * 1000.0);
 
   collection_set->clear();
 }
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Tue Dec 10 10:44:09 2019 +0530
@@ -1170,6 +1170,9 @@
   // Iterate over all objects, calling "cl.do_object" on each.
   virtual void object_iterate(ObjectClosure* cl);
 
+  // Keep alive an object that was loaded with AS_NO_KEEPALIVE.
+  virtual void keep_alive(oop obj);
+
   // Iterate over heap regions, in address order, terminating the
   // iteration early if the "do_heap_region" method returns "true".
   void heap_region_iterate(HeapRegionClosure* blk) const;
@@ -1201,6 +1204,11 @@
   void heap_region_par_iterate_from_start(HeapRegionClosure* cl,
                                           HeapRegionClaimer* hrclaimer) const;
 
+  // Iterate over all regions in the collection set in parallel.
+  void collection_set_par_iterate_all(HeapRegionClosure* cl,
+                                      HeapRegionClaimer* hr_claimer,
+                                      uint worker_id);
+
   // Iterate over all regions currently in the current collection set.
   void collection_set_iterate_all(HeapRegionClosure* blk);
 
--- a/src/hotspot/share/gc/g1/g1CollectionSet.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/g1/g1CollectionSet.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -201,6 +201,13 @@
   }
 }
 
+void G1CollectionSet::par_iterate(HeapRegionClosure* cl,
+                                  HeapRegionClaimer* hr_claimer,
+                                  uint worker_id,
+                                  uint total_workers) const {
+  iterate_part_from(cl, hr_claimer, 0, cur_length(), worker_id, total_workers);
+}
+
 void G1CollectionSet::iterate_optional(HeapRegionClosure* cl) const {
   assert_at_safepoint();
 
@@ -215,18 +222,25 @@
                                                     HeapRegionClaimer* hr_claimer,
                                                     uint worker_id,
                                                     uint total_workers) const {
-  assert_at_safepoint();
+  iterate_part_from(cl, hr_claimer, _inc_part_start, increment_length(), worker_id, total_workers);
+}
 
-  size_t len = increment_length();
-  if (len == 0) {
+void G1CollectionSet::iterate_part_from(HeapRegionClosure* cl,
+                                        HeapRegionClaimer* hr_claimer,
+                                        size_t offset,
+                                        size_t length,
+                                        uint worker_id,
+                                        uint total_workers) const {
+  assert_at_safepoint();
+  if (length == 0) {
     return;
   }
 
-  size_t start_pos = (worker_id * len) / total_workers;
+  size_t start_pos = (worker_id * length) / total_workers;
   size_t cur_pos = start_pos;
 
   do {
-    uint region_idx = _collection_set_regions[cur_pos + _inc_part_start];
+    uint region_idx = _collection_set_regions[cur_pos + offset];
     if (hr_claimer == NULL || hr_claimer->claim_region(region_idx)) {
       HeapRegion* r = _g1h->region_at(region_idx);
       bool result = cl->do_heap_region(r);
@@ -234,7 +248,7 @@
     }
 
     cur_pos++;
-    if (cur_pos == len) {
+    if (cur_pos == length) {
       cur_pos = 0;
     }
   } while (cur_pos != start_pos);
--- a/src/hotspot/share/gc/g1/g1CollectionSet.hpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/g1/g1CollectionSet.hpp	Tue Dec 10 10:44:09 2019 +0530
@@ -254,6 +254,16 @@
   // Select the old regions of the initial collection set and determine how many optional
   // regions we might be able to evacuate in this pause.
   void finalize_old_part(double time_remaining_ms);
+
+  // Iterate the part of the collection set given by the offset and length applying the given
+  // HeapRegionClosure. The worker_id will determine where in the part to start the iteration
+  // to allow for more efficient parallel iteration.
+  void iterate_part_from(HeapRegionClosure* cl,
+                         HeapRegionClaimer* hr_claimer,
+                         size_t offset,
+                         size_t length,
+                         uint worker_id,
+                         uint total_workers) const;
 public:
   G1CollectionSet(G1CollectedHeap* g1h, G1Policy* policy);
   ~G1CollectionSet();
@@ -306,6 +316,10 @@
   // Iterate over the entire collection set (all increments calculated so far), applying
   // the given HeapRegionClosure on all of them.
   void iterate(HeapRegionClosure* cl) const;
+  void par_iterate(HeapRegionClosure* cl,
+                   HeapRegionClaimer* hr_claimer,
+                   uint worker_id,
+                   uint total_workers) const;
 
   void iterate_optional(HeapRegionClosure* cl) const;
 
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -131,8 +131,10 @@
   _gc_par_phases[RedirtyCards] = new WorkerDataArray<double>("Parallel Redirty (ms):", max_gc_threads);
   _gc_par_phases[RedirtyCards]->create_thread_work_items("Redirtied Cards:");
 
+  _gc_par_phases[ParFreeCSet] = new WorkerDataArray<double>("Parallel Free Collection Set (ms):", max_gc_threads);
   _gc_par_phases[YoungFreeCSet] = new WorkerDataArray<double>("Young Free Collection Set (ms):", max_gc_threads);
   _gc_par_phases[NonYoungFreeCSet] = new WorkerDataArray<double>("Non-Young Free Collection Set (ms):", max_gc_threads);
+  _gc_par_phases[RebuildFreeList] = new WorkerDataArray<double>("Parallel Rebuild Free List (ms):", max_gc_threads);
 
   reset();
 }
@@ -167,6 +169,8 @@
   _recorded_start_new_cset_time_ms = 0.0;
   _recorded_total_free_cset_time_ms = 0.0;
   _recorded_serial_free_cset_time_ms = 0.0;
+  _recorded_total_rebuild_freelist_time_ms = 0.0;
+  _recorded_serial_rebuild_freelist_time_ms = 0.0;
   _cur_fast_reclaim_humongous_time_ms = 0.0;
   _cur_region_register_time = 0.0;
   _cur_fast_reclaim_humongous_total = 0;
@@ -328,11 +332,11 @@
   }
 }
 
-void G1GCPhaseTimes::trace_phase(WorkerDataArray<double>* phase, bool print_sum) const {
+void G1GCPhaseTimes::trace_phase(WorkerDataArray<double>* phase, bool print_sum, uint extra_indent) const {
   LogTarget(Trace, gc, phases) lt;
   if (lt.is_enabled()) {
     LogStream ls(lt);
-    log_phase(phase, 3, &ls, print_sum);
+    log_phase(phase, 3 + extra_indent, &ls, print_sum);
   }
 }
 
@@ -456,6 +460,7 @@
                         _cur_strong_code_root_purge_time_ms +
                         _recorded_redirty_logged_cards_time_ms +
                         _recorded_total_free_cset_time_ms +
+                        _recorded_total_rebuild_freelist_time_ms +
                         _cur_fast_reclaim_humongous_time_ms +
                         _cur_expand_heap_time_ms +
                         _cur_string_deduplication_time_ms;
@@ -492,9 +497,14 @@
 #endif
 
   debug_time("Free Collection Set", _recorded_total_free_cset_time_ms);
-  trace_time("Free Collection Set Serial", _recorded_serial_free_cset_time_ms);
-  trace_phase(_gc_par_phases[YoungFreeCSet]);
-  trace_phase(_gc_par_phases[NonYoungFreeCSet]);
+  trace_time("Serial Free Collection Set", _recorded_serial_free_cset_time_ms);
+  trace_phase(_gc_par_phases[ParFreeCSet]);
+  trace_phase(_gc_par_phases[YoungFreeCSet], true, 1);
+  trace_phase(_gc_par_phases[NonYoungFreeCSet], true, 1);
+
+  debug_time("Rebuild Free List", _recorded_total_rebuild_freelist_time_ms);
+  trace_time("Serial Rebuild Free List ", _recorded_serial_rebuild_freelist_time_ms);
+  trace_phase(_gc_par_phases[RebuildFreeList]);
 
   if (G1EagerReclaimHumongousObjects) {
     debug_time("Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms);
@@ -566,8 +576,10 @@
       "StringDedupQueueFixup",
       "StringDedupTableFixup",
       "RedirtyCards",
+      "ParFreeCSet",
       "YoungFreeCSet",
       "NonYoungFreeCSet",
+      "RebuildFreeList",
       "MergePSS"
       //GCParPhasesSentinel only used to tell end of enum
       };
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp	Tue Dec 10 10:44:09 2019 +0530
@@ -76,8 +76,10 @@
     StringDedupQueueFixup,
     StringDedupTableFixup,
     RedirtyCards,
+    ParFreeCSet,
     YoungFreeCSet,
     NonYoungFreeCSet,
+    RebuildFreeList,
     MergePSS,
     GCParPhasesSentinel
   };
@@ -171,6 +173,10 @@
 
   double _recorded_serial_free_cset_time_ms;
 
+  double _recorded_total_rebuild_freelist_time_ms;
+
+  double _recorded_serial_rebuild_freelist_time_ms;
+
   double _cur_region_register_time;
 
   double _cur_fast_reclaim_humongous_time_ms;
@@ -195,7 +201,7 @@
   void log_phase(WorkerDataArray<double>* phase, uint indent, outputStream* out, bool print_sum) const;
   void debug_serial_phase(WorkerDataArray<double>* phase, uint extra_indent = 0) const;
   void debug_phase(WorkerDataArray<double>* phase, uint extra_indent = 0) const;
-  void trace_phase(WorkerDataArray<double>* phase, bool print_sum = true) const;
+  void trace_phase(WorkerDataArray<double>* phase, bool print_sum = true, uint extra_indent = 0) const;
 
   void info_time(const char* name, double value) const;
   void debug_time(const char* name, double value) const;
@@ -318,6 +324,14 @@
     _recorded_serial_free_cset_time_ms = time_ms;
   }
 
+  void record_total_rebuild_freelist_time_ms(double time_ms) {
+    _recorded_total_rebuild_freelist_time_ms = time_ms;
+  }
+
+  void record_serial_rebuild_freelist_time_ms(double time_ms) {
+    _recorded_serial_rebuild_freelist_time_ms = time_ms;
+  }
+
   void record_register_regions(double time_ms, size_t total, size_t candidates) {
     _cur_region_register_time = time_ms;
     _cur_fast_reclaim_humongous_total = total;
@@ -401,6 +415,10 @@
     return _recorded_total_free_cset_time_ms;
   }
 
+  double total_rebuild_freelist_time_ms() {
+    return _recorded_total_rebuild_freelist_time_ms;
+  }
+
   double non_young_cset_choice_time_ms() {
     return _recorded_non_young_cset_choice_time_ms;
   }
--- a/src/hotspot/share/gc/g1/g1Policy.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/g1/g1Policy.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -587,7 +587,7 @@
 }
 
 double G1Policy::constant_other_time_ms(double pause_time_ms) const {
-  return other_time_ms(pause_time_ms) - phase_times()->total_free_cset_time_ms();
+  return other_time_ms(pause_time_ms) - phase_times()->total_free_cset_time_ms() - phase_times()->total_rebuild_freelist_time_ms();
 }
 
 bool G1Policy::about_to_start_mixed_phase() const {
--- a/src/hotspot/share/gc/g1/heapRegion.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/g1/heapRegion.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -110,6 +110,19 @@
   }
 }
 
+void HeapRegion::handle_evacuation_failure() {
+  uninstall_surv_rate_group();
+  clear_young_index_in_cset();
+  set_evacuation_failed(false);
+  set_old();
+}
+
+void HeapRegion::unlink_from_list() {
+  set_next(NULL);
+  set_prev(NULL);
+  set_containing_set(NULL);
+}
+
 void HeapRegion::hr_clear(bool keep_remset, bool clear_space, bool locked) {
   assert(_humongous_start_region == NULL,
          "we should have already filtered out humongous regions");
--- a/src/hotspot/share/gc/g1/heapRegion.hpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/g1/heapRegion.hpp	Tue Dec 10 10:44:09 2019 +0530
@@ -464,14 +464,16 @@
   void set_prev(HeapRegion* prev) { _prev = prev; }
   HeapRegion* prev()              { return _prev; }
 
+  void unlink_from_list();
+
   // Every region added to a set is tagged with a reference to that
   // set. This is used for doing consistency checking to make sure that
   // the contents of a set are as they should be and it's only
   // available in non-product builds.
 #ifdef ASSERT
   void set_containing_set(HeapRegionSetBase* containing_set) {
-    assert((containing_set == NULL && _containing_set != NULL) ||
-           (containing_set != NULL && _containing_set == NULL),
+    assert((containing_set != NULL && _containing_set == NULL) ||
+            containing_set == NULL,
            "containing_set: " PTR_FORMAT " "
            "_containing_set: " PTR_FORMAT,
            p2i(containing_set), p2i(_containing_set));
@@ -559,6 +561,9 @@
     return (HeapWord *) obj >= next_top_at_mark_start();
   }
 
+  // Update the region state after a failed evacuation.
+  void handle_evacuation_failure();
+
   // Iterate over the objects overlapping the given memory region, applying cl
   // to all references in the region.  This is a helper for
   // G1RemSet::refine_card*, and is tightly coupled with them.
--- a/src/hotspot/share/gc/g1/heapRegionManager.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/g1/heapRegionManager.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -614,3 +614,80 @@
   uint old_val = Atomic::cmpxchg(&_claims[region_index], Unclaimed, Claimed);
   return old_val == Unclaimed;
 }
+
+class G1RebuildFreeListTask : public AbstractGangTask {
+  HeapRegionManager* _hrm;
+  FreeRegionList*    _worker_freelists;
+  uint               _worker_chunk_size;
+  uint               _num_workers;
+
+public:
+  G1RebuildFreeListTask(HeapRegionManager* hrm, uint num_workers) :
+      AbstractGangTask("G1 Rebuild Free List Task"),
+      _hrm(hrm),
+      _worker_freelists(NEW_C_HEAP_ARRAY(FreeRegionList, num_workers, mtGC)),
+      _worker_chunk_size((_hrm->max_length() + num_workers - 1) / num_workers),
+      _num_workers(num_workers) {
+    for (uint worker = 0; worker < _num_workers; worker++) {
+      ::new (&_worker_freelists[worker]) FreeRegionList("Appendable Worker Free List");
+    }
+  }
+
+  ~G1RebuildFreeListTask() {
+    for (uint worker = 0; worker < _num_workers; worker++) {
+      _worker_freelists[worker].~FreeRegionList();
+    }
+    FREE_C_HEAP_ARRAY(FreeRegionList, _worker_freelists);
+  }
+
+  FreeRegionList* worker_freelist(uint worker) {
+    return &_worker_freelists[worker];
+  }
+
+  // Each worker creates a free list for a chunk of the heap. The chunks won't
+  // be overlapping so we don't need to do any claiming.
+  void work(uint worker_id) {
+    Ticks start_time = Ticks::now();
+    EventGCPhaseParallel event;
+
+    uint start = worker_id * _worker_chunk_size;
+    uint end = MIN2(start + _worker_chunk_size, _hrm->max_length());
+
+    // If start is outside the heap, this worker has nothing to do.
+    if (start > end) {
+      return;
+    }
+
+    FreeRegionList *free_list = worker_freelist(worker_id);
+    for (uint i = start; i < end; i++) {
+      HeapRegion *region = _hrm->at_or_null(i);
+      if (region != NULL && region->is_free()) {
+        // Need to clear old links to allow to be added to new freelist.
+        region->unlink_from_list();
+        free_list->add_to_tail(region);
+      }
+    }
+
+    event.commit(GCId::current(), worker_id, G1GCPhaseTimes::phase_name(G1GCPhaseTimes::RebuildFreeList));
+    G1CollectedHeap::heap()->phase_times()->record_time_secs(G1GCPhaseTimes::RebuildFreeList, worker_id, (Ticks::now() - start_time).seconds());
+  }
+};
+
+void HeapRegionManager::rebuild_free_list(WorkGang* workers) {
+  // Abandon current free list to allow a rebuild.
+  _free_list.abandon();
+
+  uint const num_workers = clamp(max_length(), 1u, workers->active_workers());
+  G1RebuildFreeListTask task(this, num_workers);
+
+  log_debug(gc, ergo)("Running %s using %u workers for rebuilding free list of %u (%u) regions",
+                      task.name(), num_workers, num_free_regions(), max_length());
+  workers->run_task(&task, num_workers);
+
+  // Link the partial free lists together.
+  Ticks serial_time = Ticks::now();
+  for (uint worker = 0; worker < num_workers; worker++) {
+    _free_list.append_ordered(task.worker_freelist(worker));
+  }
+  G1CollectedHeap::heap()->phase_times()->record_serial_rebuild_freelist_time_ms((Ticks::now() - serial_time).seconds() * 1000.0);
+}
--- a/src/hotspot/share/gc/g1/heapRegionManager.hpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/g1/heapRegionManager.hpp	Tue Dec 10 10:44:09 2019 +0530
@@ -172,6 +172,9 @@
   // Insert the given region into the free region list.
   inline void insert_into_free_list(HeapRegion* hr);
 
+  // Rebuild the free region list from scratch.
+  void rebuild_free_list(WorkGang* workers);
+
   // Insert the given region list into the global free region list.
   void insert_list_into_free_list(FreeRegionList* list) {
     _free_list.add_ordered(list);
--- a/src/hotspot/share/gc/g1/heapRegionSet.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/g1/heapRegionSet.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -90,6 +90,12 @@
   _unrealistically_long_length = len;
 }
 
+void FreeRegionList::abandon() {
+  check_mt_safety();
+  clear();
+  verify_optional();
+}
+
 void FreeRegionList::remove_all() {
   check_mt_safety();
   verify_optional();
@@ -112,10 +118,9 @@
   verify_optional();
 }
 
-void FreeRegionList::add_ordered(FreeRegionList* from_list) {
+void FreeRegionList::add_list_common_start(FreeRegionList* from_list) {
   check_mt_safety();
   from_list->check_mt_safety();
-
   verify_optional();
   from_list->verify_optional();
 
@@ -138,6 +143,47 @@
     hr->set_containing_set(this);
   }
   #endif // ASSERT
+}
+
+void FreeRegionList::add_list_common_end(FreeRegionList* from_list) {
+  _length += from_list->length();
+  from_list->clear();
+
+  verify_optional();
+  from_list->verify_optional();
+}
+
+void FreeRegionList::append_ordered(FreeRegionList* from_list) {
+  add_list_common_start(from_list);
+
+  if (from_list->is_empty()) {
+    return;
+  }
+
+  if (is_empty()) {
+    // Make from_list the current list.
+    assert_free_region_list(length() == 0 && _tail == NULL, "invariant");
+    _head = from_list->_head;
+    _tail = from_list->_tail;
+  } else {
+    // Add the from_list to the end of the current list.
+    assert(_tail->hrm_index() < from_list->_head->hrm_index(), "Should be sorted %u < %u",
+           _tail->hrm_index(), from_list->_head->hrm_index());
+
+    _tail->set_next(from_list->_head);
+    from_list->_head->set_prev(_tail);
+    _tail = from_list->_tail;
+  }
+
+  add_list_common_end(from_list);
+}
+
+void FreeRegionList::add_ordered(FreeRegionList* from_list) {
+  add_list_common_start(from_list);
+
+  if (from_list->is_empty()) {
+    return;
+  }
 
   if (is_empty()) {
     assert_free_region_list(length() == 0 && _tail == NULL, "invariant");
@@ -178,11 +224,7 @@
     }
   }
 
-  _length += from_list->length();
-  from_list->clear();
-
-  verify_optional();
-  from_list->verify_optional();
+  add_list_common_end(from_list);
 }
 
 void FreeRegionList::remove_starting_at(HeapRegion* first, uint num_regions) {
--- a/src/hotspot/share/gc/g1/heapRegionSet.hpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/g1/heapRegionSet.hpp	Tue Dec 10 10:44:09 2019 +0530
@@ -180,6 +180,10 @@
   inline void increase_length(uint node_index);
   inline void decrease_length(uint node_index);
 
+  // Common checks for adding a list.
+  void add_list_common_start(FreeRegionList* from_list);
+  void add_list_common_end(FreeRegionList* from_list);
+
 protected:
   // See the comment for HeapRegionSetBase::clear()
   virtual void clear();
@@ -202,6 +206,8 @@
   // Assumes that the list is ordered and will preserve that order. The order
   // is determined by hrm_index.
   inline void add_ordered(HeapRegion* hr);
+  // Same restrictions as above, but adds the region last in the list.
+  inline void add_to_tail(HeapRegion* region_to_add);
 
   // Removes from head or tail based on the given argument.
   HeapRegion* remove_region(bool from_head);
@@ -212,10 +218,15 @@
   // Merge two ordered lists. The result is also ordered. The order is
   // determined by hrm_index.
   void add_ordered(FreeRegionList* from_list);
+  void append_ordered(FreeRegionList* from_list);
 
   // It empties the list by removing all regions from it.
   void remove_all();
 
+  // Abandon current free list. Requires that all regions in the current list
+  // are taken care of separately, to allow a rebuild.
+  void abandon();
+
   // Remove all (contiguous) regions from first to first + num_regions -1 from
   // this list.
   // Num_regions must be > 1.
--- a/src/hotspot/share/gc/g1/heapRegionSet.inline.hpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/g1/heapRegionSet.inline.hpp	Tue Dec 10 10:44:09 2019 +0530
@@ -50,6 +50,26 @@
   _length--;
 }
 
+inline void FreeRegionList::add_to_tail(HeapRegion* region_to_add) {
+  assert_free_region_list((length() == 0 && _head == NULL && _tail == NULL && _last == NULL) ||
+                          (length() >  0 && _head != NULL && _tail != NULL && _tail->hrm_index() < region_to_add->hrm_index()),
+                          "invariant");
+  // add() will verify the region and check mt safety.
+  add(region_to_add);
+
+  if (_head != NULL) {
+    // Link into list, next is already NULL, no need to set.
+    region_to_add->set_prev(_tail);
+    _tail->set_next(region_to_add);
+    _tail = region_to_add;
+  } else {
+    // Empty list, this region is now the list.
+    _head = region_to_add;
+    _tail = region_to_add;
+  }
+  increase_length(region_to_add->node_index());
+}
+
 inline void FreeRegionList::add_ordered(HeapRegion* hr) {
   assert_free_region_list((length() == 0 && _head == NULL && _tail == NULL && _last == NULL) ||
                           (length() >  0 && _head != NULL && _tail != NULL),
--- a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -43,13 +43,16 @@
 PhaseGVN& C2ParseAccess::gvn() const { return _kit->gvn(); }
 
 bool C2Access::needs_cpu_membar() const {
-  bool mismatched = (_decorators & C2_MISMATCHED) != 0;
+  bool mismatched   = (_decorators & C2_MISMATCHED) != 0;
   bool is_unordered = (_decorators & MO_UNORDERED) != 0;
+
   bool anonymous = (_decorators & C2_UNSAFE_ACCESS) != 0;
-  bool in_heap = (_decorators & IN_HEAP) != 0;
+  bool in_heap   = (_decorators & IN_HEAP) != 0;
+  bool in_native = (_decorators & IN_NATIVE) != 0;
+  bool is_mixed  = !in_heap && !in_native;
 
-  bool is_write = (_decorators & C2_WRITE_ACCESS) != 0;
-  bool is_read = (_decorators & C2_READ_ACCESS) != 0;
+  bool is_write  = (_decorators & C2_WRITE_ACCESS) != 0;
+  bool is_read   = (_decorators & C2_READ_ACCESS) != 0;
   bool is_atomic = is_read && is_write;
 
   if (is_atomic) {
@@ -63,9 +66,11 @@
     // the barriers get omitted and the unsafe reference begins to "pollute"
     // the alias analysis of the rest of the graph, either Compile::can_alias
     // or Compile::must_alias will throw a diagnostic assert.)
-    if (!in_heap || !is_unordered || (mismatched && !_addr.type()->isa_aryptr())) {
+    if (is_mixed || !is_unordered || (mismatched && !_addr.type()->isa_aryptr())) {
       return true;
     }
+  } else {
+    assert(!is_mixed, "not unsafe");
   }
 
   return false;
@@ -80,7 +85,7 @@
   bool requires_atomic_access = (decorators & MO_UNORDERED) == 0;
 
   bool in_native = (decorators & IN_NATIVE) != 0;
-  assert(!in_native, "not supported yet");
+  assert(!in_native || (unsafe && !access.is_oop()), "not supported yet");
 
   MemNode::MemOrd mo = access.mem_node_mo();
 
--- a/src/hotspot/share/gc/shared/collectedHeap.hpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/shared/collectedHeap.hpp	Tue Dec 10 10:44:09 2019 +0530
@@ -387,6 +387,9 @@
   // Iterate over all objects, calling "cl.do_object" on each.
   virtual void object_iterate(ObjectClosure* cl) = 0;
 
+  // Keep alive an object that was loaded with AS_NO_KEEPALIVE.
+  virtual void keep_alive(oop obj) {}
+
   // Returns the longest time (in ms) that has elapsed since the last
   // time that any part of the heap was examined by a garbage collection.
   virtual jlong millis_since_last_gc() = 0;
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -1327,6 +1327,11 @@
   }
 }
 
+// Keep alive an object that was loaded with AS_NO_KEEPALIVE.
+void ShenandoahHeap::keep_alive(oop obj) {
+  ShenandoahBarrierSet::barrier_set()->enqueue(obj);
+}
+
 void ShenandoahHeap::heap_region_iterate(ShenandoahHeapRegionClosure* blk) const {
   for (size_t i = 0; i < num_regions(); i++) {
     ShenandoahHeapRegion* current = get_region(i);
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp	Tue Dec 10 10:44:09 2019 +0530
@@ -560,6 +560,9 @@
   // Used for native heap walkers: heap dumpers, mostly
   void object_iterate(ObjectClosure* cl);
 
+  // Keep alive an object that was loaded with AS_NO_KEEPALIVE.
+  void keep_alive(oop obj);
+
   // Used by RMI
   jlong millis_since_last_gc();
 
--- a/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -140,7 +140,7 @@
 public:
   ShenandoahMarkCLDClosure(OopClosure* cl) : _cl(cl) {}
   void do_cld(ClassLoaderData* cld) {
-    cld->oops_do(_cl, true, true);
+    cld->oops_do(_cl, ClassLoaderData::_claim_strong, true);
   }
 };
 
@@ -152,7 +152,7 @@
   ShenandoahRemarkCLDClosure(OopClosure* cl) : _cl(cl) {}
   void do_cld(ClassLoaderData* cld) {
     if (cld->has_modified_oops()) {
-      cld->oops_do(_cl, true, true);
+      cld->oops_do(_cl, ClassLoaderData::_claim_strong, true);
     }
   }
 };
--- a/src/hotspot/share/gc/z/zBarrier.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/z/zBarrier.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -31,14 +31,6 @@
 #include "runtime/safepoint.hpp"
 #include "utilities/debug.hpp"
 
-bool ZBarrier::during_mark() {
-  return ZGlobalPhase == ZPhaseMark;
-}
-
-bool ZBarrier::during_relocate() {
-  return ZGlobalPhase == ZPhaseRelocate;
-}
-
 template <bool finalizable>
 bool ZBarrier::should_mark_through(uintptr_t addr) {
   // Finalizable marked oops can still exists on the heap after marking
--- a/src/hotspot/share/gc/z/zBarrier.hpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/z/zBarrier.hpp	Tue Dec 10 10:44:09 2019 +0530
@@ -105,6 +105,7 @@
   static void keep_alive_barrier_on_weak_oop_field(volatile oop* p);
   static void keep_alive_barrier_on_phantom_oop_field(volatile oop* p);
   static void keep_alive_barrier_on_phantom_root_oop_field(oop* p);
+  static void keep_alive_barrier_on_oop(oop o);
 
   // Mark barrier
   static void mark_barrier_on_oop_field(volatile oop* p, bool finalizable);
--- a/src/hotspot/share/gc/z/zBarrier.inline.hpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/z/zBarrier.inline.hpp	Tue Dec 10 10:44:09 2019 +0530
@@ -144,6 +144,14 @@
   return ZAddress::is_weak_good_or_null(addr);
 }
 
+inline bool ZBarrier::during_mark() {
+  return ZGlobalPhase == ZPhaseMark;
+}
+
+inline bool ZBarrier::during_relocate() {
+  return ZGlobalPhase == ZPhaseRelocate;
+}
+
 //
 // Load barrier
 //
@@ -291,6 +299,12 @@
   root_barrier<is_good_or_null_fast_path, keep_alive_barrier_on_phantom_oop_slow_path>(p, o);
 }
 
+inline void ZBarrier::keep_alive_barrier_on_oop(oop o) {
+  if (during_mark()) {
+    barrier<is_null_fast_path, mark_barrier_on_oop_slow_path>(NULL, o);
+  }
+}
+
 //
 // Mark barrier
 //
--- a/src/hotspot/share/gc/z/zCollectedHeap.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/z/zCollectedHeap.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -247,6 +247,10 @@
   _heap.object_iterate(cl, true /* visit_weaks */);
 }
 
+void ZCollectedHeap::keep_alive(oop obj) {
+  _heap.keep_alive(obj);
+}
+
 void ZCollectedHeap::register_nmethod(nmethod* nm) {
   ZNMethod::register_nmethod(nm);
 }
--- a/src/hotspot/share/gc/z/zCollectedHeap.hpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/z/zCollectedHeap.hpp	Tue Dec 10 10:44:09 2019 +0530
@@ -99,6 +99,8 @@
 
   virtual void object_iterate(ObjectClosure* cl);
 
+  virtual void keep_alive(oop obj);
+
   virtual void register_nmethod(nmethod* nm);
   virtual void unregister_nmethod(nmethod* nm);
   virtual void flush_nmethod(nmethod* nm);
--- a/src/hotspot/share/gc/z/zHeap.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/z/zHeap.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -322,6 +322,10 @@
   return true;
 }
 
+void ZHeap::keep_alive(oop obj) {
+  ZBarrier::keep_alive_barrier_on_oop(obj);
+}
+
 void ZHeap::set_soft_reference_policy(bool clear) {
   _reference_processor.set_soft_reference_policy(clear);
 }
--- a/src/hotspot/share/gc/z/zHeap.hpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/gc/z/zHeap.hpp	Tue Dec 10 10:44:09 2019 +0530
@@ -137,6 +137,7 @@
   void mark(bool initial);
   void mark_flush_and_free(Thread* thread);
   bool mark_end();
+  void keep_alive(oop obj);
 
   // Relocation set
   void select_relocation_set();
--- a/src/hotspot/share/jvmci/jvmciEnv.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/jvmci/jvmciEnv.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -898,12 +898,11 @@
 
 JVMCIObject JVMCIEnv::new_StackTraceElement(const methodHandle& method, int bci, JVMCI_TRAPS) {
   JavaThread* THREAD = JavaThread::current();
-  Symbol* method_name_sym;
   Symbol* file_name_sym;
   int line_number;
-  Handle mirror (THREAD, method->method_holder()->java_mirror());
-  java_lang_StackTraceElement::decode(mirror, method, bci, method_name_sym, file_name_sym, line_number);
+  java_lang_StackTraceElement::decode(method, bci, file_name_sym, line_number, CHECK_(JVMCIObject()));
 
+  Symbol* method_name_sym = method->name();
   InstanceKlass* holder = method->method_holder();
   const char* declaring_class_str = holder->external_name();
 
--- a/src/hotspot/share/memory/heapInspection.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/memory/heapInspection.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -778,6 +778,10 @@
 
   void do_object(oop obj) {
     if (obj->is_a(_klass)) {
+      // obj was read with AS_NO_KEEPALIVE, or equivalent.
+      // The object needs to be kept alive when it is published.
+      Universe::heap()->keep_alive(obj);
+
       _result->append(obj);
     }
   }
--- a/src/hotspot/share/memory/metaspaceShared.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/memory/metaspaceShared.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -2052,6 +2052,7 @@
     if (result == MAP_ARCHIVE_MMAP_FAILURE) {
       // Mapping has failed (probably due to ASLR). Let's map at an address chosen
       // by the OS.
+      log_info(cds)("Try to map archive(s) at an alternative address");
       result = map_archives(static_mapinfo, dynamic_mapinfo, false);
     }
   }
--- a/src/hotspot/share/oops/accessDecorators.hpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/oops/accessDecorators.hpp	Tue Dec 10 10:44:09 2019 +0530
@@ -176,11 +176,11 @@
                                         ON_PHANTOM_OOP_REF | ON_UNKNOWN_OOP_REF;
 
 // === Access Location ===
-// Accesses can take place in, e.g. the heap, old or young generation and different native roots.
+// Accesses can take place in, e.g. the heap, old or young generation, different native roots, or native memory off the heap.
 // The location is important to the GC as it may imply different actions. The following decorators are used:
 // * IN_HEAP: The access is performed in the heap. Many barriers such as card marking will
 //   be omitted if this decorator is not set.
-// * IN_NATIVE: The access is performed in an off-heap data structure pointing into the Java heap.
+// * IN_NATIVE: The access is performed in an off-heap data structure.
 const DecoratorSet IN_HEAP            = UCONST64(1) << 19;
 const DecoratorSet IN_NATIVE          = UCONST64(1) << 20;
 const DecoratorSet IN_DECORATOR_MASK  = IN_HEAP | IN_NATIVE;
--- a/src/hotspot/share/oops/instanceKlass.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/oops/instanceKlass.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -1595,27 +1595,34 @@
 
 bool InstanceKlass::_disable_method_binary_search = false;
 
-int InstanceKlass::quick_search(const Array<Method*>* methods, const Symbol* name) {
+NOINLINE int linear_search(const Array<Method*>* methods, const Symbol* name) {
   int len = methods->length();
   int l = 0;
   int h = len - 1;
-
+  while (l <= h) {
+    Method* m = methods->at(l);
+    if (m->name() == name) {
+      return l;
+    }
+    l++;
+  }
+  return -1;
+}
+
+inline int InstanceKlass::quick_search(const Array<Method*>* methods, const Symbol* name) {
   if (_disable_method_binary_search) {
+    assert(DynamicDumpSharedSpaces, "must be");
     // At the final stage of dynamic dumping, the methods array may not be sorted
     // by ascending addresses of their names, so we can't use binary search anymore.
     // However, methods with the same name are still laid out consecutively inside the
     // methods array, so let's look for the first one that matches.
-    assert(DynamicDumpSharedSpaces, "must be");
-    while (l <= h) {
-      Method* m = methods->at(l);
-      if (m->name() == name) {
-        return l;
-      }
-      l ++;
-    }
-    return -1;
+    return linear_search(methods, name);
   }
 
+  int len = methods->length();
+  int l = 0;
+  int h = len - 1;
+
   // methods are sorted by ascending addresses of their names, so do binary search
   while (l <= h) {
     int mid = (l + h) >> 1;
--- a/src/hotspot/share/oops/instanceKlass.hpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/oops/instanceKlass.hpp	Tue Dec 10 10:44:09 2019 +0530
@@ -579,7 +579,7 @@
   bool find_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const;
 
  private:
-  static int quick_search(const Array<Method*>* methods, const Symbol* name);
+  inline static int quick_search(const Array<Method*>* methods, const Symbol* name);
 
  public:
   static void disable_method_binary_search() {
--- a/src/hotspot/share/opto/library_call.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/opto/library_call.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -1087,7 +1087,7 @@
   const Type* thread_type  = TypeOopPtr::make_from_klass(thread_klass)->cast_to_ptr_type(TypePtr::NotNull);
   Node* thread = _gvn.transform(new ThreadLocalNode());
   Node* p = basic_plus_adr(top()/*!oop*/, thread, in_bytes(JavaThread::threadObj_offset()));
-  Node* threadObj = make_load(NULL, p, thread_type, T_OBJECT, MemNode::unordered);
+  Node* threadObj = _gvn.transform(LoadNode::make(_gvn, NULL, immutable_memory(), p, p->bottom_type()->is_ptr(), thread_type, T_OBJECT, MemNode::unordered));
   tls_output = thread;
   return threadObj;
 }
@@ -2447,10 +2447,14 @@
   offset = ConvL2X(offset);
   adr = make_unsafe_address(base, offset, is_store ? ACCESS_WRITE : ACCESS_READ, type, kind == Relaxed);
 
-  if (_gvn.type(base)->isa_ptr() != TypePtr::NULL_PTR) {
-    heap_base_oop = base;
-  } else if (type == T_OBJECT) {
-    return false; // off-heap oop accesses are not supported
+  if (_gvn.type(base)->isa_ptr() == TypePtr::NULL_PTR) {
+    if (type != T_OBJECT) {
+      decorators |= IN_NATIVE; // off-heap primitive access
+    } else {
+      return false; // off-heap oop accesses are not supported
+    }
+  } else {
+    heap_base_oop = base; // on-heap or mixed access
   }
 
   // Can base be NULL? Otherwise, always on-heap access.
--- a/src/hotspot/share/prims/jvmtiTagMap.cpp	Mon Dec 09 14:59:33 2019 -0800
+++ b/src/hotspot/share/prims/jvmtiTagMap.cpp	Tue Dec 10 10:44:09 2019 +0530
@@ -483,6 +483,11 @@
 // is returned. Otherwise an new entry is allocated.
 JvmtiTagHashmapEntry* JvmtiTagMap::create_entry(oop ref, jlong tag) {
   assert(Thread::current()->is_VM_thread() || is_locked(), "checking");
+
+  // ref was read with AS_NO_KEEPALIVE, or equivalent.
+  // The object needs to be kept alive when it is published.
+  Universe::heap()->keep_alive(ref);
+
   JvmtiTagHashmapEntry* entry;
   if (_free_entries == NULL) {
     entry = new JvmtiTagHashmapEntry(ref, tag);
@@ -2958,7 +2963,7 @@
     ClassFieldDescriptor* field = field_map->field_at(i);
     char type = field->field_type();
     if (!is_primitive_field_type(type)) {
-      oop fld_o = o->obj_field(field->field_offset());
+      oop fld_o = o->obj_field_access<AS_NO_KEEPALIVE | ON_UNKNOWN_OOP_REF>(field->field_offset());
       // ignore any objects that aren't visible to profiler
       if (fld_o != NULL) {
         assert(Universe::heap()->is_in(fld_o), "unsafe code should not "
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/AdaptiveCoding.java	Mon Dec 09 14:59:33 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,298 +0,0 @@
-/*
- * Copyright (c) 2003, 2010, 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.
- */
-
-package com.sun.java.util.jar.pack;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import static com.sun.java.util.jar.pack.Constants.*;
-
-/**
- * Adaptive coding.
- * See the section "Adaptive Encodings" in the Pack200 spec.
- * @author John Rose
- */
-class AdaptiveCoding implements CodingMethod {
-    CodingMethod headCoding;
-    int          headLength;
-    CodingMethod tailCoding;
-
-    public AdaptiveCoding(int headLength, CodingMethod headCoding, CodingMethod tailCoding) {
-        assert(isCodableLength(headLength));
-        this.headLength = headLength;
-        this.headCoding = headCoding;
-        this.tailCoding = tailCoding;
-    }
-
-    public void setHeadCoding(CodingMethod headCoding) {
-        this.headCoding = headCoding;
-    }
-    public void setHeadLength(int headLength) {
-        assert(isCodableLength(headLength));
-        this.headLength = headLength;
-    }
-    public void setTailCoding(CodingMethod tailCoding) {
-        this.tailCoding = tailCoding;
-    }
-
-    public boolean isTrivial() {
-        return headCoding == tailCoding;
-    }
-
-    // CodingMethod methods.
-    public void writeArrayTo(OutputStream out, int[] a, int start, int end) throws IOException {
-        writeArray(this, out, a, start, end);
-    }
-    // writeArrayTo must be coded iteratively, not recursively:
-    private static void writeArray(AdaptiveCoding run, OutputStream out, int[] a, int start, int end) throws IOException {
-        for (;;) {
-            int mid = start+run.headLength;
-            assert(mid <= end);
-            run.headCoding.writeArrayTo(out, a, start, mid);
-            start = mid;
-            if (run.tailCoding instanceof AdaptiveCoding) {
-                run = (AdaptiveCoding) run.tailCoding;
-                continue;
-            }
-            break;
-        }
-        run.tailCoding.writeArrayTo(out, a, start, end);
-    }
-
-    public void readArrayFrom(InputStream in, int[] a, int start, int end) throws IOException {
-        readArray(this, in, a, start, end);
-    }
-    private static void readArray(AdaptiveCoding run, InputStream in, int[] a, int start, int end) throws IOException {
-        for (;;) {
-            int mid = start+run.headLength;
-            assert(mid <= end);
-            run.headCoding.readArrayFrom(in, a, start, mid);
-            start = mid;
-            if (run.tailCoding instanceof AdaptiveCoding) {
-                run = (AdaptiveCoding) run.tailCoding;
-                continue;
-            }
-            break;
-        }
-        run.tailCoding.readArrayFrom(in, a, start, end);
-    }
-
-    public static final int KX_MIN = 0;
-    public static final int KX_MAX = 3;
-    public static final int KX_LG2BASE = 4;
-    public static final int KX_BASE = 16;
-
-    public static final int KB_MIN = 0x00;
-    public static final int KB_MAX = 0xFF;
-    public static final int KB_OFFSET = 1;
-    public static final int KB_DEFAULT = 3;
-
-    static int getKXOf(int K) {
-        for (int KX = KX_MIN; KX <= KX_MAX; KX++) {
-            if (((K - KB_OFFSET) & ~KB_MAX) == 0)
-                return KX;
-            K >>>= KX_LG2BASE;
-        }
-        return -1;
-    }
-
-    static int getKBOf(int K) {
-        int KX = getKXOf(K);
-        if (KX < 0)  return -1;
-        K >>>= (KX * KX_LG2BASE);
-        return K-1;
-    }
-
-    static int decodeK(int KX, int KB) {
-        assert(KX_MIN <= KX && KX <= KX_MAX);
-        assert(KB_MIN <= KB && KB <= KB_MAX);
-        return (KB+KB_OFFSET) << (KX * KX_LG2BASE);
-    }
-
-    static int getNextK(int K) {
-        if (K <= 0)  return 1;  // 1st K value
-        int KX = getKXOf(K);
-        if (KX < 0)  return Integer.MAX_VALUE;
-        // This is the increment we expect to apply:
-        int unit = 1      << (KX * KX_LG2BASE);
-        int mask = KB_MAX << (KX * KX_LG2BASE);
-        int K1 = K + unit;
-        K1 &= ~(unit-1);  // cut off stray low-order bits
-        if (((K1 - unit) & ~mask) == 0) {
-            assert(getKXOf(K1) == KX);
-            return K1;
-        }
-        if (KX == KX_MAX)  return Integer.MAX_VALUE;
-        KX += 1;
-        int mask2 = KB_MAX << (KX * KX_LG2BASE);
-        K1 |= (mask & ~mask2);
-        K1 += unit;
-        assert(getKXOf(K1) == KX);
-        return K1;
-    }
-
-    // Is K of the form ((KB:[0..255])+1) * 16^(KX:{0..3])?
-    public static boolean isCodableLength(int K) {
-        int KX = getKXOf(K);
-        if (KX < 0)  return false;
-        int unit = 1      << (KX * KX_LG2BASE);
-        int mask = KB_MAX << (KX * KX_LG2BASE);
-        return ((K - unit) & ~mask) == 0;
-    }
-
-    public byte[] getMetaCoding(Coding dflt) {
-        //assert(!isTrivial()); // can happen
-        // See the isCodableLength restriction in CodingChooser.
-        ByteArrayOutputStream bytes = new ByteArrayOutputStream(10);
-        try {
-            makeMetaCoding(this, dflt, bytes);
-        } catch (IOException ee) {
-            throw new RuntimeException(ee);
-        }
-        return bytes.toByteArray();
-    }
-    private static void makeMetaCoding(AdaptiveCoding run, Coding dflt,
-                                       ByteArrayOutputStream bytes)
-                                      throws IOException {
-        for (;;) {
-            CodingMethod headCoding = run.headCoding;
-            int          headLength = run.headLength;
-            CodingMethod tailCoding = run.tailCoding;
-            int K = headLength;
-            assert(isCodableLength(K));
-            int ADef   = (headCoding == dflt)?1:0;
-            int BDef   = (tailCoding == dflt)?1:0;
-            if (ADef+BDef > 1)  BDef = 0;  // arbitrary choice
-            int ABDef  = 1*ADef + 2*BDef;
-            assert(ABDef < 3);
-            int KX     = getKXOf(K);
-            int KB     = getKBOf(K);
-            assert(decodeK(KX, KB) == K);
-            int KBFlag = (KB != KB_DEFAULT)?1:0;
-            bytes.write(_meta_run + KX + 4*KBFlag + 8*ABDef);
-            if (KBFlag != 0)    bytes.write(KB);
-            if (ADef == 0)  bytes.write(headCoding.getMetaCoding(dflt));
-            if (tailCoding instanceof AdaptiveCoding) {
-                run = (AdaptiveCoding) tailCoding;
-                continue; // tail call, to avoid deep stack recursion
-            }
-            if (BDef == 0)  bytes.write(tailCoding.getMetaCoding(dflt));
-            break;
-        }
-    }
-    public static int parseMetaCoding(byte[] bytes, int pos, Coding dflt, CodingMethod res[]) {
-        int op = bytes[pos++] & 0xFF;
-        if (op < _meta_run || op >= _meta_pop)  return pos-1; // backup
-        AdaptiveCoding prevc = null;
-        for (boolean keepGoing = true; keepGoing; ) {
-            keepGoing = false;
-            assert(op >= _meta_run);
-            op -= _meta_run;
-            int KX = op % 4;
-            int KBFlag = (op / 4) % 2;
-            int ABDef = (op / 8);
-            assert(ABDef < 3);
-            int ADef = (ABDef & 1);
-            int BDef = (ABDef & 2);
-            CodingMethod[] ACode = {dflt}, BCode = {dflt};
-            int KB = KB_DEFAULT;
-            if (KBFlag != 0)
-                KB = bytes[pos++] & 0xFF;
-            if (ADef == 0) {
-                pos = BandStructure.parseMetaCoding(bytes, pos, dflt, ACode);
-            }
-            if (BDef == 0 &&
-                ((op = bytes[pos] & 0xFF) >= _meta_run) && op < _meta_pop) {
-                pos++;
-                keepGoing = true;
-            } else if (BDef == 0) {
-                pos = BandStructure.parseMetaCoding(bytes, pos, dflt, BCode);
-            }
-            AdaptiveCoding newc = new AdaptiveCoding(decodeK(KX, KB),
-                                                     ACode[0], BCode[0]);
-            if (prevc == null) {
-                res[0] = newc;
-            } else {
-                prevc.tailCoding = newc;
-            }
-            prevc = newc;
-        }
-        return pos;
-    }
-
-    private String keyString(CodingMethod m) {
-        if (m instanceof Coding)
-            return ((Coding)m).keyString();
-        return m.toString();
-    }
-    public String toString() {
-        StringBuilder res = new StringBuilder(20);
-        AdaptiveCoding run = this;
-        res.append("run(");
-        for (;;) {
-            res.append(run.headLength).append("*");
-            res.append(keyString(run.headCoding));
-            if (run.tailCoding instanceof AdaptiveCoding) {
-                run = (AdaptiveCoding) run.tailCoding;
-                res.append(" ");
-                continue;
-            }
-            break;
-        }
-        res.append(" **").append(keyString(run.tailCoding));
-        res.append(")");
-        return res.toString();
-    }
-
-/*
-    public static void main(String av[]) {
-        int[][] samples = {
-            {1,2,3,4,5},
-            {254,255,256,256+1*16,256+2*16},
-            {0xfd,0xfe,0xff,0x100,0x110,0x120,0x130},
-            {0xfd0,0xfe0,0xff0,0x1000,0x1100,0x1200,0x1300},
-            {0xfd00,0xfe00,0xff00,0x10000,0x11000,0x12000,0x13000},
-            {0xfd000,0xfe000,0xff000,0x100000}
-        };
-        for (int i = 0; i < samples.length; i++) {
-            for (int j = 0; j < samples[i].length; j++) {
-                int K = samples[i][j];
-                int KX = getKXOf(K);
-                int KB = getKBOf(K);
-                System.out.println("K="+Integer.toHexString(K)+
-                                   " KX="+KX+" KB="+KB);
-                assert(isCodableLength(K));
-                assert(K == decodeK(KX, KB));
-                if (j == 0)  continue;
-                int K1 = samples[i][j-1];
-                assert(K == getNextK(K1));
-            }
-        }
-    }
-//*/
-
-}
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/Attribute.java	Mon Dec 09 14:59:33 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1699 +0,0 @@
-/*
- * Copyright (c) 2003, 2019, 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.
- */
-
-package com.sun.java.util.jar.pack;
-
-import com.sun.java.util.jar.pack.ConstantPool.Entry;
-import com.sun.java.util.jar.pack.ConstantPool.Index;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import static com.sun.java.util.jar.pack.Constants.*;
-
-/**
- * Represents an attribute in a class-file.
- * Takes care to remember where constant pool indexes occur.
- * Implements the "little language" of Pack200 for describing
- * attribute layouts.
- * @author John Rose
- */
-class Attribute implements Comparable<Attribute> {
-    // Attribute instance fields.
-
-    Layout def;     // the name and format of this attr
-    byte[] bytes;   // the actual bytes
-    Object fixups;  // reference relocations, if any are required
-
-    public String name() { return def.name(); }
-    public Layout layout() { return def; }
-    public byte[] bytes() { return bytes; }
-    public int size() { return bytes.length; }
-    public Entry getNameRef() { return def.getNameRef(); }
-
-    private Attribute(Attribute old) {
-        this.def = old.def;
-        this.bytes = old.bytes;
-        this.fixups = old.fixups;
-    }
-
-    public Attribute(Layout def, byte[] bytes, Object fixups) {
-        this.def = def;
-        this.bytes = bytes;
-        this.fixups = fixups;
-        Fixups.setBytes(fixups, bytes);
-    }
-    public Attribute(Layout def, byte[] bytes) {
-        this(def, bytes, null);
-    }
-
-    public Attribute addContent(byte[] bytes, Object fixups) {
-        assert(isCanonical());
-        if (bytes.length == 0 && fixups == null)
-            return this;
-        Attribute res = new Attribute(this);
-        res.bytes = bytes;
-        res.fixups = fixups;
-        Fixups.setBytes(fixups, bytes);
-        return res;
-    }
-    public Attribute addContent(byte[] bytes) {
-        return addContent(bytes, null);
-    }
-
-    public void finishRefs(Index ix) {
-        if (fixups != null) {
-            Fixups.finishRefs(fixups, bytes, ix);
-            fixups = null;
-        }
-    }
-
-    public boolean isCanonical() {
-        return this == def.canon;
-    }
-
-    @Override
-    public int compareTo(Attribute that) {
-        return this.def.compareTo(that.def);
-    }
-
-    private static final Map<List<Attribute>, List<Attribute>> canonLists = new HashMap<>();
-    private static final Map<Layout, Attribute> attributes = new HashMap<>();
-    private static final Map<Layout, Attribute> standardDefs = new HashMap<>();
-
-    // Canonicalized lists of trivial attrs (Deprecated, etc.)
-    // are used by trimToSize, in order to reduce footprint
-    // of some common cases.  (Note that Code attributes are
-    // always zero size.)
-    public static List<Attribute> getCanonList(List<Attribute> al) {
-        synchronized (canonLists) {
-            List<Attribute> cl = canonLists.get(al);
-            if (cl == null) {
-                cl = new ArrayList<>(al.size());
-                cl.addAll(al);
-                cl = Collections.unmodifiableList(cl);
-                canonLists.put(al, cl);
-            }
-            return cl;
-        }
-    }
-
-    // Find the canonical empty attribute with the given ctype, name, layout.
-    public static Attribute find(int ctype, String name, String layout) {
-        Layout key = Layout.makeKey(ctype, name, layout);
-        synchronized (attributes) {
-            Attribute a = attributes.get(key);
-            if (a == null) {
-                a = new Layout(ctype, name, layout).canonicalInstance();
-                attributes.put(key, a);
-            }
-            return a;
-        }
-    }
-
-    public static Layout keyForLookup(int ctype, String name) {
-        return Layout.makeKey(ctype, name);
-    }
-
-    // Find canonical empty attribute with given ctype and name,
-    // and with the standard layout.
-    public static Attribute lookup(Map<Layout, Attribute> defs, int ctype,
-            String name) {
-        if (defs == null) {
-            defs = standardDefs;
-        }
-        return defs.get(Layout.makeKey(ctype, name));
-    }
-
-    public static Attribute define(Map<Layout, Attribute> defs, int ctype,
-            String name, String layout) {
-        Attribute a = find(ctype, name, layout);
-        defs.put(Layout.makeKey(ctype, name), a);
-        return a;
-    }
-
-    static {
-        Map<Layout, Attribute> sd = standardDefs;
-        define(sd, ATTR_CONTEXT_CLASS, "Signature", "RSH");
-        define(sd, ATTR_CONTEXT_CLASS, "Synthetic", "");
-        define(sd, ATTR_CONTEXT_CLASS, "Deprecated", "");
-        define(sd, ATTR_CONTEXT_CLASS, "SourceFile", "RUH");
-        define(sd, ATTR_CONTEXT_CLASS, "EnclosingMethod", "RCHRDNH");
-        define(sd, ATTR_CONTEXT_CLASS, "InnerClasses", "NH[RCHRCNHRUNHFH]");
-        define(sd, ATTR_CONTEXT_CLASS, "BootstrapMethods", "NH[RMHNH[KLH]]");
-
-        define(sd, ATTR_CONTEXT_FIELD, "Signature", "RSH");
-        define(sd, ATTR_CONTEXT_FIELD, "Synthetic", "");
-        define(sd, ATTR_CONTEXT_FIELD, "Deprecated", "");
-        define(sd, ATTR_CONTEXT_FIELD, "ConstantValue", "KQH");
-
-        define(sd, ATTR_CONTEXT_METHOD, "Signature", "RSH");
-        define(sd, ATTR_CONTEXT_METHOD, "Synthetic", "");
-        define(sd, ATTR_CONTEXT_METHOD, "Deprecated", "");
-        define(sd, ATTR_CONTEXT_METHOD, "Exceptions", "NH[RCH]");
-        define(sd, ATTR_CONTEXT_METHOD, "MethodParameters", "NB[RUNHFH]");
-        //define(sd, ATTR_CONTEXT_METHOD, "Code", "HHNI[B]NH[PHPOHPOHRCNH]NH[RUHNI[B]]");
-
-        define(sd, ATTR_CONTEXT_CODE, "StackMapTable",
-               ("[NH[(1)]]" +
-                "[TB" +
-                "(64-127)[(2)]" +
-                "(247)[(1)(2)]" +
-                "(248-251)[(1)]" +
-                "(252)[(1)(2)]" +
-                "(253)[(1)(2)(2)]" +
-                "(254)[(1)(2)(2)(2)]" +
-                "(255)[(1)NH[(2)]NH[(2)]]" +
-                "()[]" +
-                "]" +
-                "[H]" +
-                "[TB(7)[RCH](8)[PH]()[]]"));
-
-        define(sd, ATTR_CONTEXT_CODE, "LineNumberTable", "NH[PHH]");
-        define(sd, ATTR_CONTEXT_CODE, "LocalVariableTable", "NH[PHOHRUHRSHH]");
-        define(sd, ATTR_CONTEXT_CODE, "LocalVariableTypeTable", "NH[PHOHRUHRSHH]");
-        //define(sd, ATTR_CONTEXT_CODE, "CharacterRangeTable", "NH[PHPOHIIH]");
-        //define(sd, ATTR_CONTEXT_CODE, "CoverageTable", "NH[PHHII]");
-
-        // Note:  Code and InnerClasses are special-cased elsewhere.
-        // Their layout specs. are given here for completeness.
-        // The Code spec is incomplete, in that it does not distinguish
-        // bytecode bytes or locate CP references.
-        // The BootstrapMethods attribute is also special-cased
-        // elsewhere as an appendix to the local constant pool.
-    }
-
-    // Metadata.
-    //
-    // We define metadata using similar layouts
-    // for all five kinds of metadata attributes and 2 type metadata attributes
-    //
-    // Regular annotations are a counted list of [RSHNH[RUH(1)]][...]
-    //   pack.method.attribute.RuntimeVisibleAnnotations=[NH[(1)]][RSHNH[RUH(1)]][TB...]
-    //
-    // Parameter annotations are a counted list of regular annotations.
-    //   pack.method.attribute.RuntimeVisibleParameterAnnotations=[NB[(1)]][NH[(1)]][RSHNH[RUH(1)]][TB...]
-    //
-    // RuntimeInvisible annotations are defined similarly...
-    // Non-method annotations are defined similarly...
-    //
-    // Annotation are a simple tagged value [TB...]
-    //   pack.attribute.method.AnnotationDefault=[TB...]
-
-    static {
-        String mdLayouts[] = {
-            Attribute.normalizeLayoutString
-            (""
-             +"\n  # parameter_annotations :="
-             +"\n  [ NB[(1)] ]     # forward call to annotations"
-             ),
-            Attribute.normalizeLayoutString
-            (""
-             +"\n  # annotations :="
-             +"\n  [ NH[(1)] ]     # forward call to annotation"
-             +"\n  "
-            ),
-            Attribute.normalizeLayoutString
-             (""
-             +"\n  # annotation :="
-             +"\n  [RSH"
-             +"\n    NH[RUH (1)]   # forward call to value"
-             +"\n    ]"
-             ),
-            Attribute.normalizeLayoutString
-            (""
-             +"\n  # value :="
-             +"\n  [TB # Callable 2 encodes one tagged value."
-             +"\n    (\\B,\\C,\\I,\\S,\\Z)[KIH]"
-             +"\n    (\\D)[KDH]"
-             +"\n    (\\F)[KFH]"
-             +"\n    (\\J)[KJH]"
-             +"\n    (\\c)[RSH]"
-             +"\n    (\\e)[RSH RUH]"
-             +"\n    (\\s)[RUH]"
-             +"\n    (\\[)[NH[(0)]] # backward self-call to value"
-             +"\n    (\\@)[RSH NH[RUH (0)]] # backward self-call to value"
-             +"\n    ()[] ]"
-             )
-        };
-        /*
-         * RuntimeVisibleTypeAnnotation and RuntimeInvisibleTypeAnnotatation are
-         * similar to RuntimeVisibleAnnotation and RuntimeInvisibleAnnotation,
-         * a type-annotation union  and a type-path structure precedes the
-         * annotation structure
-         */
-        String typeLayouts[] = {
-            Attribute.normalizeLayoutString
-            (""
-             +"\n # type-annotations :="
-             +"\n  [ NH[(1)(2)(3)] ]     # forward call to type-annotations"
-            ),
-            Attribute.normalizeLayoutString
-            ( ""
-             +"\n  # type-annotation :="
-             +"\n  [TB"
-             +"\n    (0-1) [B] # {CLASS, METHOD}_TYPE_PARAMETER"
-             +"\n    (16) [FH] # CLASS_EXTENDS"
-             +"\n    (17-18) [BB] # {CLASS, METHOD}_TYPE_PARAMETER_BOUND"
-             +"\n    (19-21) [] # FIELD, METHOD_RETURN, METHOD_RECEIVER"
-             +"\n    (22) [B] # METHOD_FORMAL_PARAMETER"
-             +"\n    (23) [H] # THROWS"
-             +"\n    (64-65) [NH[PHOHH]] # LOCAL_VARIABLE, RESOURCE_VARIABLE"
-             +"\n    (66) [H] # EXCEPTION_PARAMETER"
-             +"\n    (67-70) [PH] # INSTANCEOF, NEW, {CONSTRUCTOR, METHOD}_REFERENCE_RECEIVER"
-             +"\n    (71-75) [PHB] # CAST, {CONSTRUCTOR,METHOD}_INVOCATION_TYPE_ARGUMENT, {CONSTRUCTOR, METHOD}_REFERENCE_TYPE_ARGUMENT"
-             +"\n    ()[] ]"
-            ),
-            Attribute.normalizeLayoutString
-            (""
-             +"\n # type-path"
-             +"\n [ NB[BB] ]"
-            )
-        };
-        Map<Layout, Attribute> sd = standardDefs;
-        String defaultLayout     = mdLayouts[3];
-        String annotationsLayout = mdLayouts[1] + mdLayouts[2] + mdLayouts[3];
-        String paramsLayout      = mdLayouts[0] + annotationsLayout;
-        String typesLayout       = typeLayouts[0] + typeLayouts[1] +
-                                   typeLayouts[2] + mdLayouts[2] + mdLayouts[3];
-
-        for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) {
-            if (ctype != ATTR_CONTEXT_CODE) {
-                define(sd, ctype,
-                       "RuntimeVisibleAnnotations",   annotationsLayout);
-                define(sd, ctype,
-                       "RuntimeInvisibleAnnotations",  annotationsLayout);
-
-                if (ctype == ATTR_CONTEXT_METHOD) {
-                    define(sd, ctype,
-                           "RuntimeVisibleParameterAnnotations",   paramsLayout);
-                    define(sd, ctype,
-                           "RuntimeInvisibleParameterAnnotations", paramsLayout);
-                    define(sd, ctype,
-                           "AnnotationDefault", defaultLayout);
-                }
-            }
-            define(sd, ctype,
-                   "RuntimeVisibleTypeAnnotations", typesLayout);
-            define(sd, ctype,
-                   "RuntimeInvisibleTypeAnnotations", typesLayout);
-        }
-    }
-
-    public static String contextName(int ctype) {
-        switch (ctype) {
-        case ATTR_CONTEXT_CLASS: return "class";
-        case ATTR_CONTEXT_FIELD: return "field";
-        case ATTR_CONTEXT_METHOD: return "method";
-        case ATTR_CONTEXT_CODE: return "code";
-        }
-        return null;
-    }
-
-    /** Base class for any attributed object (Class, Field, Method, Code).
-     *  Flags are included because they are used to help transmit the
-     *  presence of attributes.  That is, flags are a mix of modifier
-     *  bits and attribute indicators.
-     */
-    public abstract static
-    class Holder {
-
-        // We need this abstract method to interpret embedded CP refs.
-        protected abstract Entry[] getCPMap();
-
-        protected int flags;             // defined here for convenience
-        protected List<Attribute> attributes;
-
-        public int attributeSize() {
-            return (attributes == null) ? 0 : attributes.size();
-        }
-
-        public void trimToSize() {
-            if (attributes == null) {
-                return;
-            }
-            if (attributes.isEmpty()) {
-                attributes = null;
-                return;
-            }
-            if (attributes instanceof ArrayList) {
-                ArrayList<Attribute> al = (ArrayList<Attribute>)attributes;
-                al.trimToSize();
-                boolean allCanon = true;
-                for (Attribute a : al) {
-                    if (!a.isCanonical()) {
-                        allCanon = false;
-                    }
-                    if (a.fixups != null) {
-                        assert(!a.isCanonical());
-                        a.fixups = Fixups.trimToSize(a.fixups);
-                    }
-                }
-                if (allCanon) {
-                    // Replace private writable attribute list
-                    // with only trivial entries by public unique
-                    // immutable attribute list with the same entries.
-                    attributes = getCanonList(al);
-                }
-            }
-        }
-
-        public void addAttribute(Attribute a) {
-            if (attributes == null)
-                attributes = new ArrayList<>(3);
-            else if (!(attributes instanceof ArrayList))
-                attributes = new ArrayList<>(attributes);  // unfreeze it
-            attributes.add(a);
-        }
-
-        public Attribute removeAttribute(Attribute a) {
-            if (attributes == null)       return null;
-            if (!attributes.contains(a))  return null;
-            if (!(attributes instanceof ArrayList))
-                attributes = new ArrayList<>(attributes);  // unfreeze it
-            attributes.remove(a);
-            return a;
-        }
-
-        public Attribute getAttribute(int n) {
-            return attributes.get(n);
-        }
-
-        protected void visitRefs(int mode, Collection<Entry> refs) {
-            if (attributes == null)  return;
-            for (Attribute a : attributes) {
-                a.visitRefs(this, mode, refs);
-            }
-        }
-
-        static final List<Attribute> noAttributes = Arrays.asList(new Attribute[0]);
-
-        public List<Attribute> getAttributes() {
-            if (attributes == null)
-                return noAttributes;
-            return attributes;
-        }
-
-        public void setAttributes(List<Attribute> attrList) {
-            if (attrList.isEmpty())
-                attributes = null;
-            else
-                attributes = attrList;
-        }
-
-        public Attribute getAttribute(String attrName) {
-            if (attributes == null)  return null;
-            for (Attribute a : attributes) {
-                if (a.name().equals(attrName))
-                    return a;
-            }
-            return null;
-        }
-
-        public Attribute getAttribute(Layout attrDef) {
-            if (attributes == null)  return null;
-            for (Attribute a : attributes) {
-                if (a.layout() == attrDef)
-                    return a;
-            }
-            return null;
-        }
-
-        public Attribute removeAttribute(String attrName) {
-            return removeAttribute(getAttribute(attrName));
-        }
-
-        public Attribute removeAttribute(Layout attrDef) {
-            return removeAttribute(getAttribute(attrDef));
-        }
-
-        public void strip(String attrName) {
-            removeAttribute(getAttribute(attrName));
-        }
-    }
-
-    // Lightweight interface to hide details of band structure.
-    // Also used for testing.
-    public abstract static
-    class ValueStream {
-        public int getInt(int bandIndex) { throw undef(); }
-        public void putInt(int bandIndex, int value) { throw undef(); }
-        public Entry getRef(int bandIndex) { throw undef(); }
-        public void putRef(int bandIndex, Entry ref) { throw undef(); }
-        // Note:  decodeBCI goes w/ getInt/Ref; encodeBCI goes w/ putInt/Ref
-        public int decodeBCI(int bciCode) { throw undef(); }
-        public int encodeBCI(int bci) { throw undef(); }
-        public void noteBackCall(int whichCallable) { /* ignore by default */ }
-        private RuntimeException undef() {
-            return new UnsupportedOperationException("ValueStream method");
-        }
-    }
-
-    // Element kinds:
-    static final byte EK_INT  = 1;     // B H I SH etc.
-    static final byte EK_BCI  = 2;     // PH POH etc.
-    static final byte EK_BCO  = 3;     // OH etc.
-    static final byte EK_FLAG = 4;     // FH etc.
-    static final byte EK_REPL = 5;     // NH[...] etc.
-    static final byte EK_REF  = 6;     // RUH, RUNH, KQH, etc.
-    static final byte EK_UN   = 7;     // TB(...)[...] etc.
-    static final byte EK_CASE = 8;     // (...)[...] etc.
-    static final byte EK_CALL = 9;     // (0), (1), etc.
-    static final byte EK_CBLE = 10;    // [...][...] etc.
-    static final byte EF_SIGN  = 1<<0;   // INT is signed
-    static final byte EF_DELTA = 1<<1;   // BCI/BCI value is diff'ed w/ previous
-    static final byte EF_NULL  = 1<<2;   // null REF is expected/allowed
-    static final byte EF_BACK  = 1<<3;   // call, callable, case is backward
-    static final int NO_BAND_INDEX = -1;
-
-    /** A "class" of attributes, characterized by a context-type, name
-     *  and format.  The formats are specified in a "little language".
-     */
-    public static
-    class Layout implements Comparable<Layout> {
-        int ctype;       // attribute context type, e.g., ATTR_CONTEXT_CODE
-        String name;     // name of attribute
-        boolean hasRefs; // this kind of attr contains CP refs?
-        String layout;   // layout specification
-        int bandCount;   // total number of elems
-        Element[] elems; // tokenization of layout
-        Attribute canon; // canonical instance of this layout
-
-        public int ctype() { return ctype; }
-        public String name() { return name; }
-        public String layout() { return layout; }
-        public Attribute canonicalInstance() { return canon; }
-
-        public Entry getNameRef() {
-            return ConstantPool.getUtf8Entry(name());
-        }
-
-        public boolean isEmpty() {
-            return layout.isEmpty();
-        }
-
-        public Layout(int ctype, String name, String layout) {
-            this.ctype = ctype;
-            this.name = name.intern();
-            this.layout = layout.intern();
-            assert(ctype < ATTR_CONTEXT_LIMIT);
-            boolean hasCallables = layout.startsWith("[");
-            try {
-                if (!hasCallables) {
-                    this.elems = tokenizeLayout(this, -1, layout);
-                } else {
-                    String[] bodies = splitBodies(layout);
-                    // Make the callables now, so they can be linked immediately.
-                    Element[] lelems = new Element[bodies.length];
-                    this.elems = lelems;
-                    for (int i = 0; i < lelems.length; i++) {
-                        Element ce = this.new Element();
-                        ce.kind = EK_CBLE;
-                        ce.removeBand();
-                        ce.bandIndex = NO_BAND_INDEX;
-                        ce.layout = bodies[i];
-                        lelems[i] = ce;
-                    }
-                    // Next fill them in.
-                    for (int i = 0; i < lelems.length; i++) {
-                        Element ce = lelems[i];
-                        ce.body = tokenizeLayout(this, i, bodies[i]);
-                    }
-                    //System.out.println(Arrays.asList(elems));
-                }
-            } catch (StringIndexOutOfBoundsException ee) {
-                // simplest way to catch syntax errors...
-                throw new RuntimeException("Bad attribute layout: "+layout, ee);
-            }
-            // Some uses do not make a fresh one for each occurrence.
-            // For example, if layout == "", we only need one attr to share.
-            canon = new Attribute(this, noBytes);
-        }
-        private Layout() {}
-        static Layout makeKey(int ctype, String name, String layout) {
-            Layout def = new Layout();
-            def.ctype = ctype;
-            def.name = name.intern();
-            def.layout = layout.intern();
-            assert(ctype < ATTR_CONTEXT_LIMIT);
-            return def;
-        }
-        static Layout makeKey(int ctype, String name) {
-            return makeKey(ctype, name, "");
-        }
-
-        public Attribute addContent(byte[] bytes, Object fixups) {
-            return canon.addContent(bytes, fixups);
-        }
-        public Attribute addContent(byte[] bytes) {
-            return canon.addContent(bytes, null);
-        }
-
-        @Override
-        public boolean equals(Object x) {
-            return ( x != null) && ( x.getClass() == Layout.class ) &&
-                    equals((Layout)x);
-        }
-        public boolean equals(Layout that) {
-            return this.name.equals(that.name)
-                && this.layout.equals(that.layout)
-                && this.ctype == that.ctype;
-        }
-        @Override
-        public int hashCode() {
-            return (((17 + name.hashCode())
-                    * 37 + layout.hashCode())
-                    * 37 + ctype);
-        }
-        @Override
-        public int compareTo(Layout that) {
-            int r;
-            r = this.name.compareTo(that.name);
-            if (r != 0)  return r;
-            r = this.layout.compareTo(that.layout);
-            if (r != 0)  return r;
-            return this.ctype - that.ctype;
-        }
-        @Override
-        public String toString() {
-            String str = contextName(ctype)+"."+name+"["+layout+"]";
-            // If -ea, print out more informative strings!
-            assert((str = stringForDebug()) != null);
-            return str;
-        }
-        private String stringForDebug() {
-            return contextName(ctype)+"."+name+Arrays.asList(elems);
-        }
-
-        public
-        class Element {
-            String layout;   // spelling in the little language
-            byte flags;      // EF_SIGN, etc.
-            byte kind;       // EK_UINT, etc.
-            byte len;        // scalar length of element
-            byte refKind;    // CONSTANT_String, etc.
-            int bandIndex;   // which band does this element govern?
-            int value;       // extra parameter
-            Element[] body;  // extra data (for replications, unions, calls)
-
-            boolean flagTest(byte mask) { return (flags & mask) != 0; }
-
-            Element() {
-                bandIndex = bandCount++;
-            }
-
-            void removeBand() {
-                --bandCount;
-                assert(bandIndex == bandCount);
-                bandIndex = NO_BAND_INDEX;
-            }
-
-            public boolean hasBand() {
-                return bandIndex >= 0;
-            }
-            public String toString() {
-                String str = layout;
-                // If -ea, print out more informative strings!
-                assert((str = stringForDebug()) != null);
-                return str;
-            }
-            private String stringForDebug() {
-                Element[] lbody = this.body;
-                switch (kind) {
-                case EK_CALL:
-                    lbody = null;
-                    break;
-                case EK_CASE:
-                    if (flagTest(EF_BACK))
-                        lbody = null;
-                    break;
-                }
-                return layout
-                    + (!hasBand()?"":"#"+bandIndex)
-                    + "<"+ (flags==0?"":""+flags)+kind+len
-                    + (refKind==0?"":""+refKind) + ">"
-                    + (value==0?"":"("+value+")")
-                    + (lbody==null?"": ""+Arrays.asList(lbody));
-            }
-        }
-
-        public boolean hasCallables() {
-            return (elems.length > 0 && elems[0].kind == EK_CBLE);
-        }
-        private static final Element[] noElems = {};
-        public Element[] getCallables() {
-            if (hasCallables()) {
-                Element[] nelems = Arrays.copyOf(elems, elems.length);
-                return nelems;
-            } else
-                return noElems;  // no callables at all
-        }
-        public Element[] getEntryPoint() {
-            if (hasCallables())
-                return elems[0].body;  // body of first callable
-            else {
-                Element[] nelems = Arrays.copyOf(elems, elems.length);
-                return nelems;  // no callables; whole body
-            }
-        }
-
-        /** Return a sequence of tokens from the given attribute bytes.
-         *  Sequence elements will be 1-1 correspondent with my layout tokens.
-         */
-        public void parse(Holder holder,
-                          byte[] bytes, int pos, int len, ValueStream out) {
-            int end = parseUsing(getEntryPoint(),
-                                 holder, bytes, pos, len, out);
-            if (end != pos + len)
-                throw new InternalError("layout parsed "+(end-pos)+" out of "+len+" bytes");
-        }
-        /** Given a sequence of tokens, return the attribute bytes.
-         *  Sequence elements must be 1-1 correspondent with my layout tokens.
-         *  The returned object is a cookie for Fixups.finishRefs, which
-         *  must be used to harden any references into integer indexes.
-         */
-        public Object unparse(ValueStream in, ByteArrayOutputStream out) {
-            Object[] fixups = { null };
-            unparseUsing(getEntryPoint(), fixups, in, out);
-            return fixups[0]; // return ref-bearing cookie, if any
-        }
-
-        public String layoutForClassVersion(Package.Version vers) {
-            if (vers.lessThan(JAVA6_MAX_CLASS_VERSION)) {
-                // Disallow layout syntax in the oldest protocol version.
-                return expandCaseDashNotation(layout);
-            }
-            return layout;
-        }
-    }
-
-    public static
-    class FormatException extends IOException {
-        @java.io.Serial
-        private static final long serialVersionUID = -2542243830788066513L;
-
-        private int ctype;
-        private String name;
-        String layout;
-        public FormatException(String message,
-                               int ctype, String name, String layout) {
-            super(ATTR_CONTEXT_NAME[ctype]+ " attribute \"" + name + "\"" +
-                  (message == null? "" : (": " + message)));
-            this.ctype = ctype;
-            this.name = name;
-            this.layout = layout;
-        }
-        public FormatException(String message,
-                               int ctype, String name) {
-            this(message, ctype, name, null);
-        }
-    }
-
-    void visitRefs(Holder holder, int mode, final Collection<Entry> refs) {
-        if (mode == VRM_CLASSIC) {
-            refs.add(getNameRef());
-        }
-        // else the name is owned by the layout, and is processed elsewhere
-        if (bytes.length == 0)  return;  // quick exit
-        if (!def.hasRefs)       return;  // quick exit
-        if (fixups != null) {
-            Fixups.visitRefs(fixups, refs);
-            return;
-        }
-        // References (to a local cpMap) are embedded in the bytes.
-        def.parse(holder, bytes, 0, bytes.length,
-            new ValueStream() {
-                @Override
-                public void putInt(int bandIndex, int value) {
-                }
-                @Override
-                public void putRef(int bandIndex, Entry ref) {
-                    refs.add(ref);
-                }
-                @Override
-                public int encodeBCI(int bci) {
-                    return bci;
-                }
-            });
-    }
-
-    public void parse(Holder holder, byte[] bytes, int pos, int len, ValueStream out) {
-        def.parse(holder, bytes, pos, len, out);
-    }
-    public Object unparse(ValueStream in, ByteArrayOutputStream out) {
-        return def.unparse(in, out);
-    }
-
-    @Override
-    public String toString() {
-        return def
-            +"{"+(bytes == null ? -1 : size())+"}"
-            +(fixups == null? "": fixups.toString());
-    }
-
-    /** Remove any informal "pretty printing" from the layout string.
-     *  Removes blanks and control chars.
-     *  Removes '#' comments (to end of line).
-     *  Replaces '\c' by the decimal code of the character c.
-     *  Replaces '0xNNN' by the decimal code of the hex number NNN.
-     */
-    public static
-    String normalizeLayoutString(String layout) {
-        StringBuilder buf = new StringBuilder();
-        for (int i = 0, len = layout.length(); i < len; ) {
-            char ch = layout.charAt(i++);
-            if (ch <= ' ') {
-                // Skip whitespace and control chars
-                continue;
-            } else if (ch == '#') {
-                // Skip to end of line.
-                int end1 = layout.indexOf('\n', i);
-                int end2 = layout.indexOf('\r', i);
-                if (end1 < 0)  end1 = len;
-                if (end2 < 0)  end2 = len;
-                i = Math.min(end1, end2);
-            } else if (ch == '\\') {
-                // Map a character reference to its decimal code.
-                buf.append((int) layout.charAt(i++));
-            } else if (ch == '0' && layout.startsWith("0x", i-1)) {
-                // Map a hex numeral to its decimal code.
-                int start = i-1;
-                int end = start+2;
-                while (end < len) {
-                    int dig = layout.charAt(end);
-                    if ((dig >= '0' && dig <= '9') ||
-                        (dig >= 'a' && dig <= 'f'))
-                        ++end;
-                    else
-                        break;
-                }
-                if (end > start) {
-                    String num = layout.substring(start, end);
-                    buf.append(Integer.decode(num));
-                    i = end;
-                } else {
-                    buf.append(ch);
-                }
-            } else {
-                buf.append(ch);
-            }
-        }
-        String result = buf.toString();
-        if (false && !result.equals(layout)) {
-            Utils.log.info("Normalizing layout string");
-            Utils.log.info("    From: "+layout);
-            Utils.log.info("    To:   "+result);
-        }
-        return result;
-    }
-
-    /// Subroutines for parsing and unparsing:
-
-    /** Parse the attribute layout language.
-<pre>
-  attribute_layout:
-        ( layout_element )* | ( callable )+
-  layout_element:
-        ( integral | replication | union | call | reference )
-
-  callable:
-        '[' body ']'
-  body:
-        ( layout_element )+
-
-  integral:
-        ( unsigned_int | signed_int | bc_index | bc_offset | flag )
-  unsigned_int:
-        uint_type
-  signed_int:
-        'S' uint_type
-  any_int:
-        ( unsigned_int | signed_int )
-  bc_index:
-        ( 'P' uint_type | 'PO' uint_type )
-  bc_offset:
-        'O' any_int
-  flag:
-        'F' uint_type
-  uint_type:
-        ( 'B' | 'H' | 'I' | 'V' )
-
-  replication:
-        'N' uint_type '[' body ']'
-
-  union:
-        'T' any_int (union_case)* '(' ')' '[' (body)? ']'
-  union_case:
-        '(' union_case_tag (',' union_case_tag)* ')' '[' (body)? ']'
-  union_case_tag:
-        ( numeral | numeral '-' numeral )
-  call:
-        '(' numeral ')'
-
-  reference:
-        reference_type ( 'N' )? uint_type
-  reference_type:
-        ( constant_ref | schema_ref | utf8_ref | untyped_ref )
-  constant_ref:
-        ( 'KI' | 'KJ' | 'KF' | 'KD' | 'KS' | 'KQ' | 'KM' | 'KT' | 'KL' )
-  schema_ref:
-        ( 'RC' | 'RS' | 'RD' | 'RF' | 'RM' | 'RI' | 'RY' | 'RB' | 'RN' )
-  utf8_ref:
-        'RU'
-  untyped_ref:
-        'RQ'
-
-  numeral:
-        '(' ('-')? (digit)+ ')'
-  digit:
-        ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' )
- </pre>
-    */
-    static //private
-    Layout.Element[] tokenizeLayout(Layout self, int curCble, String layout) {
-        List<Layout.Element> col = new ArrayList<>(layout.length());
-        tokenizeLayout(self, curCble, layout, col);
-        Layout.Element[] res = new Layout.Element[col.size()];
-        col.toArray(res);
-        return res;
-    }
-    static //private
-    void tokenizeLayout(Layout self, int curCble, String layout, List<Layout.Element> col) {
-        boolean prevBCI = false;
-        for (int len = layout.length(), i = 0; i < len; ) {
-            int start = i;
-            int body;
-            Layout.Element e = self.new Element();
-            byte kind;
-            //System.out.println("at "+i+": ..."+layout.substring(i));
-            // strip a prefix
-            switch (layout.charAt(i++)) {
-            /// layout_element: integral
-            case 'B': case 'H': case 'I': case 'V': // unsigned_int
-                kind = EK_INT;
-                --i; // reparse
-                i = tokenizeUInt(e, layout, i);
-                break;
-            case 'S': // signed_int
-                kind = EK_INT;
-                --i; // reparse
-                i = tokenizeSInt(e, layout, i);
-                break;
-            case 'P': // bc_index
-                kind = EK_BCI;
-                if (layout.charAt(i++) == 'O') {
-                    // bc_index: 'PO' tokenizeUInt
-                    e.flags |= EF_DELTA;
-                    // must follow P or PO:
-                    if (!prevBCI)
-                        { i = -i; continue; } // fail
-                    i++; // move forward
-                }
-                --i; // reparse
-                i = tokenizeUInt(e, layout, i);
-                break;
-            case 'O': // bc_offset
-                kind = EK_BCO;
-                e.flags |= EF_DELTA;
-                // must follow P or PO:
-                if (!prevBCI)
-                    { i = -i; continue; } // fail
-                i = tokenizeSInt(e, layout, i);
-                break;
-            case 'F': // flag
-                kind = EK_FLAG;
-                i = tokenizeUInt(e, layout, i);
-                break;
-            case 'N': // replication: 'N' uint '[' elem ... ']'
-                kind = EK_REPL;
-                i = tokenizeUInt(e, layout, i);
-                if (layout.charAt(i++) != '[')
-                    { i = -i; continue; } // fail
-                i = skipBody(layout, body = i);
-                e.body = tokenizeLayout(self, curCble,
-                                        layout.substring(body, i++));
-                break;
-            case 'T': // union: 'T' any_int union_case* '(' ')' '[' body ']'
-                kind = EK_UN;
-                i = tokenizeSInt(e, layout, i);
-                List<Layout.Element> cases = new ArrayList<>();
-                for (;;) {
-                    // Keep parsing cases until we hit the default case.
-                    if (layout.charAt(i++) != '(')
-                        { i = -i; break; } // fail
-                    int beg = i;
-                    i = layout.indexOf(')', i);
-                    String cstr = layout.substring(beg, i++);
-                    int cstrlen = cstr.length();
-                    if (layout.charAt(i++) != '[')
-                        { i = -i; break; } // fail
-                    // Check for duplication.
-                    if (layout.charAt(i) == ']')
-                        body = i;  // missing body, which is legal here
-                    else
-                        i = skipBody(layout, body = i);
-                    Layout.Element[] cbody
-                        = tokenizeLayout(self, curCble,
-                                         layout.substring(body, i++));
-                    if (cstrlen == 0) {
-                        Layout.Element ce = self.new Element();
-                        ce.body = cbody;
-                        ce.kind = EK_CASE;
-                        ce.removeBand();
-                        cases.add(ce);
-                        break;  // done with the whole union
-                    } else {
-                        // Parse a case string.
-                        boolean firstCaseNum = true;
-                        for (int cp = 0, endp;; cp = endp+1) {
-                            // Look for multiple case tags:
-                            endp = cstr.indexOf(',', cp);
-                            if (endp < 0)  endp = cstrlen;
-                            String cstr1 = cstr.substring(cp, endp);
-                            if (cstr1.isEmpty())
-                                cstr1 = "empty";  // will fail parse
-                            int value0, value1;
-                            // Check for a case range (new in 1.6).
-                            int dash = findCaseDash(cstr1, 0);
-                            if (dash >= 0) {
-                                value0 = parseIntBefore(cstr1, dash);
-                                value1 = parseIntAfter(cstr1, dash);
-                                if (value0 >= value1)
-                                    { i = -i; break; } // fail
-                            } else {
-                                value0 = value1 = Integer.parseInt(cstr1);
-                            }
-                            // Add a case for each value in value0..value1
-                            for (;; value0++) {
-                                Layout.Element ce = self.new Element();
-                                ce.body = cbody;  // all cases share one body
-                                ce.kind = EK_CASE;
-                                ce.removeBand();
-                                if (!firstCaseNum)
-                                    // "backward case" repeats a body
-                                    ce.flags |= EF_BACK;
-                                firstCaseNum = false;
-                                ce.value = value0;
-                                cases.add(ce);
-                                if (value0 == value1)  break;
-                            }
-                            if (endp == cstrlen) {
-                                break;  // done with this case
-                            }
-                        }
-                    }
-                }
-                e.body = new Layout.Element[cases.size()];
-                cases.toArray(e.body);
-                e.kind = kind;
-                for (int j = 0; j < e.body.length-1; j++) {
-                    Layout.Element ce = e.body[j];
-                    if (matchCase(e, ce.value) != ce) {
-                        // Duplicate tag.
-                        { i = -i; break; } // fail
-                    }
-                }
-                break;
-            case '(': // call: '(' '-'? digit+ ')'
-                kind = EK_CALL;
-                e.removeBand();
-                i = layout.indexOf(')', i);
-                String cstr = layout.substring(start+1, i++);
-                int offset = Integer.parseInt(cstr);
-                int target = curCble + offset;
-                if (!(offset+"").equals(cstr) ||
-                    self.elems == null ||
-                    target < 0 ||
-                    target >= self.elems.length)
-                    { i = -i; continue; } // fail
-                Layout.Element ce = self.elems[target];
-                assert(ce.kind == EK_CBLE);
-                e.value = target;
-                e.body = new Layout.Element[]{ ce };
-                // Is it a (recursive) backward call?
-                if (offset <= 0) {
-                    // Yes.  Mark both caller and callee backward.
-                    e.flags  |= EF_BACK;
-                    ce.flags |= EF_BACK;
-                }
-                break;
-            case 'K':  // reference_type: constant_ref
-                kind = EK_REF;
-                switch (layout.charAt(i++)) {
-                case 'I': e.refKind = CONSTANT_Integer; break;
-                case 'J': e.refKind = CONSTANT_Long; break;
-                case 'F': e.refKind = CONSTANT_Float; break;
-                case 'D': e.refKind = CONSTANT_Double; break;
-                case 'S': e.refKind = CONSTANT_String; break;
-                case 'Q': e.refKind = CONSTANT_FieldSpecific; break;
-
-                // new in 1.7:
-                case 'M': e.refKind = CONSTANT_MethodHandle; break;
-                case 'T': e.refKind = CONSTANT_MethodType; break;
-                case 'L': e.refKind = CONSTANT_LoadableValue; break;
-                default: { i = -i; continue; } // fail
-                }
-                break;
-            case 'R': // schema_ref
-                kind = EK_REF;
-                switch (layout.charAt(i++)) {
-                case 'C': e.refKind = CONSTANT_Class; break;
-                case 'S': e.refKind = CONSTANT_Signature; break;
-                case 'D': e.refKind = CONSTANT_NameandType; break;
-                case 'F': e.refKind = CONSTANT_Fieldref; break;
-                case 'M': e.refKind = CONSTANT_Methodref; break;
-                case 'I': e.refKind = CONSTANT_InterfaceMethodref; break;
-
-                case 'U': e.refKind = CONSTANT_Utf8; break; //utf8_ref
-                case 'Q': e.refKind = CONSTANT_All; break; //untyped_ref
-
-                // new in 1.7:
-                case 'Y': e.refKind = CONSTANT_InvokeDynamic; break;
-                case 'B': e.refKind = CONSTANT_BootstrapMethod; break;
-                case 'N': e.refKind = CONSTANT_AnyMember; break;
-
-                default: { i = -i; continue; } // fail
-                }
-                break;
-            default: { i = -i; continue; } // fail
-            }
-
-            // further parsing of refs
-            if (kind == EK_REF) {
-                // reference: reference_type -><- ( 'N' )? tokenizeUInt
-                if (layout.charAt(i++) == 'N') {
-                    e.flags |= EF_NULL;
-                    i++; // move forward
-                }
-                --i; // reparse
-                i = tokenizeUInt(e, layout, i);
-                self.hasRefs = true;
-            }
-
-            prevBCI = (kind == EK_BCI);
-
-            // store the new element
-            e.kind = kind;
-            e.layout = layout.substring(start, i);
-            col.add(e);
-        }
-    }
-    static //private
-    String[] splitBodies(String layout) {
-        List<String> bodies = new ArrayList<>();
-        // Parse several independent layout bodies:  "[foo][bar]...[baz]"
-        for (int i = 0; i < layout.length(); i++) {
-            if (layout.charAt(i++) != '[')
-                layout.charAt(-i);  // throw error
-            int body;
-            i = skipBody(layout, body = i);
-            bodies.add(layout.substring(body, i));
-        }
-        String[] res = new String[bodies.size()];
-        bodies.toArray(res);
-        return res;
-    }
-    private static
-    int skipBody(String layout, int i) {
-        assert(layout.charAt(i-1) == '[');
-        if (layout.charAt(i) == ']')
-            // No empty bodies, please.
-            return -i;
-        // skip balanced [...[...]...]
-        for (int depth = 1; depth > 0; ) {
-            switch (layout.charAt(i++)) {
-            case '[': depth++; break;
-            case ']': depth--; break;
-            }
-        }
-        --i;  // get before bracket
-        assert(layout.charAt(i) == ']');
-        return i;  // return closing bracket
-    }
-    private static
-    int tokenizeUInt(Layout.Element e, String layout, int i) {
-        switch (layout.charAt(i++)) {
-        case 'V': e.len = 0; break;
-        case 'B': e.len = 1; break;
-        case 'H': e.len = 2; break;
-        case 'I': e.len = 4; break;
-        default: return -i;
-        }
-        return i;
-    }
-    private static
-    int tokenizeSInt(Layout.Element e, String layout, int i) {
-        if (layout.charAt(i) == 'S') {
-            e.flags |= EF_SIGN;
-            ++i;
-        }
-        return tokenizeUInt(e, layout, i);
-    }
-
-    private static
-    boolean isDigit(char c) {
-        return c >= '0' && c <= '9';
-    }
-
-    /** Find an occurrence of hyphen '-' between two numerals. */
-    static //private
-    int findCaseDash(String layout, int fromIndex) {
-        if (fromIndex <= 0)  fromIndex = 1;  // minimum dash pos
-        int lastDash = layout.length() - 2;  // maximum dash pos
-        for (;;) {
-            int dash = layout.indexOf('-', fromIndex);
-            if (dash < 0 || dash > lastDash)  return -1;
-            if (isDigit(layout.charAt(dash-1))) {
-                char afterDash = layout.charAt(dash+1);
-                if (afterDash == '-' && dash+2 < layout.length())
-                    afterDash = layout.charAt(dash+2);
-                if (isDigit(afterDash)) {
-                    // matched /[0-9]--?[0-9]/; return position of dash
-                    return dash;
-                }
-            }
-            fromIndex = dash+1;
-        }
-    }
-    static
-    int parseIntBefore(String layout, int dash) {
-        int end = dash;
-        int beg = end;
-        while (beg > 0 && isDigit(layout.charAt(beg-1))) {
-            --beg;
-        }
-        if (beg == end)  return Integer.parseInt("empty");
-        // skip backward over a sign
-        if (beg >= 1 && layout.charAt(beg-1) == '-')  --beg;
-        assert(beg == 0 || !isDigit(layout.charAt(beg-1)));
-        return Integer.parseInt(layout.substring(beg, end));
-    }
-    static
-    int parseIntAfter(String layout, int dash) {
-        int beg = dash+1;
-        int end = beg;
-        int limit = layout.length();
-        if (end < limit && layout.charAt(end) == '-')  ++end;
-        while (end < limit && isDigit(layout.charAt(end))) {
-            ++end;
-        }
-        if (beg == end)  return Integer.parseInt("empty");
-        return Integer.parseInt(layout.substring(beg, end));
-    }
-    /** For compatibility with 1.5 pack, expand 1-5 into 1,2,3,4,5. */
-    static
-    String expandCaseDashNotation(String layout) {
-        int dash = findCaseDash(layout, 0);
-        if (dash < 0)  return layout;  // no dashes (the common case)
-        StringBuilder result = new StringBuilder(layout.length() * 3);
-        int sofar = 0;  // how far have we processed the layout?
-        for (;;) {
-            // for each dash, collect everything up to the dash
-            result.append(layout, sofar, dash);
-            sofar = dash+1;  // skip the dash
-            // then collect intermediate values
-            int value0 = parseIntBefore(layout, dash);
-            int value1 = parseIntAfter(layout, dash);
-            assert(value0 < value1);
-            result.append(",");  // close off value0 numeral
-            for (int i = value0+1; i < value1; i++) {
-                result.append(i);
-                result.append(",");  // close off i numeral
-            }
-            dash = findCaseDash(layout, sofar);
-            if (dash < 0)  break;
-        }
-        result.append(layout, sofar, layout.length());  // collect the rest
-        return result.toString();
-    }
-    static {
-        assert(expandCaseDashNotation("1-5").equals("1,2,3,4,5"));
-        assert(expandCaseDashNotation("-2--1").equals("-2,-1"));
-        assert(expandCaseDashNotation("-2-1").equals("-2,-1,0,1"));
-        assert(expandCaseDashNotation("-1-0").equals("-1,0"));
-    }
-
-    // Parse attribute bytes, putting values into bands.  Returns new pos.
-    // Used when reading a class file (local refs resolved with local cpMap).
-    // Also used for ad hoc scanning.
-    static
-    int parseUsing(Layout.Element[] elems, Holder holder,
-                   byte[] bytes, int pos, int len, ValueStream out) {
-        int prevBCI = 0;
-        int prevRBCI = 0;
-        int end = pos + len;
-        int[] buf = { 0 };  // for calls to parseInt, holds 2nd result
-        for (int i = 0; i < elems.length; i++) {
-            Layout.Element e = elems[i];
-            int bandIndex = e.bandIndex;
-            int value;
-            int BCI, RBCI;
-            switch (e.kind) {
-            case EK_INT:
-                pos = parseInt(e, bytes, pos, buf);
-                value = buf[0];
-                out.putInt(bandIndex, value);
-                break;
-            case EK_BCI:  // PH, POH
-                pos = parseInt(e, bytes, pos, buf);
-                BCI = buf[0];
-                RBCI = out.encodeBCI(BCI);
-                if (!e.flagTest(EF_DELTA)) {
-                    // PH:  transmit R(bci), store bci
-                    value = RBCI;
-                } else {
-                    // POH:  transmit D(R(bci)), store bci
-                    value = RBCI - prevRBCI;
-                }
-                prevBCI = BCI;
-                prevRBCI = RBCI;
-                out.putInt(bandIndex, value);
-                break;
-            case EK_BCO:  // OH
-                assert(e.flagTest(EF_DELTA));
-                // OH:  transmit D(R(bci)), store D(bci)
-                pos = parseInt(e, bytes, pos, buf);
-                BCI = prevBCI + buf[0];
-                RBCI = out.encodeBCI(BCI);
-                value = RBCI - prevRBCI;
-                prevBCI = BCI;
-                prevRBCI = RBCI;
-                out.putInt(bandIndex, value);
-                break;
-            case EK_FLAG:
-                pos = parseInt(e, bytes, pos, buf);
-                value = buf[0];
-                out.putInt(bandIndex, value);
-                break;
-            case EK_REPL:
-                pos = parseInt(e, bytes, pos, buf);
-                value = buf[0];
-                out.putInt(bandIndex, value);
-                for (int j = 0; j < value; j++) {
-                    pos = parseUsing(e.body, holder, bytes, pos, end-pos, out);
-                }
-                break;  // already transmitted the scalar value
-            case EK_UN:
-                pos = parseInt(e, bytes, pos, buf);
-                value = buf[0];
-                out.putInt(bandIndex, value);
-                Layout.Element ce = matchCase(e, value);
-                pos = parseUsing(ce.body, holder, bytes, pos, end-pos, out);
-
-                break;  // already transmitted the scalar value
-            case EK_CALL:
-                // Adjust band offset if it is a backward call.
-                assert(e.body.length == 1);
-                assert(e.body[0].kind == EK_CBLE);
-                if (e.flagTest(EF_BACK))
-                    out.noteBackCall(e.value);
-                pos = parseUsing(e.body[0].body, holder, bytes, pos, end-pos, out);
-                break;  // no additional scalar value to transmit
-            case EK_REF:
-                pos = parseInt(e, bytes, pos, buf);
-                int localRef = buf[0];
-                Entry globalRef;
-                if (localRef == 0) {
-                    globalRef = null;  // N.B. global null reference is -1
-                } else {
-                    Entry[] cpMap = holder.getCPMap();
-                    globalRef = (localRef >= 0 && localRef < cpMap.length
-                                    ? cpMap[localRef]
-                                    : null);
-                    byte tag = e.refKind;
-                    if (globalRef != null && tag == CONSTANT_Signature
-                        && globalRef.getTag() == CONSTANT_Utf8) {
-                        // Cf. ClassReader.readSignatureRef.
-                        String typeName = globalRef.stringValue();
-                        globalRef = ConstantPool.getSignatureEntry(typeName);
-                    }
-                    String got = (globalRef == null
-                        ? "invalid CP index"
-                        : "type=" + ConstantPool.tagName(globalRef.tag));
-                    if (globalRef == null || !globalRef.tagMatches(tag)) {
-                        throw new IllegalArgumentException(
-                                "Bad constant, expected type=" +
-                                ConstantPool.tagName(tag) + " got " + got);
-                    }
-                }
-                out.putRef(bandIndex, globalRef);
-                break;
-            default: assert(false);
-            }
-        }
-        return pos;
-    }
-
-    static
-    Layout.Element matchCase(Layout.Element e, int value) {
-        assert(e.kind == EK_UN);
-        int lastj = e.body.length-1;
-        for (int j = 0; j < lastj; j++) {
-            Layout.Element ce = e.body[j];
-            assert(ce.kind == EK_CASE);
-            if (value == ce.value)
-                return ce;
-        }
-        return e.body[lastj];
-    }
-
-    private static
-    int parseInt(Layout.Element e, byte[] bytes, int pos, int[] buf) {
-        int value = 0;
-        int loBits = e.len * 8;
-        // Read in big-endian order:
-        for (int bitPos = loBits; (bitPos -= 8) >= 0; ) {
-            value += (bytes[pos++] & 0xFF) << bitPos;
-        }
-        if (loBits < 32 && e.flagTest(EF_SIGN)) {
-            // sign-extend subword value
-            int hiBits = 32 - loBits;
-            value = (value << hiBits) >> hiBits;
-        }
-        buf[0] = value;
-        return pos;
-    }
-
-    // Format attribute bytes, drawing values from bands.
-    // Used when emptying attribute bands into a package model.
-    // (At that point CP refs. are not yet assigned indexes.)
-    static
-    void unparseUsing(Layout.Element[] elems, Object[] fixups,
-                      ValueStream in, ByteArrayOutputStream out) {
-        int prevBCI = 0;
-        int prevRBCI = 0;
-        for (int i = 0; i < elems.length; i++) {
-            Layout.Element e = elems[i];
-            int bandIndex = e.bandIndex;
-            int value;
-            int BCI, RBCI;  // "RBCI" is R(BCI), BCI's coded representation
-            switch (e.kind) {
-            case EK_INT:
-                value = in.getInt(bandIndex);
-                unparseInt(e, value, out);
-                break;
-            case EK_BCI:  // PH, POH
-                value = in.getInt(bandIndex);
-                if (!e.flagTest(EF_DELTA)) {
-                    // PH:  transmit R(bci), store bci
-                    RBCI = value;
-                } else {
-                    // POH:  transmit D(R(bci)), store bci
-                    RBCI = prevRBCI + value;
-                }
-                assert(prevBCI == in.decodeBCI(prevRBCI));
-                BCI = in.decodeBCI(RBCI);
-                unparseInt(e, BCI, out);
-                prevBCI = BCI;
-                prevRBCI = RBCI;
-                break;
-            case EK_BCO:  // OH
-                value = in.getInt(bandIndex);
-                assert(e.flagTest(EF_DELTA));
-                // OH:  transmit D(R(bci)), store D(bci)
-                assert(prevBCI == in.decodeBCI(prevRBCI));
-                RBCI = prevRBCI + value;
-                BCI = in.decodeBCI(RBCI);
-                unparseInt(e, BCI - prevBCI, out);
-                prevBCI = BCI;
-                prevRBCI = RBCI;
-                break;
-            case EK_FLAG:
-                value = in.getInt(bandIndex);
-                unparseInt(e, value, out);
-                break;
-            case EK_REPL:
-                value = in.getInt(bandIndex);
-                unparseInt(e, value, out);
-                for (int j = 0; j < value; j++) {
-                    unparseUsing(e.body, fixups, in, out);
-                }
-                break;
-            case EK_UN:
-                value = in.getInt(bandIndex);
-                unparseInt(e, value, out);
-                Layout.Element ce = matchCase(e, value);
-                unparseUsing(ce.body, fixups, in, out);
-                break;
-            case EK_CALL:
-                assert(e.body.length == 1);
-                assert(e.body[0].kind == EK_CBLE);
-                unparseUsing(e.body[0].body, fixups, in, out);
-                break;
-            case EK_REF:
-                Entry globalRef = in.getRef(bandIndex);
-                int localRef;
-                if (globalRef != null) {
-                    // It's a one-element array, really an lvalue.
-                    fixups[0] = Fixups.addRefWithLoc(fixups[0], out.size(), globalRef);
-                    localRef = 0; // placeholder for fixups
-                } else {
-                    localRef = 0; // fixed null value
-                }
-                unparseInt(e, localRef, out);
-                break;
-            default: assert(false); continue;
-            }
-        }
-    }
-
-    private static
-    void unparseInt(Layout.Element e, int value, ByteArrayOutputStream out) {
-        int loBits = e.len * 8;
-        if (loBits == 0) {
-            // It is not stored at all ('V' layout).
-            return;
-        }
-        if (loBits < 32) {
-            int hiBits = 32 - loBits;
-            int codedValue;
-            if (e.flagTest(EF_SIGN))
-                codedValue = (value << hiBits) >> hiBits;
-            else
-                codedValue = (value << hiBits) >>> hiBits;
-            if (codedValue != value)
-                throw new InternalError("cannot code in "+e.len+" bytes: "+value);
-        }
-        // Write in big-endian order:
-        for (int bitPos = loBits; (bitPos -= 8) >= 0; ) {
-            out.write((byte)(value >>> bitPos));
-        }
-    }
-
-/*
-    /// Testing.
-    public static void main(String av[]) {
-        int maxVal = 12;
-        int iters = 0;
-        boolean verbose;
-        int ap = 0;
-        while (ap < av.length) {
-            if (!av[ap].startsWith("-"))  break;
-            if (av[ap].startsWith("-m"))
-                maxVal = Integer.parseInt(av[ap].substring(2));
-            else if (av[ap].startsWith("-i"))
-                iters = Integer.parseInt(av[ap].substring(2));
-            else
-                throw new RuntimeException("Bad option: "+av[ap]);
-            ap++;
-        }
-        verbose = (iters == 0);
-        if (iters <= 0)  iters = 1;
-        if (ap == av.length) {
-            av = new String[] {
-                "HH",         // ClassFile.version
-                "RUH",        // SourceFile
-                "RCHRDNH",    // EnclosingMethod
-                "KQH",        // ConstantValue
-                "NH[RCH]",    // Exceptions
-                "NH[PHH]",    // LineNumberTable
-                "NH[PHOHRUHRSHH]",      // LocalVariableTable
-                "NH[PHPOHIIH]",         // CharacterRangeTable
-                "NH[PHHII]",            // CoverageTable
-                "NH[RCHRCNHRUNHFH]",    // InnerClasses
-                "NH[RMHNH[KLH]]",       // BootstrapMethods
-                "HHNI[B]NH[PHPOHPOHRCNH]NH[RUHNI[B]]", // Code
-                "=AnnotationDefault",
-                // Like metadata, but with a compact tag set:
-                "[NH[(1)]]"
-                +"[NH[(1)]]"
-                +"[RSHNH[RUH(1)]]"
-                +"[TB(0,1,3)[KIH](2)[KDH](5)[KFH](4)[KJH](7)[RSH](8)[RSHRUH](9)[RUH](10)[(-1)](6)[NH[(0)]]()[]]",
-                ""
-            };
-            ap = 0;
-        }
-        Utils.currentInstance.set(new PackerImpl());
-        final int[][] counts = new int[2][3];  // int bci ref
-        final Entry[] cpMap = new Entry[maxVal+1];
-        for (int i = 0; i < cpMap.length; i++) {
-            if (i == 0)  continue;  // 0 => null
-            cpMap[i] = ConstantPool.getLiteralEntry(new Integer(i));
-        }
-        Package.Class cls = new Package().new Class("");
-        cls.cpMap = cpMap;
-        class TestValueStream extends ValueStream {
-            java.util.Random rand = new java.util.Random(0);
-            ArrayList history = new ArrayList();
-            int ckidx = 0;
-            int maxVal;
-            boolean verbose;
-            void reset() { history.clear(); ckidx = 0; }
-            public int getInt(int bandIndex) {
-                counts[0][0]++;
-                int value = rand.nextInt(maxVal+1);
-                history.add(new Integer(bandIndex));
-                history.add(new Integer(value));
-                return value;
-            }
-            public void putInt(int bandIndex, int token) {
-                counts[1][0]++;
-                if (verbose)
-                    System.out.print(" "+bandIndex+":"+token);
-                // Make sure this put parallels a previous get:
-                int check0 = ((Integer)history.get(ckidx+0)).intValue();
-                int check1 = ((Integer)history.get(ckidx+1)).intValue();
-                if (check0 != bandIndex || check1 != token) {
-                    if (!verbose)
-                        System.out.println(history.subList(0, ckidx));
-                    System.out.println(" *** Should be "+check0+":"+check1);
-                    throw new RuntimeException("Failed test!");
-                }
-                ckidx += 2;
-            }
-            public Entry getRef(int bandIndex) {
-                counts[0][2]++;
-                int value = getInt(bandIndex);
-                if (value < 0 || value > maxVal) {
-                    System.out.println(" *** Unexpected ref code "+value);
-                    return ConstantPool.getLiteralEntry(new Integer(value));
-                }
-                return cpMap[value];
-            }
-            public void putRef(int bandIndex, Entry ref) {
-                counts[1][2]++;
-                if (ref == null) {
-                    putInt(bandIndex, 0);
-                    return;
-                }
-                Number refValue = null;
-                if (ref instanceof ConstantPool.NumberEntry)
-                    refValue = ((ConstantPool.NumberEntry)ref).numberValue();
-                int value;
-                if (!(refValue instanceof Integer)) {
-                    System.out.println(" *** Unexpected ref "+ref);
-                    value = -1;
-                } else {
-                    value = ((Integer)refValue).intValue();
-                }
-                putInt(bandIndex, value);
-            }
-            public int encodeBCI(int bci) {
-                counts[1][1]++;
-                // move LSB to MSB of low byte
-                int code = (bci >> 8) << 8;  // keep high bits
-                code += (bci & 0xFE) >> 1;
-                code += (bci & 0x01) << 7;
-                return code ^ (8<<8);  // mark it clearly as coded
-            }
-            public int decodeBCI(int bciCode) {
-                counts[0][1]++;
-                bciCode ^= (8<<8);  // remove extra mark
-                int bci = (bciCode >> 8) << 8;  // keep high bits
-                bci += (bciCode & 0x7F) << 1;
-                bci += (bciCode & 0x80) >> 7;
-                return bci;
-            }
-        }
-        TestValueStream tts = new TestValueStream();
-        tts.maxVal = maxVal;
-        tts.verbose = verbose;
-        ByteArrayOutputStream buf = new ByteArrayOutputStream();
-        for (int i = 0; i < (1 << 30); i = (i + 1) * 5) {
-            int ei = tts.encodeBCI(i);
-            int di = tts.decodeBCI(ei);
-            if (di != i)  System.out.println("i="+Integer.toHexString(i)+
-                                             " ei="+Integer.toHexString(ei)+
-                                             " di="+Integer.toHexString(di));
-        }
-        while (iters-- > 0) {
-            for (int i = ap; i < av.length; i++) {
-                String layout = av[i];
-                if (layout.startsWith("=")) {
-                    String name = layout.substring(1);
-                    for (Attribute a : standardDefs.values()) {
-                        if (a.name().equals(name)) {
-                            layout = a.layout().layout();
-                            break;
-                        }
-                    }
-                    if (layout.startsWith("=")) {
-                        System.out.println("Could not find "+name+" in "+standardDefs.values());
-                    }
-                }
-                Layout self = new Layout(0, "Foo", layout);
-                if (verbose) {
-                    System.out.print("/"+layout+"/ => ");
-                    System.out.println(Arrays.asList(self.elems));
-                }
-                buf.reset();
-                tts.reset();
-                Object fixups = self.unparse(tts, buf);
-                byte[] bytes = buf.toByteArray();
-                // Attach the references to the byte array.
-                Fixups.setBytes(fixups, bytes);
-                // Patch the references to their frozen values.
-                Fixups.finishRefs(fixups, bytes, new Index("test", cpMap));
-                if (verbose) {
-                    System.out.print("  bytes: {");
-                    for (int j = 0; j < bytes.length; j++) {
-                        System.out.print(" "+bytes[j]);
-                    }
-                    System.out.println("}");
-                }
-                if (verbose) {
-                    System.out.print("  parse: {");
-                }
-                self.parse(cls, bytes, 0, bytes.length, tts);
-                if (verbose) {
-                    System.out.println("}");
-                }
-            }
-        }
-        for (int j = 0; j <= 1; j++) {
-            System.out.print("values "+(j==0?"read":"written")+": {");
-            for (int k = 0; k < counts[j].length; k++) {
-                System.out.print(" "+counts[j][k]);
-            }
-            System.out.println(" }");
-        }
-    }
-//*/
-}
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/BandStructure.java	Mon Dec 09 14:59:33 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2762 +0,0 @@
-/*
- * Copyright (c) 2001, 2013, 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.
- */
-
-package com.sun.java.util.jar.pack;
-
-import com.sun.java.util.jar.pack.ConstantPool.Entry;
-import com.sun.java.util.jar.pack.ConstantPool.Index;
-import com.sun.java.util.jar.pack.Package.Class.Field;
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.EOFException;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FilterInputStream;
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.jar.Pack200;
-import static com.sun.java.util.jar.pack.Constants.*;
-import java.util.LinkedList;
-
-/**
- * Define the structure and ordering of "bands" in a packed file.
- * @author John Rose
- */
-@SuppressWarnings({"removal"})
-abstract
-class BandStructure {
-    static final int MAX_EFFORT = 9;
-    static final int MIN_EFFORT = 1;
-    static final int DEFAULT_EFFORT = 5;
-
-    // Inherit options from Pack200:
-    PropMap p200 = Utils.currentPropMap();
-
-    int verbose = p200.getInteger(Utils.DEBUG_VERBOSE);
-    int effort = p200.getInteger(Pack200.Packer.EFFORT);
-    { if (effort == 0)  effort = DEFAULT_EFFORT; }
-    boolean optDumpBands = p200.getBoolean(Utils.COM_PREFIX+"dump.bands");
-    boolean optDebugBands = p200.getBoolean(Utils.COM_PREFIX+"debug.bands");
-
-    // Various heuristic options.
-    boolean optVaryCodings = !p200.getBoolean(Utils.COM_PREFIX+"no.vary.codings");
-    boolean optBigStrings = !p200.getBoolean(Utils.COM_PREFIX+"no.big.strings");
-
-    protected abstract Index getCPIndex(byte tag);
-
-    // Local copy of highest class version.
-    private Package.Version highestClassVersion = null;
-
-    /** Call this exactly once, early, to specify the archive major version. */
-    public void initHighestClassVersion(Package.Version highestClassVersion) throws IOException {
-        if (this.highestClassVersion != null) {
-            throw new IOException(
-                "Highest class major version is already initialized to " +
-                this.highestClassVersion + "; new setting is " + highestClassVersion);
-        }
-        this.highestClassVersion = highestClassVersion;
-        adjustToClassVersion();
-    }
-
-    public Package.Version getHighestClassVersion() {
-        return highestClassVersion;
-    }
-
-    private final boolean isReader = this instanceof PackageReader;
-
-    protected BandStructure() {}
-
-    static final Coding BYTE1 = Coding.of(1,256);
-
-    static final Coding CHAR3 = Coding.of(3,128);
-    // Note:  Tried sharper (3,16) with no post-zip benefit.
-
-    // This is best used with BCI values:
-    static final Coding BCI5 = Coding.of(5,4);  // mostly 1-byte offsets
-    static final Coding BRANCH5 = Coding.of(5,4,2); // mostly forward branches
-
-    static final Coding UNSIGNED5 = Coding.of(5,64);
-    static final Coding UDELTA5 = UNSIGNED5.getDeltaCoding();
-    // "sharp" (5,64) zips 0.4% better than "medium" (5,128)
-    // It zips 1.1% better than "flat" (5,192)
-
-    static final Coding SIGNED5 = Coding.of(5,64,1);  //sharp
-    static final Coding DELTA5 = SIGNED5.getDeltaCoding();
-    // Note:  Tried (5,128,2) and (5,192,2) with no benefit.
-
-    static final Coding MDELTA5 = Coding.of(5,64,2).getDeltaCoding();
-
-    private static final Coding[] basicCodings = {
-        // Table of "Canonical BHSD Codings" from Pack200 spec.
-        null,  // _meta_default
-
-        // Fixed-length codings:
-        Coding.of(1,256,0),
-        Coding.of(1,256,1),
-        Coding.of(1,256,0).getDeltaCoding(),
-        Coding.of(1,256,1).getDeltaCoding(),
-        Coding.of(2,256,0),
-        Coding.of(2,256,1),
-        Coding.of(2,256,0).getDeltaCoding(),
-        Coding.of(2,256,1).getDeltaCoding(),
-        Coding.of(3,256,0),
-        Coding.of(3,256,1),
-        Coding.of(3,256,0).getDeltaCoding(),
-        Coding.of(3,256,1).getDeltaCoding(),
-        Coding.of(4,256,0),
-        Coding.of(4,256,1),
-        Coding.of(4,256,0).getDeltaCoding(),
-        Coding.of(4,256,1).getDeltaCoding(),
-
-        // Full-range variable-length codings:
-        Coding.of(5,  4,0),
-        Coding.of(5,  4,1),
-        Coding.of(5,  4,2),
-        Coding.of(5, 16,0),
-        Coding.of(5, 16,1),
-        Coding.of(5, 16,2),
-        Coding.of(5, 32,0),
-        Coding.of(5, 32,1),
-        Coding.of(5, 32,2),
-        Coding.of(5, 64,0),
-        Coding.of(5, 64,1),
-        Coding.of(5, 64,2),
-        Coding.of(5,128,0),
-        Coding.of(5,128,1),
-        Coding.of(5,128,2),
-
-        Coding.of(5,  4,0).getDeltaCoding(),
-        Coding.of(5,  4,1).getDeltaCoding(),
-        Coding.of(5,  4,2).getDeltaCoding(),
-        Coding.of(5, 16,0).getDeltaCoding(),
-        Coding.of(5, 16,1).getDeltaCoding(),
-        Coding.of(5, 16,2).getDeltaCoding(),
-        Coding.of(5, 32,0).getDeltaCoding(),
-        Coding.of(5, 32,1).getDeltaCoding(),
-        Coding.of(5, 32,2).getDeltaCoding(),
-        Coding.of(5, 64,0).getDeltaCoding(),
-        Coding.of(5, 64,1).getDeltaCoding(),
-        Coding.of(5, 64,2).getDeltaCoding(),
-        Coding.of(5,128,0).getDeltaCoding(),
-        Coding.of(5,128,1).getDeltaCoding(),
-        Coding.of(5,128,2).getDeltaCoding(),
-
-        // Variable length subrange codings:
-        Coding.of(2,192,0),
-        Coding.of(2,224,0),
-        Coding.of(2,240,0),
-        Coding.of(2,248,0),
-        Coding.of(2,252,0),
-
-        Coding.of(2,  8,0).getDeltaCoding(),
-        Coding.of(2,  8,1).getDeltaCoding(),
-        Coding.of(2, 16,0).getDeltaCoding(),
-        Coding.of(2, 16,1).getDeltaCoding(),
-        Coding.of(2, 32,0).getDeltaCoding(),
-        Coding.of(2, 32,1).getDeltaCoding(),
-        Coding.of(2, 64,0).getDeltaCoding(),
-        Coding.of(2, 64,1).getDeltaCoding(),
-        Coding.of(2,128,0).getDeltaCoding(),
-        Coding.of(2,128,1).getDeltaCoding(),
-        Coding.of(2,192,0).getDeltaCoding(),
-        Coding.of(2,192,1).getDeltaCoding(),
-        Coding.of(2,224,0).getDeltaCoding(),
-        Coding.of(2,224,1).getDeltaCoding(),
-        Coding.of(2,240,0).getDeltaCoding(),
-        Coding.of(2,240,1).getDeltaCoding(),
-        Coding.of(2,248,0).getDeltaCoding(),
-        Coding.of(2,248,1).getDeltaCoding(),
-
-        Coding.of(3,192,0),
-        Coding.of(3,224,0),
-        Coding.of(3,240,0),
-        Coding.of(3,248,0),
-        Coding.of(3,252,0),
-
-        Coding.of(3,  8,0).getDeltaCoding(),
-        Coding.of(3,  8,1).getDeltaCoding(),
-        Coding.of(3, 16,0).getDeltaCoding(),
-        Coding.of(3, 16,1).getDeltaCoding(),
-        Coding.of(3, 32,0).getDeltaCoding(),
-        Coding.of(3, 32,1).getDeltaCoding(),
-        Coding.of(3, 64,0).getDeltaCoding(),
-        Coding.of(3, 64,1).getDeltaCoding(),
-        Coding.of(3,128,0).getDeltaCoding(),
-        Coding.of(3,128,1).getDeltaCoding(),
-        Coding.of(3,192,0).getDeltaCoding(),
-        Coding.of(3,192,1).getDeltaCoding(),
-        Coding.of(3,224,0).getDeltaCoding(),
-        Coding.of(3,224,1).getDeltaCoding(),
-        Coding.of(3,240,0).getDeltaCoding(),
-        Coding.of(3,240,1).getDeltaCoding(),
-        Coding.of(3,248,0).getDeltaCoding(),
-        Coding.of(3,248,1).getDeltaCoding(),
-
-        Coding.of(4,192,0),
-        Coding.of(4,224,0),
-        Coding.of(4,240,0),
-        Coding.of(4,248,0),
-        Coding.of(4,252,0),
-
-        Coding.of(4,  8,0).getDeltaCoding(),
-        Coding.of(4,  8,1).getDeltaCoding(),
-        Coding.of(4, 16,0).getDeltaCoding(),
-        Coding.of(4, 16,1).getDeltaCoding(),
-        Coding.of(4, 32,0).getDeltaCoding(),
-        Coding.of(4, 32,1).getDeltaCoding(),
-        Coding.of(4, 64,0).getDeltaCoding(),
-        Coding.of(4, 64,1).getDeltaCoding(),
-        Coding.of(4,128,0).getDeltaCoding(),
-        Coding.of(4,128,1).getDeltaCoding(),
-        Coding.of(4,192,0).getDeltaCoding(),
-        Coding.of(4,192,1).getDeltaCoding(),
-        Coding.of(4,224,0).getDeltaCoding(),
-        Coding.of(4,224,1).getDeltaCoding(),
-        Coding.of(4,240,0).getDeltaCoding(),
-        Coding.of(4,240,1).getDeltaCoding(),
-        Coding.of(4,248,0).getDeltaCoding(),
-        Coding.of(4,248,1).getDeltaCoding(),
-
-        null
-    };
-    private static final Map<Coding, Integer> basicCodingIndexes;
-    static {
-        assert(basicCodings[_meta_default] == null);
-        assert(basicCodings[_meta_canon_min] != null);
-        assert(basicCodings[_meta_canon_max] != null);
-        Map<Coding, Integer> map = new HashMap<>();
-        for (int i = 0; i < basicCodings.length; i++) {
-            Coding c = basicCodings[i];
-            if (c == null)  continue;
-            assert(i >= _meta_canon_min);
-            assert(i <= _meta_canon_max);
-            map.put(c, i);
-        }
-        basicCodingIndexes = map;
-    }
-    public static Coding codingForIndex(int i) {
-        return i < basicCodings.length ? basicCodings[i] : null;
-    }
-    public static int indexOf(Coding c) {
-        Integer i = basicCodingIndexes.get(c);
-        if (i == null)  return 0;
-        return i.intValue();
-    }
-    public static Coding[] getBasicCodings() {
-        return basicCodings.clone();
-    }
-
-    protected byte[] bandHeaderBytes;    // used for input only
-    protected int    bandHeaderBytePos;  // BHB read pointer, for input only
-    protected int    bandHeaderBytePos0; // for debug
-
-    protected CodingMethod getBandHeader(int XB, Coding regularCoding) {
-        CodingMethod[] res = {null};
-        // push back XB onto the band header bytes
-        bandHeaderBytes[--bandHeaderBytePos] = (byte) XB;
-        bandHeaderBytePos0 = bandHeaderBytePos;
-        // scan forward through XB and any additional band header bytes
-        bandHeaderBytePos = parseMetaCoding(bandHeaderBytes,
-                                            bandHeaderBytePos,
-                                            regularCoding,
-                                            res);
-        return res[0];
-    }
-
-    public static int parseMetaCoding(byte[] bytes, int pos, Coding dflt, CodingMethod[] res) {
-        if ((bytes[pos] & 0xFF) == _meta_default) {
-            res[0] = dflt;
-            return pos+1;
-        }
-        int pos2;
-        pos2 = Coding.parseMetaCoding(bytes, pos, dflt, res);
-        if (pos2 > pos)  return pos2;
-        pos2 = PopulationCoding.parseMetaCoding(bytes, pos, dflt, res);
-        if (pos2 > pos)  return pos2;
-        pos2 = AdaptiveCoding.parseMetaCoding(bytes, pos, dflt, res);
-        if (pos2 > pos)  return pos2;
-        throw new RuntimeException("Bad meta-coding op "+(bytes[pos]&0xFF));
-    }
-
-    static final int SHORT_BAND_HEURISTIC = 100;
-
-    public static final int NO_PHASE        = 0;
-
-    // package writing phases:
-    public static final int COLLECT_PHASE   = 1; // collect data before write
-    public static final int FROZEN_PHASE    = 3; // no longer collecting
-    public static final int WRITE_PHASE     = 5; // ready to write bytes
-
-    // package reading phases:
-    public static final int EXPECT_PHASE    = 2; // gather expected counts
-    public static final int READ_PHASE      = 4; // ready to read bytes
-    public static final int DISBURSE_PHASE  = 6; // pass out data after read
-
-    public static final int DONE_PHASE      = 8; // done writing or reading
-
-    static boolean phaseIsRead(int p) {
-        return (p % 2) == 0;
-    }
-    static int phaseCmp(int p0, int p1) {
-        assert((p0 % 2) == (p1 % 2) || (p0 % 8) == 0 || (p1 % 8) == 0);
-        return p0 - p1;
-    }
-
-    /** The packed file is divided up into a number of segments.
-     *  Most segments are typed as ValueBand, strongly-typed sequences
-     *  of integer values, all interpreted in a single way.
-     *  A few segments are ByteBands, which hetergeneous sequences
-     *  of bytes.
-     *
-     *  The two phases for writing a packed file are COLLECT and WRITE.
-     *  1. When writing a packed file, each band collects
-     *  data in an ad-hoc order.
-     *  2. At the end, each band is assigned a coding scheme,
-     *  and then all the bands are written in their global order.
-     *
-     *  The three phases for reading a packed file are EXPECT, READ,
-     *  and DISBURSE.
-     *  1. For each band, the expected number of integers  is determined.
-     *  2. The data is actually read from the file into the band.
-     *  3. The band pays out its values as requested, in an ad hoc order.
-     *
-     *  When the last phase of a band is done, it is marked so (DONE).
-     *  Clearly, these phases must be properly ordered WRT each other.
-     */
-    abstract class Band {
-        private int    phase = NO_PHASE;
-        private final  String name;
-
-        private int    valuesExpected;
-
-        protected long outputSize = -1;  // cache
-
-        public final Coding regularCoding;
-
-        public final int seqForDebug;
-        public int       elementCountForDebug;
-
-
-        protected Band(String name, Coding regularCoding) {
-            this.name = name;
-            this.regularCoding = regularCoding;
-            this.seqForDebug = ++nextSeqForDebug;
-            if (verbose > 2)
-                Utils.log.fine("Band "+seqForDebug+" is "+name);
-            // caller must call init
-        }
-
-        public Band init() {
-            // Cannot due this from the constructor, because constructor
-            // may wish to initialize some subclass variables.
-            // Set initial phase for reading or writing:
-            if (isReader)
-                readyToExpect();
-            else
-                readyToCollect();
-            return this;
-        }
-
-        // common operations
-        boolean isReader() { return isReader; }
-        int phase() { return phase; }
-        String name() { return name; }
-
-        /** Return -1 if data buffer not allocated, else max length. */
-        public abstract int capacity();
-
-        /** Allocate data buffer to specified length. */
-        protected abstract void setCapacity(int cap);
-
-        /** Return current number of values in buffer, which must exist. */
-        public abstract int length();
-
-        protected abstract int valuesRemainingForDebug();
-
-        public final int valuesExpected() {
-            return valuesExpected;
-        }
-
-        /** Write out bytes, encoding the values. */
-        public final void writeTo(OutputStream out) throws IOException {
-            assert(assertReadyToWriteTo(this, out));
-            setPhase(WRITE_PHASE);
-            // subclasses continue by writing their contents to output
-            writeDataTo(out);
-            doneWriting();
-        }
-
-        abstract void chooseBandCodings() throws IOException;
-
-        public final long outputSize() {
-            if (outputSize >= 0) {
-                long size = outputSize;
-                assert(size == computeOutputSize());
-                return size;
-            }
-            return computeOutputSize();
-        }
-
-        protected abstract long computeOutputSize();
-
-        protected abstract void writeDataTo(OutputStream out) throws IOException;
-
-        /** Expect a certain number of values. */
-        void expectLength(int l) {
-            assert(assertPhase(this, EXPECT_PHASE));
-            assert(valuesExpected == 0);  // all at once
-            assert(l >= 0);
-            valuesExpected = l;
-        }
-        /** Expect more values.  (Multiple calls accumulate.) */
-        void expectMoreLength(int l) {
-            assert(assertPhase(this, EXPECT_PHASE));
-            valuesExpected += l;
-        }
-
-
-        /// Phase change markers.
-
-        private void readyToCollect() { // called implicitly by constructor
-            setCapacity(1);
-            setPhase(COLLECT_PHASE);
-        }
-        protected void doneWriting() {
-            assert(assertPhase(this, WRITE_PHASE));
-            setPhase(DONE_PHASE);
-        }
-        private void readyToExpect() { // called implicitly by constructor
-            setPhase(EXPECT_PHASE);
-        }
-        /** Read in bytes, decoding the values. */
-        public final void readFrom(InputStream in) throws IOException {
-            assert(assertReadyToReadFrom(this, in));
-            setCapacity(valuesExpected());
-            setPhase(READ_PHASE);
-            // subclasses continue by reading their contents from input:
-            readDataFrom(in);
-            readyToDisburse();
-        }
-        protected abstract void readDataFrom(InputStream in) throws IOException;
-        protected void readyToDisburse() {
-            if (verbose > 1)  Utils.log.fine("readyToDisburse "+this);
-            setPhase(DISBURSE_PHASE);
-        }
-        public void doneDisbursing() {
-            assert(assertPhase(this, DISBURSE_PHASE));
-            setPhase(DONE_PHASE);
-        }
-        public final void doneWithUnusedBand() {
-            if (isReader) {
-                assert(assertPhase(this, EXPECT_PHASE));
-                assert(valuesExpected() == 0);
-                // Fast forward:
-                setPhase(READ_PHASE);
-                setPhase(DISBURSE_PHASE);
-                setPhase(DONE_PHASE);
-            } else {
-                setPhase(FROZEN_PHASE);
-            }
-        }
-
-        protected void setPhase(int newPhase) {
-            assert(assertPhaseChangeOK(this, phase, newPhase));
-            this.phase = newPhase;
-        }
-
-        protected int lengthForDebug = -1;  // DEBUG ONLY
-        @Override
-        public String toString() {  // DEBUG ONLY
-            int length = (lengthForDebug != -1 ? lengthForDebug : length());
-            String str = name;
-            if (length != 0)
-                str += "[" + length + "]";
-            if (elementCountForDebug != 0)
-                str += "(" + elementCountForDebug + ")";
-            return str;
-        }
-    }
-
-    class ValueBand extends Band {
-        private int[]  values;   // must be null in EXPECT phase
-        private int    length;
-        private int    valuesDisbursed;
-
-        private CodingMethod bandCoding;
-        private byte[] metaCoding;
-
-        protected ValueBand(String name, Coding regularCoding) {
-            super(name, regularCoding);
-        }
-
-        @Override
-        public int capacity() {
-            return values == null ? -1 : values.length;
-        }
-
-        /** Declare predicted or needed capacity. */
-        @Override
-        protected void setCapacity(int cap) {
-            assert(length <= cap);
-            if (cap == -1) { values = null; return; }
-            values = realloc(values, cap);
-        }
-
-        @Override
-        public int length() {
-            return length;
-        }
-        @Override
-        protected int valuesRemainingForDebug() {
-            return length - valuesDisbursed;
-        }
-        protected int valueAtForDebug(int i) {
-            return values[i];
-        }
-
-        void patchValue(int i, int value) {
-            // Only one use for this.
-            assert(this == archive_header_S);
-            assert(i == AH_ARCHIVE_SIZE_HI || i == AH_ARCHIVE_SIZE_LO);
-            assert(i < length);  // must have already output a dummy
-            values[i] = value;
-            outputSize = -1;  // decache
-        }
-
-        protected void initializeValues(int[] values) {
-            assert(assertCanChangeLength(this));
-            assert(length == 0);
-            this.values = values;
-            this.length = values.length;
-        }
-
-        /** Collect one value, or store one decoded value. */
-        protected void addValue(int x) {
-            assert(assertCanChangeLength(this));
-            if (length == values.length)
-                setCapacity(length < 1000 ? length * 10 : length * 2);
-            values[length++] = x;
-        }
-
-        private boolean canVaryCoding() {
-            if (!optVaryCodings)           return false;
-            if (length == 0)               return false;
-            // Can't read band_headers w/o the archive header:
-            if (this == archive_header_0)  return false;
-            if (this == archive_header_S)  return false;
-            if (this == archive_header_1)  return false;
-            // BYTE1 bands can't vary codings, but the others can.
-            // All that's needed for the initial escape is at least
-            // 256 negative values or more than 256 non-negative values
-            return (regularCoding.min() <= -256 || regularCoding.max() >= 256);
-        }
-
-        private boolean shouldVaryCoding() {
-            assert(canVaryCoding());
-            if (effort < MAX_EFFORT && length < SHORT_BAND_HEURISTIC)
-                return false;
-            return true;
-        }
-
-        @Override
-        protected void chooseBandCodings() throws IOException {
-            boolean canVary = canVaryCoding();
-            if (!canVary || !shouldVaryCoding()) {
-                if (regularCoding.canRepresent(values, 0, length)) {
-                    bandCoding = regularCoding;
-                } else {
-                    assert(canVary);
-                    if (verbose > 1)
-                        Utils.log.fine("regular coding fails in band "+name());
-                    bandCoding = UNSIGNED5;
-                }
-                outputSize = -1;
-            } else {
-                int[] sizes = {0,0};
-                bandCoding = chooseCoding(values, 0, length,
-                                          regularCoding, name(),
-                                          sizes);
-                outputSize = sizes[CodingChooser.BYTE_SIZE];
-                if (outputSize == 0)  // CodingChooser failed to size it.
-                    outputSize = -1;
-            }
-
-            // Compute and save the meta-coding bytes also.
-            if (bandCoding != regularCoding) {
-                metaCoding = bandCoding.getMetaCoding(regularCoding);
-                if (verbose > 1) {
-                    Utils.log.fine("alternate coding "+this+" "+bandCoding);
-                }
-            } else if (canVary &&
-                       decodeEscapeValue(values[0], regularCoding) >= 0) {
-                // Need an explicit default.
-                metaCoding = defaultMetaCoding;
-            } else {
-                // Common case:  Zero bytes of meta coding.
-                metaCoding = noMetaCoding;
-            }
-            if (metaCoding.length > 0
-                && (verbose > 2 || verbose > 1 && metaCoding.length > 1)) {
-                StringBuilder sb = new StringBuilder();
-                for (int i = 0; i < metaCoding.length; i++) {
-                    if (i == 1)  sb.append(" /");
-                    sb.append(" ").append(metaCoding[i] & 0xFF);
-                }
-                Utils.log.fine("   meta-coding "+sb);
-            }
-
-            assert((outputSize < 0) ||
-                   !(bandCoding instanceof Coding) ||
-                   (outputSize == ((Coding)bandCoding)
-                    .getLength(values, 0, length)))
-                : (bandCoding+" : "+
-                   outputSize+" != "+
-                   ((Coding)bandCoding).getLength(values, 0, length)
-                   +" ?= "+getCodingChooser().computeByteSize(bandCoding,values,0,length)
-                   );
-
-            // Compute outputSize of the escape value X, if any.
-            if (metaCoding.length > 0) {
-                // First byte XB of meta-coding is treated specially,
-                // but any other bytes go into the band headers band.
-                // This must be done before any other output happens.
-                if (outputSize >= 0)
-                    outputSize += computeEscapeSize();  // good cache
-                // Other bytes go into band_headers.
-                for (int i = 1; i < metaCoding.length; i++) {
-                    band_headers.putByte(metaCoding[i] & 0xFF);
-                }
-            }
-        }
-
-        @Override
-        protected long computeOutputSize() {
-            outputSize = getCodingChooser().computeByteSize(bandCoding,
-                                                            values, 0, length);
-            assert(outputSize < Integer.MAX_VALUE);
-            outputSize += computeEscapeSize();
-            return outputSize;
-        }
-
-        protected int computeEscapeSize() {
-            if (metaCoding.length == 0)  return 0;
-            int XB = metaCoding[0] & 0xFF;
-            int X = encodeEscapeValue(XB, regularCoding);
-            return regularCoding.setD(0).getLength(X);
-        }
-
-        @Override
-        protected void writeDataTo(OutputStream out) throws IOException {
-            if (length == 0)  return;  // nothing to write
-            long len0 = 0;
-            if (out == outputCounter) {
-                len0 = outputCounter.getCount();
-            }
-            if (metaCoding.length > 0) {
-                int XB = metaCoding[0] & 0xFF;
-                // We need an explicit band header, either because
-                // there is a non-default coding method, or because
-                // the first value would be parsed as an escape value.
-                int X = encodeEscapeValue(XB, regularCoding);
-                //System.out.println("X="+X+" XB="+XB+" in "+this);
-                regularCoding.setD(0).writeTo(out, X);
-            }
-            bandCoding.writeArrayTo(out, values, 0, length);
-            if (out == outputCounter) {
-                assert(outputSize == outputCounter.getCount() - len0)
-                    : (outputSize+" != "+outputCounter.getCount()+"-"+len0);
-            }
-            if (optDumpBands)  dumpBand();
-        }
-
-        @Override
-        protected void readDataFrom(InputStream in) throws IOException {
-            length = valuesExpected();
-            if (length == 0)  return;  // nothing to read
-            if (verbose > 1)
-                Utils.log.fine("Reading band "+this);
-            if (!canVaryCoding()) {
-                bandCoding = regularCoding;
-                metaCoding = noMetaCoding;
-            } else {
-                assert(in.markSupported());  // input must be buffered
-                in.mark(Coding.B_MAX);
-                int X = regularCoding.setD(0).readFrom(in);
-                int XB = decodeEscapeValue(X, regularCoding);
-                if (XB < 0) {
-                    // Do not consume this value.  No alternate coding.
-                    in.reset();
-                    bandCoding = regularCoding;
-                    metaCoding = noMetaCoding;
-                } else if (XB == _meta_default) {
-                    bandCoding = regularCoding;
-                    metaCoding = defaultMetaCoding;
-                } else {
-                    if (verbose > 2)
-                        Utils.log.fine("found X="+X+" => XB="+XB);
-                    bandCoding = getBandHeader(XB, regularCoding);
-                    // This is really used only by dumpBands.
-                    int p0 = bandHeaderBytePos0;
-                    int p1 = bandHeaderBytePos;
-                    metaCoding = new byte[p1-p0];
-                    System.arraycopy(bandHeaderBytes, p0,
-                                     metaCoding, 0, metaCoding.length);
-                }
-            }
-            if (bandCoding != regularCoding) {
-                if (verbose > 1)
-                    Utils.log.fine(name()+": irregular coding "+bandCoding);
-            }
-            bandCoding.readArrayFrom(in, values, 0, length);
-            if (optDumpBands)  dumpBand();
-        }
-
-        @Override
-        public void doneDisbursing() {
-            super.doneDisbursing();
-            values = null;  // for GC
-        }
-
-        private void dumpBand() throws IOException {
-            assert(optDumpBands);
-            try (PrintStream ps = new PrintStream(getDumpStream(this, ".txt"))) {
-                String irr = (bandCoding == regularCoding) ? "" : " irregular";
-                ps.print("# length="+length+
-                         " size="+outputSize()+
-                         irr+" coding="+bandCoding);
-                if (metaCoding != noMetaCoding) {
-                    StringBuilder sb = new StringBuilder();
-                    for (int i = 0; i < metaCoding.length; i++) {
-                        if (i == 1)  sb.append(" /");
-                        sb.append(" ").append(metaCoding[i] & 0xFF);
-                    }
-                    ps.print(" //header: "+sb);
-                }
-                printArrayTo(ps, values, 0, length);
-            }
-            try (OutputStream ds = getDumpStream(this, ".bnd")) {
-                bandCoding.writeArrayTo(ds, values, 0, length);
-            }
-        }
-
-        /** Disburse one value. */
-        protected int getValue() {
-            assert(phase() == DISBURSE_PHASE);
-            // when debugging return a zero if lengths are zero
-            if (optDebugBands && length == 0 && valuesDisbursed == length)
-                return 0;
-            assert(valuesDisbursed <= length);
-            return values[valuesDisbursed++];
-        }
-
-        /** Reset for another pass over the same value set. */
-        public void resetForSecondPass() {
-            assert(phase() == DISBURSE_PHASE);
-            assert(valuesDisbursed == length());  // 1st pass is complete
-            valuesDisbursed = 0;
-        }
-    }
-
-    class ByteBand extends Band {
-        private ByteArrayOutputStream bytes;  // input buffer
-        private ByteArrayOutputStream bytesForDump;
-        private InputStream in;
-
-        public ByteBand(String name) {
-            super(name, BYTE1);
-        }
-
-        @Override
-        public int capacity() {
-            return bytes == null ? -1 : Integer.MAX_VALUE;
-        }
-        @Override
-        protected void setCapacity(int cap) {
-            assert(bytes == null);  // do this just once
-            bytes = new ByteArrayOutputStream(cap);
-        }
-        public void destroy() {
-            lengthForDebug = length();
-            bytes = null;
-        }
-
-        @Override
-        public int length() {
-            return bytes == null ? -1 : bytes.size();
-        }
-        public void reset() {
-            bytes.reset();
-        }
-        @Override
-        protected int valuesRemainingForDebug() {
-            return (bytes == null) ? -1 : ((ByteArrayInputStream)in).available();
-        }
-
-        @Override
-        protected void chooseBandCodings() throws IOException {
-            // No-op.
-            assert(decodeEscapeValue(regularCoding.min(), regularCoding) < 0);
-            assert(decodeEscapeValue(regularCoding.max(), regularCoding) < 0);
-        }
-
-        @Override
-        protected long computeOutputSize() {
-            // do not cache
-            return bytes.size();
-        }
-
-        @Override
-        public void writeDataTo(OutputStream out) throws IOException {
-            if (length() == 0)  return;
-            bytes.writeTo(out);
-            if (optDumpBands)  dumpBand();
-            destroy();  // done with the bits!
-        }
-
-        private void dumpBand() throws IOException {
-            assert(optDumpBands);
-            try (OutputStream ds = getDumpStream(this, ".bnd")) {
-                if (bytesForDump != null)
-                    bytesForDump.writeTo(ds);
-                else
-                    bytes.writeTo(ds);
-            }
-        }
-
-        @Override
-        public void readDataFrom(InputStream in) throws IOException {
-            int vex = valuesExpected();
-            if (vex == 0)  return;
-            if (verbose > 1) {
-                lengthForDebug = vex;
-                Utils.log.fine("Reading band "+this);
-                lengthForDebug = -1;
-            }
-            byte[] buf = new byte[Math.min(vex, 1<<14)];
-            while (vex > 0) {
-                int nr = in.read(buf, 0, Math.min(vex, buf.length));
-                if (nr < 0)  throw new EOFException();
-                bytes.write(buf, 0, nr);
-                vex -= nr;
-            }
-            if (optDumpBands)  dumpBand();
-        }
-
-        @Override
-        public void readyToDisburse() {
-            in = new ByteArrayInputStream(bytes.toByteArray());
-            super.readyToDisburse();
-        }
-
-        @Override
-        public void doneDisbursing() {
-            super.doneDisbursing();
-            if (optDumpBands
-                && bytesForDump != null && bytesForDump.size() > 0) {
-                try {
-                    dumpBand();
-                } catch (IOException ee) {
-                    throw new RuntimeException(ee);
-                }
-            }
-            in = null; // GC
-            bytes = null;  // GC
-            bytesForDump = null;  // GC
-        }
-
-        // alternative to readFrom:
-        public void setInputStreamFrom(InputStream in) throws IOException {
-            assert(bytes == null);
-            assert(assertReadyToReadFrom(this, in));
-            setPhase(READ_PHASE);
-            this.in = in;
-            if (optDumpBands) {
-                // Tap the stream.
-                bytesForDump = new ByteArrayOutputStream();
-                this.in = new FilterInputStream(in) {
-                    @Override
-                    public int read() throws IOException {
-                        int ch = in.read();
-                        if (ch >= 0)  bytesForDump.write(ch);
-                        return ch;
-                    }
-                    @Override
-                    public int read(byte b[], int off, int len) throws IOException {
-                        int nr = in.read(b, off, len);
-                        if (nr >= 0)  bytesForDump.write(b, off, nr);
-                        return nr;
-                    }
-                };
-            }
-            super.readyToDisburse();
-        }
-
-        public OutputStream collectorStream() {
-            assert(phase() == COLLECT_PHASE);
-            assert(bytes != null);
-            return bytes;
-        }
-
-        public InputStream getInputStream() {
-            assert(phase() == DISBURSE_PHASE);
-            assert(in != null);
-            return in;
-        }
-        public int getByte() throws IOException {
-            int b = getInputStream().read();
-            if (b < 0)  throw new EOFException();
-            return b;
-        }
-        public void putByte(int b) throws IOException {
-            assert(b == (b & 0xFF));
-            collectorStream().write(b);
-        }
-        @Override
-        public String toString() {
-            return "byte "+super.toString();
-        }
-    }
-
-    class IntBand extends ValueBand {
-        // The usual coding for bands is 7bit/5byte/delta.
-        public IntBand(String name, Coding regularCoding) {
-            super(name, regularCoding);
-        }
-
-        public void putInt(int x) {
-            assert(phase() == COLLECT_PHASE);
-            addValue(x);
-        }
-
-        public int getInt() {
-            return getValue();
-        }
-        /** Return the sum of all values in this band. */
-        public int getIntTotal() {
-            assert(phase() == DISBURSE_PHASE);
-            // assert that this is the whole pass; no other reads allowed
-            assert(valuesRemainingForDebug() == length());
-            int total = 0;
-            for (int k = length(); k > 0; k--) {
-                total += getInt();
-            }
-            resetForSecondPass();
-            return total;
-        }
-        /** Return the occurrence count of a specific value in this band. */
-        public int getIntCount(int value) {
-            assert(phase() == DISBURSE_PHASE);
-            // assert that this is the whole pass; no other reads allowed
-            assert(valuesRemainingForDebug() == length());
-            int total = 0;
-            for (int k = length(); k > 0; k--) {
-                if (getInt() == value) {
-                    total += 1;
-                }
-            }
-            resetForSecondPass();
-            return total;
-        }
-    }
-
-    static int getIntTotal(int[] values) {
-        int total = 0;
-        for (int i = 0; i < values.length; i++) {
-            total += values[i];
-        }
-        return total;
-    }
-
-    class CPRefBand extends ValueBand {
-        Index index;
-        boolean nullOK;
-
-        public CPRefBand(String name, Coding regularCoding, byte cpTag, boolean nullOK) {
-            super(name, regularCoding);
-            this.nullOK = nullOK;
-            if (cpTag != CONSTANT_None)
-                setBandIndex(this, cpTag);
-        }
-        public CPRefBand(String name, Coding regularCoding, byte cpTag) {
-            this(name, regularCoding, cpTag, false);
-        }
-        public CPRefBand(String name, Coding regularCoding, Object undef) {
-            this(name, regularCoding, CONSTANT_None, false);
-        }
-
-        public void setIndex(Index index) {
-            this.index = index;
-        }
-
-        protected void readDataFrom(InputStream in) throws IOException {
-            super.readDataFrom(in);
-            assert(assertValidCPRefs(this));
-        }
-
-        /** Write a constant pool reference. */
-        public void putRef(Entry e) {
-            addValue(encodeRefOrNull(e, index));
-        }
-        public void putRef(Entry e, Index index) {
-            assert(this.index == null);
-            addValue(encodeRefOrNull(e, index));
-        }
-        public void putRef(Entry e, byte cptag) {
-            putRef(e, getCPIndex(cptag));
-        }
-
-        public Entry getRef() {
-            if (index == null)  Utils.log.warning("No index for "+this);
-            assert(index != null);
-            return decodeRefOrNull(getValue(), index);
-        }
-        public Entry getRef(Index index) {
-            assert(this.index == null);
-            return decodeRefOrNull(getValue(), index);
-        }
-        public Entry getRef(byte cptag) {
-            return getRef(getCPIndex(cptag));
-        }
-
-        private int encodeRefOrNull(Entry e, Index index) {
-            int nonNullCode;  // NNC is the coding which assumes nulls are rare
-            if (e == null) {
-                nonNullCode = -1;  // negative values are rare
-            } else {
-                nonNullCode = encodeRef(e, index);
-            }
-            // If nulls are expected, increment, to make -1 code turn to 0.
-            return (nullOK ? 1 : 0) + nonNullCode;
-        }
-        private Entry decodeRefOrNull(int code, Index index) {
-            // Inverse to encodeRefOrNull...
-            int nonNullCode = code - (nullOK ? 1 : 0);
-            if (nonNullCode == -1) {
-                return null;
-            } else {
-                return decodeRef(nonNullCode, index);
-            }
-        }
-    }
-
-    // Bootstrap support for CPRefBands.  These are needed to record
-    // intended CP indexes, before the CP has been created.
-    private final List<CPRefBand> allKQBands = new ArrayList<>();
-    private List<Object[]> needPredefIndex = new ArrayList<>();
-
-
-    int encodeRef(Entry e, Index ix) {
-        if (ix == null)
-            throw new RuntimeException("null index for " + e.stringValue());
-        int coding = ix.indexOf(e);
-        if (verbose > 2)
-            Utils.log.fine("putRef "+coding+" => "+e);
-        return coding;
-    }
-
-    Entry decodeRef(int n, Index ix) {
-        if (n < 0 || n >= ix.size())
-            Utils.log.warning("decoding bad ref "+n+" in "+ix);
-        Entry e = ix.getEntry(n);
-        if (verbose > 2)
-            Utils.log.fine("getRef "+n+" => "+e);
-        return e;
-    }
-
-    private CodingChooser codingChooser;
-    protected CodingChooser getCodingChooser() {
-        if (codingChooser == null) {
-            codingChooser = new CodingChooser(effort, basicCodings);
-            if (codingChooser.stress != null
-                && this instanceof PackageWriter) {
-                // Twist the random state based on my first file.
-                // This sends each segment off in a different direction.
-                List<Package.Class> classes = ((PackageWriter)this).pkg.classes;
-                if (!classes.isEmpty()) {
-                    Package.Class cls = classes.get(0);
-                    codingChooser.addStressSeed(cls.getName().hashCode());
-                }
-            }
-        }
-        return codingChooser;
-    }
-
-    public CodingMethod chooseCoding(int[] values, int start, int end,
-                                     Coding regular, String bandName,
-                                     int[] sizes) {
-        assert(optVaryCodings);
-        if (effort <= MIN_EFFORT) {
-            return regular;
-        }
-        CodingChooser cc = getCodingChooser();
-        if (verbose > 1 || cc.verbose > 1) {
-            Utils.log.fine("--- chooseCoding "+bandName);
-        }
-        return cc.choose(values, start, end, regular, sizes);
-    }
-
-    static final byte[] defaultMetaCoding = { _meta_default };
-    static final byte[] noMetaCoding      = {};
-
-    // The first value in a band is always coded with the default coding D.
-    // If this first value X is an escape value, it actually represents the
-    // first (and perhaps only) byte of a meta-coding.
-    //
-    // If D.S != 0 and D includes the range [-256..-1],
-    // the escape values are in that range,
-    // and the first byte XB is -1-X.
-    //
-    // If D.S == 0 and D includes the range [(D.L)..(D.L)+255],
-    // the escape values are in that range,
-    // and XB is X-(D.L).
-    //
-    // This representation is designed so that a band header is unlikely
-    // to be confused with the initial value of a headerless band,
-    // and yet so that a band header is likely to occupy only a byte or two.
-    //
-    // Result is in [0..255] if XB was successfully extracted, else -1.
-    // See section "Coding Specifier Meta-Encoding" in the JSR 200 spec.
-    protected static int decodeEscapeValue(int X, Coding regularCoding) {
-        // The first value in a band is always coded with the default coding D.
-        // If this first value X is an escape value, it actually represents the
-        // first (and perhaps only) byte of a meta-coding.
-        // Result is in [0..255] if XB was successfully extracted, else -1.
-        if (regularCoding.B() == 1 || regularCoding.L() == 0)
-            return -1;  // degenerate regular coding (BYTE1)
-        if (regularCoding.S() != 0) {
-            if (-256 <= X && X <= -1 && regularCoding.min() <= -256) {
-                int XB = -1-X;
-                assert(XB >= 0 && XB < 256);
-                return XB;
-            }
-        } else {
-            int L = regularCoding.L();
-            if (L <= X && X <= L+255 && regularCoding.max() >= L+255) {
-                int XB = X-L;
-                assert(XB >= 0 && XB < 256);
-                return XB;
-            }
-        }
-        return -1;  // negative value for failure
-    }
-    // Inverse to decodeEscapeValue().
-    protected static int encodeEscapeValue(int XB, Coding regularCoding) {
-        assert(XB >= 0 && XB < 256);
-        assert(regularCoding.B() > 1 && regularCoding.L() > 0);
-        int X;
-        if (regularCoding.S() != 0) {
-            assert(regularCoding.min() <= -256);
-            X = -1-XB;
-        } else {
-            int L = regularCoding.L();
-            assert(regularCoding.max() >= L+255);
-            X = XB+L;
-        }
-        assert(decodeEscapeValue(X, regularCoding) == XB)
-            : (regularCoding+" XB="+XB+" X="+X);
-        return X;
-    }
-
-    static {
-        boolean checkXB = false;
-        assert(checkXB = true);
-        if (checkXB) {
-            for (int i = 0; i < basicCodings.length; i++) {
-                Coding D = basicCodings[i];
-                if (D == null)   continue;
-                if (D.B() == 1)  continue;
-                if (D.L() == 0)  continue;
-                for (int XB = 0; XB <= 255; XB++) {
-                    // The following exercises decodeEscapeValue also:
-                    encodeEscapeValue(XB, D);
-                }
-            }
-        }
-    }
-
-    class MultiBand extends Band {
-        MultiBand(String name, Coding regularCoding) {
-            super(name, regularCoding);
-        }
-
-        @Override
-        public Band init() {
-            super.init();
-            // This is all just to keep the asserts happy:
-            setCapacity(0);
-            if (phase() == EXPECT_PHASE) {
-                // Fast forward:
-                setPhase(READ_PHASE);
-                setPhase(DISBURSE_PHASE);
-            }
-            return this;
-        }
-
-        Band[] bands     = new Band[10];
-        int    bandCount = 0;
-
-        int size() {
-            return bandCount;
-        }
-        Band get(int i) {
-            assert(i < bandCount);
-            return bands[i];
-        }
-        Band[] toArray() {
-            return (Band[]) realloc(bands, bandCount);
-        }
-
-        void add(Band b) {
-            assert(bandCount == 0 || notePrevForAssert(b, bands[bandCount-1]));
-            if (bandCount == bands.length) {
-                bands = (Band[]) realloc(bands);
-            }
-            bands[bandCount++] = b;
-        }
-
-        ByteBand newByteBand(String name) {
-            ByteBand b = new ByteBand(name);
-            b.init(); add(b);
-            return b;
-        }
-        IntBand newIntBand(String name) {
-            IntBand b = new IntBand(name, regularCoding);
-            b.init(); add(b);
-            return b;
-        }
-        IntBand newIntBand(String name, Coding regularCoding) {
-            IntBand b = new IntBand(name, regularCoding);
-            b.init(); add(b);
-            return b;
-        }
-        MultiBand newMultiBand(String name, Coding regularCoding) {
-            MultiBand b = new MultiBand(name, regularCoding);
-            b.init(); add(b);
-            return b;
-        }
-        CPRefBand newCPRefBand(String name, byte cpTag) {
-            CPRefBand b = new CPRefBand(name, regularCoding, cpTag);
-            b.init(); add(b);
-            return b;
-        }
-        CPRefBand newCPRefBand(String name, Coding regularCoding,
-                               byte cpTag) {
-            CPRefBand b = new CPRefBand(name, regularCoding, cpTag);
-            b.init(); add(b);
-            return b;
-        }
-        CPRefBand newCPRefBand(String name, Coding regularCoding,
-                               byte cpTag, boolean nullOK) {
-            CPRefBand b = new CPRefBand(name, regularCoding, cpTag, nullOK);
-            b.init(); add(b);
-            return b;
-        }
-
-        int bandCount() { return bandCount; }
-
-        private int cap = -1;
-        @Override
-        public int capacity() { return cap; }
-        @Override
-        public void setCapacity(int cap) { this.cap = cap; }
-
-        @Override
-        public int length() { return 0; }
-        @Override
-        public int valuesRemainingForDebug() { return 0; }
-
-        @Override
-        protected void chooseBandCodings() throws IOException {
-            // coding decision pass
-            for (int i = 0; i < bandCount; i++) {
-                Band b = bands[i];
-                b.chooseBandCodings();
-            }
-        }
-
-        @Override
-        protected long computeOutputSize() {
-            // coding decision pass
-            long sum = 0;
-            for (int i = 0; i < bandCount; i++) {
-                Band b = bands[i];
-                long bsize = b.outputSize();
-                assert(bsize >= 0) : b;
-                sum += bsize;
-            }
-            // do not cache
-            return sum;
-        }
-
-        @Override
-        protected void writeDataTo(OutputStream out) throws IOException {
-            long preCount = 0;
-            if (outputCounter != null)  preCount = outputCounter.getCount();
-            for (int i = 0; i < bandCount; i++) {
-                Band b = bands[i];
-                b.writeTo(out);
-                if (outputCounter != null) {
-                    long postCount = outputCounter.getCount();
-                    long len = postCount - preCount;
-                    preCount = postCount;
-                    if ((verbose > 0 && len > 0) || verbose > 1) {
-                        Utils.log.info("  ...wrote "+len+" bytes from "+b);
-                    }
-                }
-            }
-        }
-
-        @Override
-        protected void readDataFrom(InputStream in) throws IOException {
-            assert(false);  // not called?
-            for (int i = 0; i < bandCount; i++) {
-                Band b = bands[i];
-                b.readFrom(in);
-                if ((verbose > 0 && b.length() > 0) || verbose > 1) {
-                    Utils.log.info("  ...read "+b);
-                }
-            }
-        }
-
-        @Override
-        public String toString() {
-            return "{"+bandCount()+" bands: "+super.toString()+"}";
-        }
-    }
-
-    /**
-     * An output stream which counts the number of bytes written.
-     */
-    private static
-    class ByteCounter extends FilterOutputStream {
-        // (should go public under the name CountingOutputStream?)
-
-        private long count;
-
-        public ByteCounter(OutputStream out) {
-            super(out);
-        }
-
-        public long getCount() { return count; }
-        public void setCount(long c) { count = c; }
-
-        @Override
-        public void write(int b) throws IOException {
-            count++;
-            if (out != null)  out.write(b);
-        }
-        @Override
-        public void write(byte b[], int off, int len) throws IOException {
-            count += len;
-            if (out != null)  out.write(b, off, len);
-        }
-        @Override
-        public String toString() {
-            return String.valueOf(getCount());
-        }
-    }
-    ByteCounter outputCounter;
-
-    void writeAllBandsTo(OutputStream out) throws IOException {
-        // Wrap a byte-counter around the output stream.
-        outputCounter = new ByteCounter(out);
-        out = outputCounter;
-        all_bands.writeTo(out);
-        if (verbose > 0) {
-            long nbytes = outputCounter.getCount();
-            Utils.log.info("Wrote total of "+nbytes+" bytes.");
-            assert(nbytes == archiveSize0+archiveSize1);
-        }
-        outputCounter = null;
-    }
-
-    // random AO_XXX bits, decoded from the archive header
-    protected int archiveOptions;
-
-    // archiveSize1 sizes most of the archive [archive_options..file_bits).
-    protected long archiveSize0; // size through archive_size_lo
-    protected long archiveSize1; // size reported in archive_header
-    protected int  archiveNextCount; // reported in archive_header
-
-    static final int AH_LENGTH_0 = 3;     // archive_header_0 = {minver, majver, options}
-    static final int AH_LENGTH_MIN = 15;  // observed in spec {header_0[3], cp_counts[8], class_counts[4]}
-    // Length contributions from optional archive size fields:
-    static final int AH_LENGTH_S = 2; // archive_header_S = optional {size_hi, size_lo}
-    static final int AH_ARCHIVE_SIZE_HI = 0; // offset in archive_header_S
-    static final int AH_ARCHIVE_SIZE_LO = 1; // offset in archive_header_S
-    // Length contributions from optional header fields:
-    static final int AH_FILE_HEADER_LEN = 5; // file_counts = {{size_hi, size_lo}, next, modtime, files}
-    static final int AH_SPECIAL_FORMAT_LEN = 2; // special_counts = {layouts, band_headers}
-    static final int AH_CP_NUMBER_LEN = 4;  // cp_number_counts = {int, float, long, double}
-    static final int AH_CP_EXTRA_LEN = 4;  // cp_attr_counts = {MH, MT, InDy, BSM}
-
-    // Common structure of attribute band groups:
-    static final int AB_FLAGS_HI = 0;
-    static final int AB_FLAGS_LO = 1;
-    static final int AB_ATTR_COUNT = 2;
-    static final int AB_ATTR_INDEXES = 3;
-    static final int AB_ATTR_CALLS = 4;
-
-    static IntBand getAttrBand(MultiBand xxx_attr_bands, int which) {
-        IntBand b = (IntBand) xxx_attr_bands.get(which);
-        switch (which) {
-        case AB_FLAGS_HI:
-            assert(b.name().endsWith("_flags_hi")); break;
-        case AB_FLAGS_LO:
-            assert(b.name().endsWith("_flags_lo")); break;
-        case AB_ATTR_COUNT:
-            assert(b.name().endsWith("_attr_count")); break;
-        case AB_ATTR_INDEXES:
-            assert(b.name().endsWith("_attr_indexes")); break;
-        case AB_ATTR_CALLS:
-            assert(b.name().endsWith("_attr_calls")); break;
-        default:
-            assert(false); break;
-        }
-        return b;
-    }
-
-    private static final boolean NULL_IS_OK = true;
-
-    MultiBand all_bands = (MultiBand) new MultiBand("(package)", UNSIGNED5).init();
-
-    // file header (various random bytes)
-    ByteBand archive_magic = all_bands.newByteBand("archive_magic");
-    IntBand  archive_header_0 = all_bands.newIntBand("archive_header_0", UNSIGNED5);
-    IntBand  archive_header_S = all_bands.newIntBand("archive_header_S", UNSIGNED5);
-    IntBand  archive_header_1 = all_bands.newIntBand("archive_header_1", UNSIGNED5);
-    ByteBand band_headers = all_bands.newByteBand("band_headers");
-
-    // constant pool contents
-    MultiBand cp_bands = all_bands.newMultiBand("(constant_pool)", DELTA5);
-    IntBand   cp_Utf8_prefix = cp_bands.newIntBand("cp_Utf8_prefix");
-    IntBand   cp_Utf8_suffix = cp_bands.newIntBand("cp_Utf8_suffix", UNSIGNED5);
-    IntBand   cp_Utf8_chars = cp_bands.newIntBand("cp_Utf8_chars", CHAR3);
-    IntBand   cp_Utf8_big_suffix = cp_bands.newIntBand("cp_Utf8_big_suffix");
-    MultiBand cp_Utf8_big_chars = cp_bands.newMultiBand("(cp_Utf8_big_chars)", DELTA5);
-    IntBand   cp_Int = cp_bands.newIntBand("cp_Int", UDELTA5);
-    IntBand   cp_Float = cp_bands.newIntBand("cp_Float", UDELTA5);
-    IntBand   cp_Long_hi = cp_bands.newIntBand("cp_Long_hi", UDELTA5);
-    IntBand   cp_Long_lo = cp_bands.newIntBand("cp_Long_lo");
-    IntBand   cp_Double_hi = cp_bands.newIntBand("cp_Double_hi", UDELTA5);
-    IntBand   cp_Double_lo = cp_bands.newIntBand("cp_Double_lo");
-    CPRefBand cp_String = cp_bands.newCPRefBand("cp_String", UDELTA5, CONSTANT_Utf8);
-    CPRefBand cp_Class = cp_bands.newCPRefBand("cp_Class", UDELTA5, CONSTANT_Utf8);
-    CPRefBand cp_Signature_form = cp_bands.newCPRefBand("cp_Signature_form", CONSTANT_Utf8);
-    CPRefBand cp_Signature_classes = cp_bands.newCPRefBand("cp_Signature_classes", UDELTA5, CONSTANT_Class);
-    CPRefBand cp_Descr_name = cp_bands.newCPRefBand("cp_Descr_name", CONSTANT_Utf8);
-    CPRefBand cp_Descr_type = cp_bands.newCPRefBand("cp_Descr_type", UDELTA5, CONSTANT_Signature);
-    CPRefBand cp_Field_class = cp_bands.newCPRefBand("cp_Field_class", CONSTANT_Class);
-    CPRefBand cp_Field_desc = cp_bands.newCPRefBand("cp_Field_desc", UDELTA5, CONSTANT_NameandType);
-    CPRefBand cp_Method_class = cp_bands.newCPRefBand("cp_Method_class", CONSTANT_Class);
-    CPRefBand cp_Method_desc = cp_bands.newCPRefBand("cp_Method_desc", UDELTA5, CONSTANT_NameandType);
-    CPRefBand cp_Imethod_class = cp_bands.newCPRefBand("cp_Imethod_class", CONSTANT_Class);
-    CPRefBand cp_Imethod_desc = cp_bands.newCPRefBand("cp_Imethod_desc", UDELTA5, CONSTANT_NameandType);
-    IntBand   cp_MethodHandle_refkind = cp_bands.newIntBand("cp_MethodHandle_refkind", DELTA5);
-    CPRefBand cp_MethodHandle_member = cp_bands.newCPRefBand("cp_MethodHandle_member", UDELTA5, CONSTANT_AnyMember);
-    CPRefBand cp_MethodType = cp_bands.newCPRefBand("cp_MethodType", UDELTA5, CONSTANT_Signature);
-    CPRefBand cp_BootstrapMethod_ref = cp_bands.newCPRefBand("cp_BootstrapMethod_ref", DELTA5, CONSTANT_MethodHandle);
-    IntBand   cp_BootstrapMethod_arg_count = cp_bands.newIntBand("cp_BootstrapMethod_arg_count", UDELTA5);
-    CPRefBand cp_BootstrapMethod_arg = cp_bands.newCPRefBand("cp_BootstrapMethod_arg", DELTA5, CONSTANT_LoadableValue);
-    CPRefBand cp_InvokeDynamic_spec = cp_bands.newCPRefBand("cp_InvokeDynamic_spec", DELTA5, CONSTANT_BootstrapMethod);
-    CPRefBand cp_InvokeDynamic_desc = cp_bands.newCPRefBand("cp_InvokeDynamic_desc", UDELTA5, CONSTANT_NameandType);
-
-    // bands for carrying attribute definitions:
-    MultiBand attr_definition_bands = all_bands.newMultiBand("(attr_definition_bands)", UNSIGNED5);
-    ByteBand attr_definition_headers = attr_definition_bands.newByteBand("attr_definition_headers");
-    CPRefBand attr_definition_name = attr_definition_bands.newCPRefBand("attr_definition_name", CONSTANT_Utf8);
-    CPRefBand attr_definition_layout = attr_definition_bands.newCPRefBand("attr_definition_layout", CONSTANT_Utf8);
-
-    // bands for hardwired InnerClasses attribute (shared across the package)
-    MultiBand ic_bands = all_bands.newMultiBand("(ic_bands)", DELTA5);
-    CPRefBand ic_this_class = ic_bands.newCPRefBand("ic_this_class", UDELTA5, CONSTANT_Class);
-    IntBand ic_flags = ic_bands.newIntBand("ic_flags", UNSIGNED5);
-    // These bands contain data only where flags sets ACC_IC_LONG_FORM:
-    CPRefBand ic_outer_class = ic_bands.newCPRefBand("ic_outer_class", DELTA5, CONSTANT_Class, NULL_IS_OK);
-    CPRefBand ic_name = ic_bands.newCPRefBand("ic_name", DELTA5, CONSTANT_Utf8, NULL_IS_OK);
-
-    // bands for carrying class schema information:
-    MultiBand class_bands = all_bands.newMultiBand("(class_bands)", DELTA5);
-    CPRefBand class_this = class_bands.newCPRefBand("class_this", CONSTANT_Class);
-    CPRefBand class_super = class_bands.newCPRefBand("class_super", CONSTANT_Class);
-    IntBand   class_interface_count = class_bands.newIntBand("class_interface_count");
-    CPRefBand class_interface = class_bands.newCPRefBand("class_interface", CONSTANT_Class);
-
-    // bands for class members
-    IntBand   class_field_count = class_bands.newIntBand("class_field_count");
-    IntBand   class_method_count = class_bands.newIntBand("class_method_count");
-
-    CPRefBand field_descr = class_bands.newCPRefBand("field_descr", CONSTANT_NameandType);
-    MultiBand field_attr_bands = class_bands.newMultiBand("(field_attr_bands)", UNSIGNED5);
-    IntBand field_flags_hi = field_attr_bands.newIntBand("field_flags_hi");
-    IntBand field_flags_lo = field_attr_bands.newIntBand("field_flags_lo");
-    IntBand field_attr_count = field_attr_bands.newIntBand("field_attr_count");
-    IntBand field_attr_indexes = field_attr_bands.newIntBand("field_attr_indexes");
-    IntBand field_attr_calls = field_attr_bands.newIntBand("field_attr_calls");
-
-    // bands for predefined field attributes
-    CPRefBand field_ConstantValue_KQ = field_attr_bands.newCPRefBand("field_ConstantValue_KQ", CONSTANT_FieldSpecific);
-    CPRefBand field_Signature_RS = field_attr_bands.newCPRefBand("field_Signature_RS", CONSTANT_Signature);
-    MultiBand field_metadata_bands = field_attr_bands.newMultiBand("(field_metadata_bands)", UNSIGNED5);
-    MultiBand field_type_metadata_bands = field_attr_bands.newMultiBand("(field_type_metadata_bands)", UNSIGNED5);
-
-    CPRefBand method_descr = class_bands.newCPRefBand("method_descr", MDELTA5, CONSTANT_NameandType);
-    MultiBand method_attr_bands = class_bands.newMultiBand("(method_attr_bands)", UNSIGNED5);
-    IntBand  method_flags_hi = method_attr_bands.newIntBand("method_flags_hi");
-    IntBand  method_flags_lo = method_attr_bands.newIntBand("method_flags_lo");
-    IntBand  method_attr_count = method_attr_bands.newIntBand("method_attr_count");
-    IntBand  method_attr_indexes = method_attr_bands.newIntBand("method_attr_indexes");
-    IntBand  method_attr_calls = method_attr_bands.newIntBand("method_attr_calls");
-    // band for predefined method attributes
-    IntBand  method_Exceptions_N = method_attr_bands.newIntBand("method_Exceptions_N");
-    CPRefBand method_Exceptions_RC = method_attr_bands.newCPRefBand("method_Exceptions_RC", CONSTANT_Class);
-    CPRefBand method_Signature_RS = method_attr_bands.newCPRefBand("method_Signature_RS", CONSTANT_Signature);
-    MultiBand method_metadata_bands = method_attr_bands.newMultiBand("(method_metadata_bands)", UNSIGNED5);
-    // band for predefine method parameters
-    IntBand  method_MethodParameters_NB = method_attr_bands.newIntBand("method_MethodParameters_NB", BYTE1);
-    CPRefBand method_MethodParameters_name_RUN = method_attr_bands.newCPRefBand("method_MethodParameters_name_RUN", UNSIGNED5, CONSTANT_Utf8, NULL_IS_OK);
-    IntBand   method_MethodParameters_flag_FH = method_attr_bands.newIntBand("method_MethodParameters_flag_FH");
-    MultiBand method_type_metadata_bands = method_attr_bands.newMultiBand("(method_type_metadata_bands)", UNSIGNED5);
-
-    MultiBand class_attr_bands = class_bands.newMultiBand("(class_attr_bands)", UNSIGNED5);
-    IntBand class_flags_hi = class_attr_bands.newIntBand("class_flags_hi");
-    IntBand class_flags_lo = class_attr_bands.newIntBand("class_flags_lo");
-    IntBand class_attr_count = class_attr_bands.newIntBand("class_attr_count");
-    IntBand class_attr_indexes = class_attr_bands.newIntBand("class_attr_indexes");
-    IntBand class_attr_calls = class_attr_bands.newIntBand("class_attr_calls");
-    // band for predefined SourceFile and other class attributes
-    CPRefBand class_SourceFile_RUN = class_attr_bands.newCPRefBand("class_SourceFile_RUN", UNSIGNED5, CONSTANT_Utf8, NULL_IS_OK);
-    CPRefBand class_EnclosingMethod_RC = class_attr_bands.newCPRefBand("class_EnclosingMethod_RC", CONSTANT_Class);
-    CPRefBand class_EnclosingMethod_RDN = class_attr_bands.newCPRefBand("class_EnclosingMethod_RDN", UNSIGNED5, CONSTANT_NameandType, NULL_IS_OK);
-    CPRefBand class_Signature_RS = class_attr_bands.newCPRefBand("class_Signature_RS", CONSTANT_Signature);
-    MultiBand class_metadata_bands = class_attr_bands.newMultiBand("(class_metadata_bands)", UNSIGNED5);
-    IntBand   class_InnerClasses_N = class_attr_bands.newIntBand("class_InnerClasses_N");
-    CPRefBand class_InnerClasses_RC = class_attr_bands.newCPRefBand("class_InnerClasses_RC", CONSTANT_Class);
-    IntBand   class_InnerClasses_F = class_attr_bands.newIntBand("class_InnerClasses_F");
-    CPRefBand class_InnerClasses_outer_RCN = class_attr_bands.newCPRefBand("class_InnerClasses_outer_RCN", UNSIGNED5, CONSTANT_Class, NULL_IS_OK);
-    CPRefBand class_InnerClasses_name_RUN = class_attr_bands.newCPRefBand("class_InnerClasses_name_RUN", UNSIGNED5, CONSTANT_Utf8, NULL_IS_OK);
-    IntBand class_ClassFile_version_minor_H = class_attr_bands.newIntBand("class_ClassFile_version_minor_H");
-    IntBand class_ClassFile_version_major_H = class_attr_bands.newIntBand("class_ClassFile_version_major_H");
-    MultiBand class_type_metadata_bands = class_attr_bands.newMultiBand("(class_type_metadata_bands)", UNSIGNED5);
-
-    MultiBand code_bands = class_bands.newMultiBand("(code_bands)", UNSIGNED5);
-    ByteBand  code_headers = code_bands.newByteBand("code_headers"); //BYTE1
-    IntBand   code_max_stack = code_bands.newIntBand("code_max_stack", UNSIGNED5);
-    IntBand   code_max_na_locals = code_bands.newIntBand("code_max_na_locals", UNSIGNED5);
-    IntBand   code_handler_count = code_bands.newIntBand("code_handler_count", UNSIGNED5);
-    IntBand   code_handler_start_P = code_bands.newIntBand("code_handler_start_P", BCI5);
-    IntBand   code_handler_end_PO = code_bands.newIntBand("code_handler_end_PO", BRANCH5);
-    IntBand   code_handler_catch_PO = code_bands.newIntBand("code_handler_catch_PO", BRANCH5);
-    CPRefBand code_handler_class_RCN = code_bands.newCPRefBand("code_handler_class_RCN", UNSIGNED5, CONSTANT_Class, NULL_IS_OK);
-
-    MultiBand code_attr_bands = class_bands.newMultiBand("(code_attr_bands)", UNSIGNED5);
-    IntBand   code_flags_hi = code_attr_bands.newIntBand("code_flags_hi");
-    IntBand   code_flags_lo = code_attr_bands.newIntBand("code_flags_lo");
-    IntBand   code_attr_count = code_attr_bands.newIntBand("code_attr_count");
-    IntBand   code_attr_indexes = code_attr_bands.newIntBand("code_attr_indexes");
-    IntBand   code_attr_calls = code_attr_bands.newIntBand("code_attr_calls");
-
-    MultiBand stackmap_bands = code_attr_bands.newMultiBand("(StackMapTable_bands)", UNSIGNED5);
-    IntBand   code_StackMapTable_N = stackmap_bands.newIntBand("code_StackMapTable_N");
-    IntBand   code_StackMapTable_frame_T = stackmap_bands.newIntBand("code_StackMapTable_frame_T",BYTE1);
-    IntBand   code_StackMapTable_local_N = stackmap_bands.newIntBand("code_StackMapTable_local_N");
-    IntBand   code_StackMapTable_stack_N = stackmap_bands.newIntBand("code_StackMapTable_stack_N");
-    IntBand   code_StackMapTable_offset = stackmap_bands.newIntBand("code_StackMapTable_offset", UNSIGNED5);
-    IntBand   code_StackMapTable_T = stackmap_bands.newIntBand("code_StackMapTable_T", BYTE1);
-    CPRefBand code_StackMapTable_RC = stackmap_bands.newCPRefBand("code_StackMapTable_RC", CONSTANT_Class);
-    IntBand   code_StackMapTable_P = stackmap_bands.newIntBand("code_StackMapTable_P", BCI5);
-
-    // bands for predefined LineNumberTable attribute
-    IntBand   code_LineNumberTable_N = code_attr_bands.newIntBand("code_LineNumberTable_N");
-    IntBand   code_LineNumberTable_bci_P = code_attr_bands.newIntBand("code_LineNumberTable_bci_P", BCI5);
-    IntBand   code_LineNumberTable_line = code_attr_bands.newIntBand("code_LineNumberTable_line");
-
-    // bands for predefined LocalVariable{Type}Table attributes
-    IntBand   code_LocalVariableTable_N = code_attr_bands.newIntBand("code_LocalVariableTable_N");
-    IntBand   code_LocalVariableTable_bci_P = code_attr_bands.newIntBand("code_LocalVariableTable_bci_P", BCI5);
-    IntBand   code_LocalVariableTable_span_O = code_attr_bands.newIntBand("code_LocalVariableTable_span_O", BRANCH5);
-    CPRefBand code_LocalVariableTable_name_RU = code_attr_bands.newCPRefBand("code_LocalVariableTable_name_RU", CONSTANT_Utf8);
-    CPRefBand code_LocalVariableTable_type_RS = code_attr_bands.newCPRefBand("code_LocalVariableTable_type_RS", CONSTANT_Signature);
-    IntBand   code_LocalVariableTable_slot = code_attr_bands.newIntBand("code_LocalVariableTable_slot");
-    IntBand   code_LocalVariableTypeTable_N = code_attr_bands.newIntBand("code_LocalVariableTypeTable_N");
-    IntBand   code_LocalVariableTypeTable_bci_P = code_attr_bands.newIntBand("code_LocalVariableTypeTable_bci_P", BCI5);
-    IntBand   code_LocalVariableTypeTable_span_O = code_attr_bands.newIntBand("code_LocalVariableTypeTable_span_O", BRANCH5);
-    CPRefBand code_LocalVariableTypeTable_name_RU = code_attr_bands.newCPRefBand("code_LocalVariableTypeTable_name_RU", CONSTANT_Utf8);
-    CPRefBand code_LocalVariableTypeTable_type_RS = code_attr_bands.newCPRefBand("code_LocalVariableTypeTable_type_RS", CONSTANT_Signature);
-    IntBand   code_LocalVariableTypeTable_slot = code_attr_bands.newIntBand("code_LocalVariableTypeTable_slot");
-    MultiBand code_type_metadata_bands = code_attr_bands.newMultiBand("(code_type_metadata_bands)", UNSIGNED5);
-
-    // bands for bytecodes
-    MultiBand bc_bands = all_bands.newMultiBand("(byte_codes)", UNSIGNED5);
-    ByteBand  bc_codes = bc_bands.newByteBand("bc_codes"); //BYTE1
-    // remaining bands provide typed opcode fields required by the bc_codes
-
-    IntBand   bc_case_count = bc_bands.newIntBand("bc_case_count");  // *switch
-    IntBand   bc_case_value = bc_bands.newIntBand("bc_case_value", DELTA5);  // *switch
-    ByteBand  bc_byte = bc_bands.newByteBand("bc_byte"); //BYTE1   // bipush, iinc, *newarray
-    IntBand   bc_short = bc_bands.newIntBand("bc_short", DELTA5);  // sipush, wide iinc
-    IntBand   bc_local = bc_bands.newIntBand("bc_local");    // *load, *store, iinc, ret
-    IntBand   bc_label = bc_bands.newIntBand("bc_label", BRANCH5);    // if*, goto*, jsr*, *switch
-
-    // Most CP refs exhibit some correlation, and benefit from delta coding.
-    // The notable exceptions are class and method references.
-
-    // ldc* operands:
-    CPRefBand bc_intref = bc_bands.newCPRefBand("bc_intref", DELTA5, CONSTANT_Integer);
-    CPRefBand bc_floatref = bc_bands.newCPRefBand("bc_floatref", DELTA5, CONSTANT_Float);
-    CPRefBand bc_longref = bc_bands.newCPRefBand("bc_longref", DELTA5, CONSTANT_Long);
-    CPRefBand bc_doubleref = bc_bands.newCPRefBand("bc_doubleref", DELTA5, CONSTANT_Double);
-    CPRefBand bc_stringref = bc_bands.newCPRefBand("bc_stringref", DELTA5, CONSTANT_String);
-    CPRefBand bc_loadablevalueref = bc_bands.newCPRefBand("bc_loadablevalueref", DELTA5, CONSTANT_LoadableValue);
-
-    // nulls produced by bc_classref are taken to mean the current class
-    CPRefBand bc_classref = bc_bands.newCPRefBand("bc_classref", UNSIGNED5, CONSTANT_Class, NULL_IS_OK);   // new, *anew*, c*cast, i*of, ldc
-    CPRefBand bc_fieldref = bc_bands.newCPRefBand("bc_fieldref", DELTA5, CONSTANT_Fieldref);   // get*, put*
-    CPRefBand bc_methodref = bc_bands.newCPRefBand("bc_methodref", CONSTANT_Methodref); // invoke[vs]*
-    CPRefBand bc_imethodref = bc_bands.newCPRefBand("bc_imethodref", DELTA5, CONSTANT_InterfaceMethodref); // invokeinterface
-    CPRefBand bc_indyref = bc_bands.newCPRefBand("bc_indyref", DELTA5, CONSTANT_InvokeDynamic); // invokedynamic
-
-    // _self_linker_op family
-    CPRefBand bc_thisfield = bc_bands.newCPRefBand("bc_thisfield", CONSTANT_None);     // any field within cur. class
-    CPRefBand bc_superfield = bc_bands.newCPRefBand("bc_superfield", CONSTANT_None);   // any field within superclass
-    CPRefBand bc_thismethod = bc_bands.newCPRefBand("bc_thismethod", CONSTANT_None);   // any method within cur. class
-    CPRefBand bc_supermethod = bc_bands.newCPRefBand("bc_supermethod", CONSTANT_None); // any method within superclass
-    // bc_invokeinit family:
-    IntBand   bc_initref = bc_bands.newIntBand("bc_initref");
-    // escapes
-    CPRefBand bc_escref = bc_bands.newCPRefBand("bc_escref", CONSTANT_All);
-    IntBand   bc_escrefsize = bc_bands.newIntBand("bc_escrefsize");
-    IntBand   bc_escsize = bc_bands.newIntBand("bc_escsize");
-    ByteBand  bc_escbyte = bc_bands.newByteBand("bc_escbyte");
-
-    // bands for carrying resource files and file attributes:
-    MultiBand file_bands = all_bands.newMultiBand("(file_bands)", UNSIGNED5);
-    CPRefBand file_name = file_bands.newCPRefBand("file_name", CONSTANT_Utf8);
-    IntBand file_size_hi = file_bands.newIntBand("file_size_hi");
-    IntBand file_size_lo = file_bands.newIntBand("file_size_lo");
-    IntBand file_modtime = file_bands.newIntBand("file_modtime", DELTA5);
-    IntBand file_options = file_bands.newIntBand("file_options");
-    ByteBand file_bits = file_bands.newByteBand("file_bits");
-
-    // End of band definitions!
-
-    /** Given CP indexes, distribute tag-specific indexes to bands. */
-    protected void setBandIndexes() {
-        // Handle prior calls to setBandIndex:
-        for (Object[] need : needPredefIndex) {
-            CPRefBand b     = (CPRefBand) need[0];
-            Byte      which = (Byte)      need[1];
-            b.setIndex(getCPIndex(which.byteValue()));
-        }
-        needPredefIndex = null;  // no more predefs
-
-        if (verbose > 3) {
-            printCDecl(all_bands);
-        }
-    }
-
-    protected void setBandIndex(CPRefBand b, byte which) {
-        Object[] need = { b, Byte.valueOf(which) };
-        if (which == CONSTANT_FieldSpecific) {
-            // I.e., attribute layouts KQ (no null) or KQN (null ok).
-            allKQBands.add(b);
-        } else if (needPredefIndex != null) {
-            needPredefIndex.add(need);
-        } else {
-            // Not in predefinition mode; getCPIndex now works.
-            b.setIndex(getCPIndex(which));
-        }
-    }
-
-    protected void setConstantValueIndex(Field f) {
-        Index ix = null;
-        if (f != null) {
-            byte tag = f.getLiteralTag();
-            ix = getCPIndex(tag);
-            if (verbose > 2)
-                Utils.log.fine("setConstantValueIndex "+f+" "+ConstantPool.tagName(tag)+" => "+ix);
-            assert(ix != null);
-        }
-        // Typically, allKQBands is the singleton of field_ConstantValue_KQ.
-        for (CPRefBand xxx_KQ : allKQBands) {
-            xxx_KQ.setIndex(ix);
-        }
-    }
-
-    // Table of bands which contain metadata.
-    protected MultiBand[] metadataBands = new MultiBand[ATTR_CONTEXT_LIMIT];
-    {
-        metadataBands[ATTR_CONTEXT_CLASS] = class_metadata_bands;
-        metadataBands[ATTR_CONTEXT_FIELD] = field_metadata_bands;
-        metadataBands[ATTR_CONTEXT_METHOD] = method_metadata_bands;
-    }
-    // Table of bands which contains type_metadata (TypeAnnotations)
-    protected MultiBand[] typeMetadataBands = new MultiBand[ATTR_CONTEXT_LIMIT];
-    {
-        typeMetadataBands[ATTR_CONTEXT_CLASS] = class_type_metadata_bands;
-        typeMetadataBands[ATTR_CONTEXT_FIELD] = field_type_metadata_bands;
-        typeMetadataBands[ATTR_CONTEXT_METHOD] = method_type_metadata_bands;
-        typeMetadataBands[ATTR_CONTEXT_CODE]   = code_type_metadata_bands;
-    }
-
-    // Attribute layouts.
-    public static final int ADH_CONTEXT_MASK   = 0x3;  // (ad_hdr & ADH_CONTEXT_MASK)
-    public static final int ADH_BIT_SHIFT      = 0x2;  // (ad_hdr >> ADH_BIT_SHIFT)
-    public static final int ADH_BIT_IS_LSB     = 1;
-    public static final int ATTR_INDEX_OVERFLOW  = -1;
-
-    public int[] attrIndexLimit = new int[ATTR_CONTEXT_LIMIT];
-    // Each index limit is either 32 or 63, depending on AO_HAVE_XXX_FLAGS_HI.
-
-    // Which flag bits are taken over by attributes?
-    protected long[] attrFlagMask = new long[ATTR_CONTEXT_LIMIT];
-    // Which flag bits have been taken over explicitly?
-    protected long[] attrDefSeen = new long[ATTR_CONTEXT_LIMIT];
-
-    // What pseudo-attribute bits are there to watch for?
-    protected int[] attrOverflowMask = new int[ATTR_CONTEXT_LIMIT];
-    protected int attrClassFileVersionMask;
-
-    // Mapping from Attribute.Layout to Band[] (layout element bands).
-    protected Map<Attribute.Layout, Band[]> attrBandTable = new HashMap<>();
-
-    // Well-known attributes:
-    protected final Attribute.Layout attrCodeEmpty;
-    protected final Attribute.Layout attrInnerClassesEmpty;
-    protected final Attribute.Layout attrClassFileVersion;
-    protected final Attribute.Layout attrConstantValue;
-
-    // Mapping from Attribute.Layout to Integer (inverse of attrDefs)
-    Map<Attribute.Layout, Integer> attrIndexTable = new HashMap<>();
-
-    // Mapping from attribute index (<32 are flag bits) to attributes.
-    protected List<List<Attribute.Layout>> attrDefs =
-            new FixedList<>(ATTR_CONTEXT_LIMIT);
-    {
-        for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
-            assert(attrIndexLimit[i] == 0);
-            attrIndexLimit[i] = 32;  // just for the sake of predefs.
-            attrDefs.set(i, new ArrayList<>(Collections.nCopies(
-                    attrIndexLimit[i], (Attribute.Layout)null)));
-
-        }
-
-        // Add predefined attribute definitions:
-        attrInnerClassesEmpty =
-        predefineAttribute(CLASS_ATTR_InnerClasses, ATTR_CONTEXT_CLASS, null,
-                           "InnerClasses", "");
-        assert(attrInnerClassesEmpty == Package.attrInnerClassesEmpty);
-        predefineAttribute(CLASS_ATTR_SourceFile, ATTR_CONTEXT_CLASS,
-                           new Band[] { class_SourceFile_RUN },
-                           "SourceFile", "RUNH");
-        predefineAttribute(CLASS_ATTR_EnclosingMethod, ATTR_CONTEXT_CLASS,
-                           new Band[] {
-                               class_EnclosingMethod_RC,
-                               class_EnclosingMethod_RDN
-                           },
-                           "EnclosingMethod", "RCHRDNH");
-        attrClassFileVersion =
-        predefineAttribute(CLASS_ATTR_ClassFile_version, ATTR_CONTEXT_CLASS,
-                           new Band[] {
-                               class_ClassFile_version_minor_H,
-                               class_ClassFile_version_major_H
-                           },
-                           ".ClassFile.version", "HH");
-        predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_CLASS,
-                           new Band[] { class_Signature_RS },
-                           "Signature", "RSH");
-        predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_CLASS, null,
-                           "Deprecated", "");
-        //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_CLASS, null,
-        //                 "Synthetic", "");
-        predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_CLASS, null,
-                           ".Overflow", "");
-        attrConstantValue =
-        predefineAttribute(FIELD_ATTR_ConstantValue, ATTR_CONTEXT_FIELD,
-                           new Band[] { field_ConstantValue_KQ },
-                           "ConstantValue", "KQH");
-        predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_FIELD,
-                           new Band[] { field_Signature_RS },
-                           "Signature", "RSH");
-        predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_FIELD, null,
-                           "Deprecated", "");
-        //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_FIELD, null,
-        //                 "Synthetic", "");
-        predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_FIELD, null,
-                           ".Overflow", "");
-        attrCodeEmpty =
-        predefineAttribute(METHOD_ATTR_Code, ATTR_CONTEXT_METHOD, null,
-                           "Code", "");
-        predefineAttribute(METHOD_ATTR_Exceptions, ATTR_CONTEXT_METHOD,
-                           new Band[] {
-                               method_Exceptions_N,
-                               method_Exceptions_RC
-                           },
-                           "Exceptions", "NH[RCH]");
-        predefineAttribute(METHOD_ATTR_MethodParameters, ATTR_CONTEXT_METHOD,
-                           new Band[]{
-                                method_MethodParameters_NB,
-                                method_MethodParameters_name_RUN,
-                                method_MethodParameters_flag_FH
-                           },
-                           "MethodParameters", "NB[RUNHFH]");
-        assert(attrCodeEmpty == Package.attrCodeEmpty);
-        predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_METHOD,
-                           new Band[] { method_Signature_RS },
-                           "Signature", "RSH");
-        predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_METHOD, null,
-                           "Deprecated", "");
-        //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_METHOD, null,
-        //                 "Synthetic", "");
-        predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_METHOD, null,
-                           ".Overflow", "");
-
-        for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) {
-            MultiBand xxx_metadata_bands = metadataBands[ctype];
-            if (ctype != ATTR_CONTEXT_CODE) {
-                // These arguments cause the bands to be built
-                // automatically for this complicated layout:
-                predefineAttribute(X_ATTR_RuntimeVisibleAnnotations,
-                                   ATTR_CONTEXT_NAME[ctype]+"_RVA_",
-                                   xxx_metadata_bands,
-                                   Attribute.lookup(null, ctype,
-                                                    "RuntimeVisibleAnnotations"));
-                predefineAttribute(X_ATTR_RuntimeInvisibleAnnotations,
-                                   ATTR_CONTEXT_NAME[ctype]+"_RIA_",
-                                   xxx_metadata_bands,
-                                   Attribute.lookup(null, ctype,
-                                                    "RuntimeInvisibleAnnotations"));
-
-                if (ctype == ATTR_CONTEXT_METHOD) {
-                    predefineAttribute(METHOD_ATTR_RuntimeVisibleParameterAnnotations,
-                                       "method_RVPA_", xxx_metadata_bands,
-                                       Attribute.lookup(null, ctype,
-                                       "RuntimeVisibleParameterAnnotations"));
-                    predefineAttribute(METHOD_ATTR_RuntimeInvisibleParameterAnnotations,
-                                       "method_RIPA_", xxx_metadata_bands,
-                                       Attribute.lookup(null, ctype,
-                                       "RuntimeInvisibleParameterAnnotations"));
-                    predefineAttribute(METHOD_ATTR_AnnotationDefault,
-                                       "method_AD_", xxx_metadata_bands,
-                                       Attribute.lookup(null, ctype,
-                                       "AnnotationDefault"));
-                }
-            }
-            // All contexts have these
-            MultiBand xxx_type_metadata_bands = typeMetadataBands[ctype];
-            predefineAttribute(X_ATTR_RuntimeVisibleTypeAnnotations,
-                    ATTR_CONTEXT_NAME[ctype] + "_RVTA_",
-                    xxx_type_metadata_bands,
-                    Attribute.lookup(null, ctype,
-                    "RuntimeVisibleTypeAnnotations"));
-            predefineAttribute(X_ATTR_RuntimeInvisibleTypeAnnotations,
-                    ATTR_CONTEXT_NAME[ctype] + "_RITA_",
-                    xxx_type_metadata_bands,
-                    Attribute.lookup(null, ctype,
-                    "RuntimeInvisibleTypeAnnotations"));
-        }
-
-
-        Attribute.Layout stackMapDef = Attribute.lookup(null, ATTR_CONTEXT_CODE, "StackMapTable").layout();
-        predefineAttribute(CODE_ATTR_StackMapTable, ATTR_CONTEXT_CODE,
-                           stackmap_bands.toArray(),
-                           stackMapDef.name(), stackMapDef.layout());
-
-        predefineAttribute(CODE_ATTR_LineNumberTable, ATTR_CONTEXT_CODE,
-                           new Band[] {
-                               code_LineNumberTable_N,
-                               code_LineNumberTable_bci_P,
-                               code_LineNumberTable_line
-                           },
-                           "LineNumberTable", "NH[PHH]");
-        predefineAttribute(CODE_ATTR_LocalVariableTable, ATTR_CONTEXT_CODE,
-                           new Band[] {
-                               code_LocalVariableTable_N,
-                               code_LocalVariableTable_bci_P,
-                               code_LocalVariableTable_span_O,
-                               code_LocalVariableTable_name_RU,
-                               code_LocalVariableTable_type_RS,
-                               code_LocalVariableTable_slot
-                           },
-                           "LocalVariableTable", "NH[PHOHRUHRSHH]");
-        predefineAttribute(CODE_ATTR_LocalVariableTypeTable, ATTR_CONTEXT_CODE,
-                           new Band[] {
-                               code_LocalVariableTypeTable_N,
-                               code_LocalVariableTypeTable_bci_P,
-                               code_LocalVariableTypeTable_span_O,
-                               code_LocalVariableTypeTable_name_RU,
-                               code_LocalVariableTypeTable_type_RS,
-                               code_LocalVariableTypeTable_slot
-                           },
-                           "LocalVariableTypeTable", "NH[PHOHRUHRSHH]");
-        predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_CODE, null,
-                           ".Overflow", "");
-
-        // Clear the record of having seen these definitions,
-        // so they may be redefined without error.
-        for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
-            attrDefSeen[i] = 0;
-        }
-
-        // Set up the special masks:
-        for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
-            attrOverflowMask[i] = (1<<X_ATTR_OVERFLOW);
-            attrIndexLimit[i] = 0;  // will make a final decision later
-        }
-        attrClassFileVersionMask = (1<<CLASS_ATTR_ClassFile_version);
-    }
-
-    private void adjustToClassVersion() throws IOException {
-        if (getHighestClassVersion().lessThan(JAVA6_MAX_CLASS_VERSION)) {
-            if (verbose > 0)  Utils.log.fine("Legacy package version");
-            // Revoke definition of pre-1.6 attribute type.
-            undefineAttribute(CODE_ATTR_StackMapTable, ATTR_CONTEXT_CODE);
-        }
-    }
-
-    protected void initAttrIndexLimit() {
-        for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
-            assert(attrIndexLimit[i] == 0);  // decide on it now!
-            attrIndexLimit[i] = (haveFlagsHi(i)? 63: 32);
-            List<Attribute.Layout> defList = attrDefs.get(i);
-            assert(defList.size() == 32);  // all predef indexes are <32
-            int addMore = attrIndexLimit[i] - defList.size();
-            defList.addAll(Collections.nCopies(addMore, (Attribute.Layout) null));
-        }
-    }
-
-    protected boolean haveFlagsHi(int ctype) {
-        int mask = 1<<(LG_AO_HAVE_XXX_FLAGS_HI+ctype);
-        switch (ctype) {
-        case ATTR_CONTEXT_CLASS:
-            assert(mask == AO_HAVE_CLASS_FLAGS_HI); break;
-        case ATTR_CONTEXT_FIELD:
-            assert(mask == AO_HAVE_FIELD_FLAGS_HI); break;
-        case ATTR_CONTEXT_METHOD:
-            assert(mask == AO_HAVE_METHOD_FLAGS_HI); break;
-        case ATTR_CONTEXT_CODE:
-            assert(mask == AO_HAVE_CODE_FLAGS_HI); break;
-        default:
-            assert(false);
-        }
-        return testBit(archiveOptions, mask);
-    }
-
-    protected List<Attribute.Layout> getPredefinedAttrs(int ctype) {
-        assert(attrIndexLimit[ctype] != 0);
-        List<Attribute.Layout> res = new ArrayList<>(attrIndexLimit[ctype]);
-        // Remove nulls and non-predefs.
-        for (int ai = 0; ai < attrIndexLimit[ctype]; ai++) {
-            if (testBit(attrDefSeen[ctype], 1L<<ai))  continue;
-            Attribute.Layout def = attrDefs.get(ctype).get(ai);
-            if (def == null)  continue;  // unused flag bit
-            assert(isPredefinedAttr(ctype, ai));
-            res.add(def);
-        }
-        return res;
-    }
-
-    protected boolean isPredefinedAttr(int ctype, int ai) {
-        assert(attrIndexLimit[ctype] != 0);
-        // Overflow attrs are never predefined.
-        if (ai >= attrIndexLimit[ctype])          return false;
-        // If the bit is set, it was explicitly def'd.
-        if (testBit(attrDefSeen[ctype], 1L<<ai))  return false;
-        return (attrDefs.get(ctype).get(ai) != null);
-    }
-
-    protected void adjustSpecialAttrMasks() {
-        // Clear special masks if new definitions have been seen for them.
-        attrClassFileVersionMask &= ~ attrDefSeen[ATTR_CONTEXT_CLASS];
-        // It is possible to clear the overflow mask (bit 16).
-        for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
-            attrOverflowMask[i] &= ~ attrDefSeen[i];
-        }
-    }
-
-    protected Attribute makeClassFileVersionAttr(Package.Version ver) {
-        return attrClassFileVersion.addContent(ver.asBytes());
-    }
-
-    protected Package.Version parseClassFileVersionAttr(Attribute attr) {
-        assert(attr.layout() == attrClassFileVersion);
-        assert(attr.size() == 4);
-        return Package.Version.of(attr.bytes());
-    }
-
-    private boolean assertBandOKForElems(Band[] ab, Attribute.Layout.Element[] elems) {
-        for (int i = 0; i < elems.length; i++) {
-            assert(assertBandOKForElem(ab, elems[i]));
-        }
-        return true;
-    }
-    private boolean assertBandOKForElem(Band[] ab, Attribute.Layout.Element e) {
-        Band b = null;
-        if (e.bandIndex != Attribute.NO_BAND_INDEX)
-            b = ab[e.bandIndex];
-        Coding rc = UNSIGNED5;
-        boolean wantIntBand = true;
-        switch (e.kind) {
-        case Attribute.EK_INT:
-            if (e.flagTest(Attribute.EF_SIGN)) {
-                rc = SIGNED5;
-            } else if (e.len == 1) {
-                rc = BYTE1;
-            }
-            break;
-        case Attribute.EK_BCI:
-            if (!e.flagTest(Attribute.EF_DELTA)) {
-                rc = BCI5;
-            } else {
-                rc = BRANCH5;
-            }
-            break;
-        case Attribute.EK_BCO:
-            rc = BRANCH5;
-            break;
-        case Attribute.EK_FLAG:
-            if (e.len == 1)  rc = BYTE1;
-            break;
-        case Attribute.EK_REPL:
-            if (e.len == 1)  rc = BYTE1;
-            assertBandOKForElems(ab, e.body);
-            break;
-        case Attribute.EK_UN:
-            if (e.flagTest(Attribute.EF_SIGN)) {
-                rc = SIGNED5;
-            } else if (e.len == 1) {
-                rc = BYTE1;
-            }
-            assertBandOKForElems(ab, e.body);
-            break;
-        case Attribute.EK_CASE:
-            assert(b == null);
-            assertBandOKForElems(ab, e.body);
-            return true;  // no direct band
-        case Attribute.EK_CALL:
-            assert(b == null);
-            return true;  // no direct band
-        case Attribute.EK_CBLE:
-            assert(b == null);
-            assertBandOKForElems(ab, e.body);
-            return true;  // no direct band
-        case Attribute.EK_REF:
-            wantIntBand = false;
-            assert(b instanceof CPRefBand);
-            assert(((CPRefBand)b).nullOK == e.flagTest(Attribute.EF_NULL));
-            break;
-        default: assert(false);
-        }
-        assert(b.regularCoding == rc)
-            : (e+" // "+b);
-        if (wantIntBand)
-            assert(b instanceof IntBand);
-        return true;
-    }
-
-    private
-    Attribute.Layout predefineAttribute(int index, int ctype, Band[] ab,
-                                        String name, String layout) {
-        // Use Attribute.find to get uniquification of layouts.
-        Attribute.Layout def = Attribute.find(ctype, name, layout).layout();
-        //def.predef = true;
-        if (index >= 0) {
-            setAttributeLayoutIndex(def, index);
-        }
-        if (ab == null) {
-            ab = new Band[0];
-        }
-        assert(attrBandTable.get(def) == null);  // no redef
-        attrBandTable.put(def, ab);
-        assert(def.bandCount == ab.length)
-            : (def+" // "+Arrays.asList(ab));
-        // Let's make sure the band types match:
-        assert(assertBandOKForElems(ab, def.elems));
-        return def;
-    }
-
-    // This version takes bandPrefix/addHere instead of prebuilt Band[] ab.
-    private
-    Attribute.Layout predefineAttribute(int index,
-                                        String bandPrefix, MultiBand addHere,
-                                        Attribute attr) {
-        //Attribute.Layout def = Attribute.find(ctype, name, layout).layout();
-        Attribute.Layout def = attr.layout();
-        int ctype = def.ctype();
-        return predefineAttribute(index, ctype,
-                                  makeNewAttributeBands(bandPrefix, def, addHere),
-                                  def.name(), def.layout());
-    }
-
-    private
-    void undefineAttribute(int index, int ctype) {
-        if (verbose > 1) {
-            System.out.println("Removing predefined "+ATTR_CONTEXT_NAME[ctype]+
-                               " attribute on bit "+index);
-        }
-        List<Attribute.Layout> defList = attrDefs.get(ctype);
-        Attribute.Layout def = defList.get(index);
-        assert(def != null);
-        defList.set(index, null);
-        attrIndexTable.put(def, null);
-        // Clear the def bit.  (For predefs, it's already clear.)
-        assert(index < 64);
-        attrDefSeen[ctype]  &= ~(1L<<index);
-        attrFlagMask[ctype] &= ~(1L<<index);
-        Band[] ab = attrBandTable.get(def);
-        for (int j = 0; j < ab.length; j++) {
-            ab[j].doneWithUnusedBand();
-        }
-    }
-
-    // Bands which contain non-predefined attrs.
-    protected MultiBand[] attrBands = new MultiBand[ATTR_CONTEXT_LIMIT];
-    {
-        attrBands[ATTR_CONTEXT_CLASS] = class_attr_bands;
-        attrBands[ATTR_CONTEXT_FIELD] = field_attr_bands;
-        attrBands[ATTR_CONTEXT_METHOD] = method_attr_bands;
-        attrBands[ATTR_CONTEXT_CODE] = code_attr_bands;
-    }
-
-    // Create bands for all non-predefined attrs.
-    void makeNewAttributeBands() {
-        // Retract special flag bit bindings, if they were taken over.
-        adjustSpecialAttrMasks();
-
-        for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) {
-            String cname = ATTR_CONTEXT_NAME[ctype];
-            MultiBand xxx_attr_bands = attrBands[ctype];
-            long defSeen = attrDefSeen[ctype];
-            // Note: attrDefSeen is always a subset of attrFlagMask.
-            assert((defSeen & ~attrFlagMask[ctype]) == 0);
-            for (int i = 0; i < attrDefs.get(ctype).size(); i++) {
-                Attribute.Layout def = attrDefs.get(ctype).get(i);
-                if (def == null)  continue;  // unused flag bit
-                if (def.bandCount == 0)  continue;  // empty attr
-                if (i < attrIndexLimit[ctype] && !testBit(defSeen, 1L<<i)) {
-                    // There are already predefined bands here.
-                    assert(attrBandTable.get(def) != null);
-                    continue;
-                }
-                int base = xxx_attr_bands.size();
-                String pfx = cname+"_"+def.name()+"_";  // debug only
-                if (verbose > 1)
-                    Utils.log.fine("Making new bands for "+def);
-                Band[] newAB  = makeNewAttributeBands(pfx, def,
-                                                      xxx_attr_bands);
-                assert(newAB.length == def.bandCount);
-                Band[] prevAB = attrBandTable.put(def, newAB);
-                if (prevAB != null) {
-                    // We won't be using these predefined bands.
-                    for (int j = 0; j < prevAB.length; j++) {
-                        prevAB[j].doneWithUnusedBand();
-                    }
-                }
-            }
-        }
-        //System.out.println(prevForAssertMap);
-    }
-    private
-    Band[] makeNewAttributeBands(String pfx, Attribute.Layout def,
-                                 MultiBand addHere) {
-        int base = addHere.size();
-        makeNewAttributeBands(pfx, def.elems, addHere);
-        int nb = addHere.size() - base;
-        Band[] newAB = new Band[nb];
-        for (int i = 0; i < nb; i++) {
-            newAB[i] = addHere.get(base+i);
-        }
-        return newAB;
-    }
-    // Recursive helper, operates on a "body" or other sequence of elems:
-    private
-    void makeNewAttributeBands(String pfx, Attribute.Layout.Element[] elems,
-                               MultiBand ab) {
-        for (int i = 0; i < elems.length; i++) {
-            Attribute.Layout.Element e = elems[i];
-            String name = pfx+ab.size()+"_"+e.layout;
-            {
-                int tem;
-                if ((tem = name.indexOf('[')) > 0)
-                    name = name.substring(0, tem);
-                if ((tem = name.indexOf('(')) > 0)
-                    name = name.substring(0, tem);
-                if (name.endsWith("H"))
-                    name = name.substring(0, name.length()-1);
-            }
-            Band nb;
-            switch (e.kind) {
-            case Attribute.EK_INT:
-                nb = newElemBand(e, name, ab);
-                break;
-            case Attribute.EK_BCI:
-                if (!e.flagTest(Attribute.EF_DELTA)) {
-                    // PH:  transmit R(bci), store bci
-                    nb = ab.newIntBand(name, BCI5);
-                } else {
-                    // POH:  transmit D(R(bci)), store bci
-                    nb = ab.newIntBand(name, BRANCH5);
-                }
-                // Note:  No case for BYTE1 here.
-                break;
-            case Attribute.EK_BCO:
-                // OH:  transmit D(R(bci)), store D(bci)
-                nb = ab.newIntBand(name, BRANCH5);
-                // Note:  No case for BYTE1 here.
-                break;
-            case Attribute.EK_FLAG:
-                assert(!e.flagTest(Attribute.EF_SIGN));
-                nb = newElemBand(e, name, ab);
-                break;
-            case Attribute.EK_REPL:
-                assert(!e.flagTest(Attribute.EF_SIGN));
-                nb = newElemBand(e, name, ab);
-                makeNewAttributeBands(pfx, e.body, ab);
-                break;
-            case Attribute.EK_UN:
-                nb = newElemBand(e, name, ab);
-                makeNewAttributeBands(pfx, e.body, ab);
-                break;
-            case Attribute.EK_CASE:
-                if (!e.flagTest(Attribute.EF_BACK)) {
-                    // If it's not a duplicate body, make the bands.
-                    makeNewAttributeBands(pfx, e.body, ab);
-                }
-                continue;  // no new band to make
-            case Attribute.EK_REF:
-                byte    refKind = e.refKind;
-                boolean nullOK  = e.flagTest(Attribute.EF_NULL);
-                nb = ab.newCPRefBand(name, UNSIGNED5, refKind, nullOK);
-                // Note:  No case for BYTE1 here.
-                break;
-            case Attribute.EK_CALL:
-                continue;  // no new band to make
-            case Attribute.EK_CBLE:
-                makeNewAttributeBands(pfx, e.body, ab);
-                continue;  // no new band to make
-            default: assert(false); continue;
-            }
-            if (verbose > 1) {
-                Utils.log.fine("New attribute band "+nb);
-            }
-        }
-    }
-    private
-    Band newElemBand(Attribute.Layout.Element e, String name, MultiBand ab) {
-        if (e.flagTest(Attribute.EF_SIGN)) {
-            return ab.newIntBand(name, SIGNED5);
-        } else if (e.len == 1) {
-            return ab.newIntBand(name, BYTE1);  // Not ByteBand, please.
-        } else {
-            return ab.newIntBand(name, UNSIGNED5);
-        }
-    }
-
-    protected int setAttributeLayoutIndex(Attribute.Layout def, int index) {
-        int ctype = def.ctype;
-        assert(ATTR_INDEX_OVERFLOW <= index && index < attrIndexLimit[ctype]);
-        List<Attribute.Layout> defList = attrDefs.get(ctype);
-        if (index == ATTR_INDEX_OVERFLOW) {
-            // Overflow attribute.
-            index = defList.size();
-            defList.add(def);
-            if (verbose > 0)
-                Utils.log.info("Adding new attribute at "+def +": "+index);
-            attrIndexTable.put(def, index);
-            return index;
-        }
-
-        // Detect redefinitions:
-        if (testBit(attrDefSeen[ctype], 1L<<index)) {
-            throw new RuntimeException("Multiple explicit definition at "+index+": "+def);
-        }
-        attrDefSeen[ctype] |= (1L<<index);
-
-        // Adding a new fixed attribute.
-        assert(0 <= index && index < attrIndexLimit[ctype]);
-        if (verbose > (attrClassFileVersionMask == 0? 2:0))
-            Utils.log.fine("Fixing new attribute at "+index
-                               +": "+def
-                               +(defList.get(index) == null? "":
-                                 "; replacing "+defList.get(index)));
-        attrFlagMask[ctype] |= (1L<<index);
-        // Remove index binding of any previous fixed attr.
-        attrIndexTable.put(defList.get(index), null);
-        defList.set(index, def);
-        attrIndexTable.put(def, index);
-        return index;
-    }
-
-    // encodings found in the code_headers band
-    private static final int[][] shortCodeLimits = {
-        { 12, 12 }, // s<12, l<12, e=0 [1..144]
-        {  8,  8 }, //  s<8,  l<8, e=1 [145..208]
-        {  7,  7 }, //  s<7,  l<7, e=2 [209..256]
-    };
-    public final int shortCodeHeader_h_limit = shortCodeLimits.length;
-
-    // return 0 if it won't encode, else a number in [1..255]
-    static int shortCodeHeader(Code code) {
-        int s = code.max_stack;
-        int l0 = code.max_locals;
-        int h = code.handler_class.length;
-        if (h >= shortCodeLimits.length)  return LONG_CODE_HEADER;
-        int siglen = code.getMethod().getArgumentSize();
-        assert(l0 >= siglen);  // enough locals for signature!
-        if (l0 < siglen)  return LONG_CODE_HEADER;
-        int l1 = l0 - siglen;  // do not count locals required by the signature
-        int lims = shortCodeLimits[h][0];
-        int liml = shortCodeLimits[h][1];
-        if (s >= lims || l1 >= liml)  return LONG_CODE_HEADER;
-        int sc = shortCodeHeader_h_base(h);
-        sc += s + lims*l1;
-        if (sc > 255)  return LONG_CODE_HEADER;
-        assert(shortCodeHeader_max_stack(sc) == s);
-        assert(shortCodeHeader_max_na_locals(sc) == l1);
-        assert(shortCodeHeader_handler_count(sc) == h);
-        return sc;
-    }
-
-    static final int LONG_CODE_HEADER = 0;
-    static int shortCodeHeader_handler_count(int sc) {
-        assert(sc > 0 && sc <= 255);
-        for (int h = 0; ; h++) {
-            if (sc < shortCodeHeader_h_base(h+1))
-                return h;
-        }
-    }
-    static int shortCodeHeader_max_stack(int sc) {
-        int h = shortCodeHeader_handler_count(sc);
-        int lims = shortCodeLimits[h][0];
-        return (sc - shortCodeHeader_h_base(h)) % lims;
-    }
-    static int shortCodeHeader_max_na_locals(int sc) {
-        int h = shortCodeHeader_handler_count(sc);
-        int lims = shortCodeLimits[h][0];
-        return (sc - shortCodeHeader_h_base(h)) / lims;
-    }
-
-    private static int shortCodeHeader_h_base(int h) {
-        assert(h <= shortCodeLimits.length);
-        int sc = 1;
-        for (int h0 = 0; h0 < h; h0++) {
-            int lims = shortCodeLimits[h0][0];
-            int liml = shortCodeLimits[h0][1];
-            sc += lims * liml;
-        }
-        return sc;
-    }
-
-    // utilities for accessing the bc_label band:
-    protected void putLabel(IntBand bc_label, Code c, int pc, int targetPC) {
-        bc_label.putInt(c.encodeBCI(targetPC) - c.encodeBCI(pc));
-    }
-    protected int getLabel(IntBand bc_label, Code c, int pc) {
-        return c.decodeBCI(bc_label.getInt() + c.encodeBCI(pc));
-    }
-
-    protected CPRefBand getCPRefOpBand(int bc) {
-        switch (Instruction.getCPRefOpTag(bc)) {
-        case CONSTANT_Class:
-            return bc_classref;
-        case CONSTANT_Fieldref:
-            return bc_fieldref;
-        case CONSTANT_Methodref:
-            return bc_methodref;
-        case CONSTANT_InterfaceMethodref:
-            return bc_imethodref;
-        case CONSTANT_InvokeDynamic:
-            return bc_indyref;
-        case CONSTANT_LoadableValue:
-            switch (bc) {
-            case _ildc: case _ildc_w:
-                return bc_intref;
-            case _fldc: case _fldc_w:
-                return bc_floatref;
-            case _lldc2_w:
-                return bc_longref;
-            case _dldc2_w:
-                return bc_doubleref;
-            case _sldc: case _sldc_w:
-                return bc_stringref;
-            case _cldc: case _cldc_w:
-                return bc_classref;
-            case _qldc: case _qldc_w:
-                return bc_loadablevalueref;
-            }
-            break;
-        }
-        assert(false);
-        return null;
-    }
-
-    protected CPRefBand selfOpRefBand(int self_bc) {
-        assert(Instruction.isSelfLinkerOp(self_bc));
-        int idx = (self_bc - _self_linker_op);
-        boolean isSuper = (idx >= _self_linker_super_flag);
-        if (isSuper)  idx -= _self_linker_super_flag;
-        boolean isAload = (idx >= _self_linker_aload_flag);
-        if (isAload)  idx -= _self_linker_aload_flag;
-        int origBC = _first_linker_op + idx;
-        boolean isField = Instruction.isFieldOp(origBC);
-        if (!isSuper)
-            return isField? bc_thisfield: bc_thismethod;
-        else
-            return isField? bc_superfield: bc_supermethod;
-    }
-
-    ////////////////////////////////////////////////////////////////////
-
-    static int nextSeqForDebug;
-    static File dumpDir = null;
-    static OutputStream getDumpStream(Band b, String ext) throws IOException {
-        return getDumpStream(b.name, b.seqForDebug, ext, b);
-    }
-    static OutputStream getDumpStream(Index ix, String ext) throws IOException {
-        if (ix.size() == 0)  return new ByteArrayOutputStream();
-        int seq = ConstantPool.TAG_ORDER[ix.cpMap[0].tag];
-        return getDumpStream(ix.debugName, seq, ext, ix);
-    }
-    static OutputStream getDumpStream(String name, int seq, String ext, Object b) throws IOException {
-        if (dumpDir == null) {
-            dumpDir = File.createTempFile("BD_", "", new File("."));
-            dumpDir.delete();
-            if (dumpDir.mkdir())
-                Utils.log.info("Dumping bands to "+dumpDir);
-        }
-        name = name.replace('(', ' ').replace(')', ' ');
-        name = name.replace('/', ' ');
-        name = name.replace('*', ' ');
-        name = name.trim().replace(' ','_');
-        name = ((10000+seq) + "_" + name).substring(1);
-        File dumpFile = new File(dumpDir, name+ext);
-        Utils.log.info("Dumping "+b+" to "+dumpFile);
-        return new BufferedOutputStream(new FileOutputStream(dumpFile));
-    }
-
-    // DEBUG ONLY:  Validate me at each length change.
-    static boolean assertCanChangeLength(Band b) {
-        switch (b.phase) {
-        case COLLECT_PHASE:
-        case READ_PHASE:
-            return true;
-        }
-        return false;
-    }
-
-    // DEBUG ONLY:  Validate a phase.
-    static boolean assertPhase(Band b, int phaseExpected) {
-        if (b.phase() != phaseExpected) {
-            Utils.log.warning("phase expected "+phaseExpected+" was "+b.phase()+" in "+b);
-            return false;
-        }
-        return true;
-    }
-
-
-    // DEBUG ONLY:  Tells whether verbosity is turned on.
-    static int verbose() {
-        return Utils.currentPropMap().getInteger(Utils.DEBUG_VERBOSE);
-    }
-
-
-    // DEBUG ONLY:  Validate me at each phase change.
-    static boolean assertPhaseChangeOK(Band b, int p0, int p1) {
-        switch (p0*10+p1) {
-        /// Writing phases:
-        case NO_PHASE*10+COLLECT_PHASE:
-            // Ready to collect data from the input classes.
-            assert(!b.isReader());
-            assert(b.capacity() >= 0);
-            assert(b.length() == 0);
-            return true;
-        case COLLECT_PHASE*10+FROZEN_PHASE:
-        case FROZEN_PHASE*10+FROZEN_PHASE:
-            assert(b.length() == 0);
-            return true;
-        case COLLECT_PHASE*10+WRITE_PHASE:
-        case FROZEN_PHASE*10+WRITE_PHASE:
-            // Data is all collected.  Ready to write bytes to disk.
-            return true;
-        case WRITE_PHASE*10+DONE_PHASE:
-            // Done writing to disk.  Ready to reset, in principle.
-            return true;
-
-        /// Reading phases:
-        case NO_PHASE*10+EXPECT_PHASE:
-            assert(b.isReader());
-            assert(b.capacity() < 0);
-            return true;
-        case EXPECT_PHASE*10+READ_PHASE:
-            // Ready to read values from disk.
-            assert(Math.max(0,b.capacity()) >= b.valuesExpected());
-            assert(b.length() <= 0);
-            return true;
-        case READ_PHASE*10+DISBURSE_PHASE:
-            // Ready to disburse values.
-            assert(b.valuesRemainingForDebug() == b.length());
-            return true;
-        case DISBURSE_PHASE*10+DONE_PHASE:
-            // Done disbursing values.  Ready to reset, in principle.
-            assert(assertDoneDisbursing(b));
-            return true;
-        }
-        if (p0 == p1)
-            Utils.log.warning("Already in phase "+p0);
-        else
-            Utils.log.warning("Unexpected phase "+p0+" -> "+p1);
-        return false;
-    }
-
-    private static boolean assertDoneDisbursing(Band b) {
-        if (b.phase != DISBURSE_PHASE) {
-            Utils.log.warning("assertDoneDisbursing: still in phase "+b.phase+": "+b);
-            if (verbose() <= 1)  return false;  // fail now
-        }
-        int left = b.valuesRemainingForDebug();
-        if (left > 0) {
-            Utils.log.warning("assertDoneDisbursing: "+left+" values left in "+b);
-            if (verbose() <= 1)  return false;  // fail now
-        }
-        if (b instanceof MultiBand) {
-            MultiBand mb = (MultiBand) b;
-            for (int i = 0; i < mb.bandCount; i++) {
-                Band sub = mb.bands[i];
-                if (sub.phase != DONE_PHASE) {
-                    Utils.log.warning("assertDoneDisbursing: sub-band still in phase "+sub.phase+": "+sub);
-                    if (verbose() <= 1)  return false;  // fail now
-                }
-            }
-        }
-        return true;
-    }
-
-    private static void printCDecl(Band b) {
-        if (b instanceof MultiBand) {
-            MultiBand mb = (MultiBand) b;
-            for (int i = 0; i < mb.bandCount; i++) {
-                printCDecl(mb.bands[i]);
-            }
-            return;
-        }
-        String ixS = "NULL";
-        if (b instanceof CPRefBand) {
-            Index ix = ((CPRefBand)b).index;
-            if (ix != null)  ixS = "INDEX("+ix.debugName+")";
-        }
-        Coding[] knownc = { BYTE1, CHAR3, BCI5, BRANCH5, UNSIGNED5,
-                            UDELTA5, SIGNED5, DELTA5, MDELTA5 };
-        String[] knowns = { "BYTE1", "CHAR3", "BCI5", "BRANCH5", "UNSIGNED5",
-                            "UDELTA5", "SIGNED5", "DELTA5", "MDELTA5" };
-        Coding rc = b.regularCoding;
-        int rci = Arrays.asList(knownc).indexOf(rc);
-        String cstr;
-        if (rci >= 0)
-            cstr = knowns[rci];
-        else
-            cstr = "CODING"+rc.keyString();
-        System.out.println("  BAND_INIT(\""+b.name()+"\""
-                           +", "+cstr+", "+ixS+"),");
-    }
-
-    private Map<Band, Band> prevForAssertMap;
-
-    // DEBUG ONLY:  Record something about the band order.
-    boolean notePrevForAssert(Band b, Band p) {
-        if (prevForAssertMap == null)
-            prevForAssertMap = new HashMap<>();
-        prevForAssertMap.put(b, p);
-        return true;
-    }
-
-    // DEBUG ONLY:  Validate next input band, ensure bands are read in sequence
-    private boolean assertReadyToReadFrom(Band b, InputStream in) throws IOException {
-        Band p = prevForAssertMap.get(b);
-        // Any previous band must be done reading before this one starts.
-        if (p != null && phaseCmp(p.phase(), DISBURSE_PHASE) < 0) {
-            Utils.log.warning("Previous band not done reading.");
-            Utils.log.info("    Previous band: "+p);
-            Utils.log.info("        Next band: "+b);
-            assert(verbose > 0);  // die unless verbose is true
-        }
-        String name = b.name;
-        if (optDebugBands && !name.startsWith("(")) {
-            assert(bandSequenceList != null);
-            // Verify synchronization between reader & writer:
-            String inName = bandSequenceList.removeFirst();
-            // System.out.println("Reading: " + name);
-            if (!inName.equals(name)) {
-                Utils.log.warning("Expected " + name + " but read: " + inName);
-                return false;
-            }
-            Utils.log.info("Read band in sequence: " + name);
-        }
-        return true;
-    }
-
-    // DEBUG ONLY:  Make sure a bunch of cprefs are correct.
-    private boolean assertValidCPRefs(CPRefBand b) {
-        if (b.index == null)  return true;
-        int limit = b.index.size()+1;
-        for (int i = 0; i < b.length(); i++) {
-            int v = b.valueAtForDebug(i);
-            if (v < 0 || v >= limit) {
-                Utils.log.warning("CP ref out of range "+
-                                   "["+i+"] = "+v+" in "+b);
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /*
-     * DEBUG ONLY:  write the bands to a list and read back the list in order,
-     * this works perfectly if we use the java packer and unpacker, typically
-     * this will work with --repack or if they are in the same jvm instance.
-     */
-    static LinkedList<String> bandSequenceList = null;
-    private boolean assertReadyToWriteTo(Band b, OutputStream out) throws IOException {
-        Band p = prevForAssertMap.get(b);
-        // Any previous band must be done writing before this one starts.
-        if (p != null && phaseCmp(p.phase(), DONE_PHASE) < 0) {
-            Utils.log.warning("Previous band not done writing.");
-            Utils.log.info("    Previous band: "+p);
-            Utils.log.info("        Next band: "+b);
-            assert(verbose > 0);  // die unless verbose is true
-        }
-        String name = b.name;
-        if (optDebugBands && !name.startsWith("(")) {
-            if (bandSequenceList == null)
-                bandSequenceList = new LinkedList<>();
-            // Verify synchronization between reader & writer:
-            bandSequenceList.add(name);
-            // System.out.println("Writing: " + b);
-        }
-        return true;
-    }
-
-    protected static boolean testBit(int flags, int bitMask) {
-        return (flags & bitMask) != 0;
-    }
-    protected static int setBit(int flags, int bitMask, boolean z) {
-        return z ? (flags | bitMask) : (flags &~ bitMask);
-    }
-    protected static boolean testBit(long flags, long bitMask) {
-        return (flags & bitMask) != 0;
-    }
-    protected static long setBit(long flags, long bitMask, boolean z) {
-        return z ? (flags | bitMask) : (flags &~ bitMask);
-    }
-
-
-    static void printArrayTo(PrintStream ps, int[] values, int start, int end) {
-        int len = end-start;
-        for (int i = 0; i < len; i++) {
-            if (i % 10 == 0)
-                ps.println();
-            else
-                ps.print(" ");
-            ps.print(values[start+i]);
-        }
-        ps.println();
-    }
-
-    static void printArrayTo(PrintStream ps, Entry[] cpMap, int start, int end) {
-        printArrayTo(ps, cpMap, start, end, false);
-    }
-    static void printArrayTo(PrintStream ps, Entry[] cpMap, int start, int end, boolean showTags) {
-        StringBuffer buf = new StringBuffer();
-        int len = end-start;
-        for (int i = 0; i < len; i++) {
-            Entry e = cpMap[start+i];
-            ps.print(start+i); ps.print("=");
-            if (showTags) { ps.print(e.tag); ps.print(":"); }
-            String s = e.stringValue();
-            buf.setLength(0);
-            for (int j = 0; j < s.length(); j++) {
-                char ch = s.charAt(j);
-                if (!(ch < ' ' || ch > '~' || ch == '\\')) {
-                    buf.append(ch);
-                } else if (ch == '\\') {
-                    buf.append("\\\\");
-                } else if (ch == '\n') {
-                    buf.append("\\n");
-                } else if (ch == '\t') {
-                    buf.append("\\t");
-                } else if (ch == '\r') {
-                    buf.append("\\r");
-                } else {
-                    String str = "000"+Integer.toHexString(ch);
-                    buf.append("\\u").append(str.substring(str.length()-4));
-                }
-            }
-            ps.println(buf);
-        }
-    }
-
-
-    // Utilities for reallocating:
-    protected static Object[] realloc(Object[] a, int len) {
-        java.lang.Class<?> elt = a.getClass().getComponentType();
-        Object[] na = (Object[]) java.lang.reflect.Array.newInstance(elt, len);
-        System.arraycopy(a, 0, na, 0, Math.min(a.length, len));
-        return na;
-    }
-    protected static Object[] realloc(Object[] a) {
-        return realloc(a, Math.max(10, a.length*2));
-    }
-
-    protected static int[] realloc(int[] a, int len) {
-        if (len == 0)  return noInts;
-        if (a == null)  return new int[len];
-        int[] na = new int[len];
-        System.arraycopy(a, 0, na, 0, Math.min(a.length, len));
-        return na;
-    }
-    protected static int[] realloc(int[] a) {
-        return realloc(a, Math.max(10, a.length*2));
-    }
-
-    protected static byte[] realloc(byte[] a, int len) {
-        if (len == 0)  return noBytes;
-        if (a == null)  return new byte[len];
-        byte[] na = new byte[len];
-        System.arraycopy(a, 0, na, 0, Math.min(a.length, len));
-        return na;
-    }
-    protected static byte[] realloc(byte[] a) {
-        return realloc(a, Math.max(10, a.length*2));
-    }
-}
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/ClassReader.java	Mon Dec 09 14:59:33 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,619 +0,0 @@
-/*
- * Copyright (c) 2001, 2019, 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.
- */
-
-package com.sun.java.util.jar.pack;
-
-import com.sun.java.util.jar.pack.ConstantPool.ClassEntry;
-import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry;
-import com.sun.java.util.jar.pack.ConstantPool.Entry;
-import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry;
-import com.sun.java.util.jar.pack.ConstantPool.MemberEntry;
-import com.sun.java.util.jar.pack.ConstantPool.MethodHandleEntry;
-import com.sun.java.util.jar.pack.ConstantPool.BootstrapMethodEntry;
-import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry;
-import com.sun.java.util.jar.pack.Package.Class;
-import com.sun.java.util.jar.pack.Package.InnerClass;
-import java.io.DataInputStream;
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Map;
-import static com.sun.java.util.jar.pack.Constants.*;
-
-/**
- * Reader for a class file that is being incorporated into a package.
- * @author John Rose
- */
-class ClassReader {
-    int verbose;
-
-    Package pkg;
-    Class cls;
-    long inPos;
-    long constantPoolLimit = -1;
-    DataInputStream in;
-    Map<Attribute.Layout, Attribute> attrDefs;
-    Map<Attribute.Layout, String> attrCommands;
-    String unknownAttrCommand = "error";;
-
-    ClassReader(Class cls, InputStream in) throws IOException {
-        this.pkg = cls.getPackage();
-        this.cls = cls;
-        this.verbose = pkg.verbose;
-        this.in = new DataInputStream(new FilterInputStream(in) {
-            public int read(byte b[], int off, int len) throws IOException {
-                int nr = super.read(b, off, len);
-                if (nr >= 0)  inPos += nr;
-                return nr;
-            }
-            public int read() throws IOException {
-                int ch = super.read();
-                if (ch >= 0)  inPos += 1;
-                return ch;
-            }
-            public long skip(long n) throws IOException {
-                long ns = super.skip(n);
-                if (ns >= 0)  inPos += ns;
-                return ns;
-            }
-        });
-    }
-
-    public void setAttrDefs(Map<Attribute.Layout, Attribute> attrDefs) {
-        this.attrDefs = attrDefs;
-    }
-
-    public void setAttrCommands(Map<Attribute.Layout, String> attrCommands) {
-        this.attrCommands = attrCommands;
-    }
-
-    private void skip(int n, String what) throws IOException {
-        Utils.log.warning("skipping "+n+" bytes of "+what);
-        long skipped = 0;
-        while (skipped < n) {
-            long j = in.skip(n - skipped);
-            assert(j > 0);
-            skipped += j;
-        }
-        assert(skipped == n);
-    }
-
-    private int readUnsignedShort() throws IOException {
-        return in.readUnsignedShort();
-    }
-
-    private int readInt() throws IOException {
-        return in.readInt();
-    }
-
-    /** Read a 2-byte int, and return the <em>global</em> CP entry for it. */
-    private Entry readRef() throws IOException {
-        int i = in.readUnsignedShort();
-        return i == 0 ? null : cls.cpMap[i];
-    }
-
-    private Entry readRef(byte tag) throws IOException {
-        Entry e = readRef();
-        assert(!(e instanceof UnresolvedEntry));
-        checkTag(e, tag);
-        return e;
-    }
-
-    /** Throw a ClassFormatException if the entry does not match the expected tag type. */
-    private Entry checkTag(Entry e, byte tag) throws ClassFormatException {
-        if (e == null || !e.tagMatches(tag)) {
-            String where = (inPos == constantPoolLimit
-                                ? " in constant pool"
-                                : " at pos: " + inPos);
-            String got = (e == null
-                            ? "null CP index"
-                            : "type=" + ConstantPool.tagName(e.tag));
-            throw new ClassFormatException("Bad constant, expected type=" +
-                    ConstantPool.tagName(tag) +
-                    " got "+ got + ", in File: " + cls.file.nameString + where);
-        }
-        return e;
-    }
-    private Entry checkTag(Entry e, byte tag, boolean nullOK) throws ClassFormatException {
-        return nullOK && e == null ? null : checkTag(e, tag);
-    }
-
-    private Entry readRefOrNull(byte tag) throws IOException {
-        Entry e = readRef();
-        checkTag(e, tag, true);
-        return e;
-    }
-
-    private Utf8Entry readUtf8Ref() throws IOException {
-        return (Utf8Entry) readRef(CONSTANT_Utf8);
-    }
-
-    private ClassEntry readClassRef() throws IOException {
-        return (ClassEntry) readRef(CONSTANT_Class);
-    }
-
-    private ClassEntry readClassRefOrNull() throws IOException {
-        return (ClassEntry) readRefOrNull(CONSTANT_Class);
-    }
-
-    private SignatureEntry readSignatureRef() throws IOException {
-        // The class file stores a Utf8, but we want a Signature.
-        Entry e = readRef(CONSTANT_Signature);
-        return (e != null && e.getTag() == CONSTANT_Utf8)
-                ? ConstantPool.getSignatureEntry(e.stringValue())
-                : (SignatureEntry) e;
-    }
-
-    void read() throws IOException {
-        boolean ok = false;
-        try {
-            readMagicNumbers();
-            readConstantPool();
-            readHeader();
-            readMembers(false);  // fields
-            readMembers(true);   // methods
-            readAttributes(ATTR_CONTEXT_CLASS, cls);
-            fixUnresolvedEntries();
-            cls.finishReading();
-            assert(0 >= in.read(new byte[1]));
-            ok = true;
-        } finally {
-            if (!ok) {
-                if (verbose > 0) Utils.log.warning("Erroneous data at input offset "+inPos+" of "+cls.file);
-            }
-        }
-    }
-
-    void readMagicNumbers() throws IOException {
-        cls.magic = in.readInt();
-        if (cls.magic != JAVA_MAGIC)
-            throw new Attribute.FormatException
-                ("Bad magic number in class file "
-                 +Integer.toHexString(cls.magic),
-                 ATTR_CONTEXT_CLASS, "magic-number", "pass");
-        int minver = (short) readUnsignedShort();
-        int majver = (short) readUnsignedShort();
-        cls.version = Package.Version.of(majver, minver);
-
-        //System.out.println("ClassFile.version="+cls.majver+"."+cls.minver);
-        String bad = checkVersion(cls.version);
-        if (bad != null) {
-            throw new Attribute.FormatException
-                ("classfile version too "+bad+": "
-                 +cls.version+" in "+cls.file,
-                 ATTR_CONTEXT_CLASS, "version", "pass");
-        }
-    }
-
-    private String checkVersion(Package.Version ver) {
-        int majver = ver.major;
-        int minver = ver.minor;
-        if (majver < pkg.minClassVersion.major ||
-            (majver == pkg.minClassVersion.major &&
-             minver < pkg.minClassVersion.minor)) {
-            return "small";
-        }
-        if (majver > pkg.maxClassVersion.major ||
-            (majver == pkg.maxClassVersion.major &&
-             minver > pkg.maxClassVersion.minor)) {
-            return "large";
-        }
-        return null;  // OK
-    }
-
-    void readConstantPool() throws IOException {
-        int length = in.readUnsignedShort();
-        //System.err.println("reading CP, length="+length);
-
-        int[] fixups = new int[length*4];
-        int fptr = 0;
-
-        Entry[] cpMap = new Entry[length];
-        cpMap[0] = null;
-        for (int i = 1; i < length; i++) {
-            //System.err.println("reading CP elt, i="+i);
-            int tag = in.readByte();
-            switch (tag) {
-                case CONSTANT_Utf8:
-                    cpMap[i] = ConstantPool.getUtf8Entry(in.readUTF());
-                    break;
-                case CONSTANT_Integer:
-                    {
-                        cpMap[i] = ConstantPool.getLiteralEntry(in.readInt());
-                    }
-                    break;
-                case CONSTANT_Float:
-                    {
-                        cpMap[i] = ConstantPool.getLiteralEntry(in.readFloat());
-                    }
-                    break;
-                case CONSTANT_Long:
-                    {
-                        cpMap[i] = ConstantPool.getLiteralEntry(in.readLong());
-                        cpMap[++i] = null;
-                    }
-                    break;
-                case CONSTANT_Double:
-                    {
-                        cpMap[i] = ConstantPool.getLiteralEntry(in.readDouble());
-                        cpMap[++i] = null;
-                    }
-                    break;
-
-                // just read the refs; do not attempt to resolve while reading
-                case CONSTANT_Class:
-                case CONSTANT_String:
-                case CONSTANT_MethodType:
-                    fixups[fptr++] = i;
-                    fixups[fptr++] = tag;
-                    fixups[fptr++] = in.readUnsignedShort();
-                    fixups[fptr++] = -1;  // empty ref2
-                    break;
-                case CONSTANT_Fieldref:
-                case CONSTANT_Methodref:
-                case CONSTANT_InterfaceMethodref:
-                case CONSTANT_NameandType:
-                    fixups[fptr++] = i;
-                    fixups[fptr++] = tag;
-                    fixups[fptr++] = in.readUnsignedShort();
-                    fixups[fptr++] = in.readUnsignedShort();
-                    break;
-                case CONSTANT_InvokeDynamic:
-                    fixups[fptr++] = i;
-                    fixups[fptr++] = tag;
-                    fixups[fptr++] = -1 ^ in.readUnsignedShort();  // not a ref
-                    fixups[fptr++] = in.readUnsignedShort();
-                    break;
-                case CONSTANT_MethodHandle:
-                    fixups[fptr++] = i;
-                    fixups[fptr++] = tag;
-                    fixups[fptr++] = -1 ^ in.readUnsignedByte();
-                    fixups[fptr++] = in.readUnsignedShort();
-                    break;
-                default:
-                    throw new ClassFormatException("Bad constant pool tag " +
-                            tag + " in File: " + cls.file.nameString +
-                            " at pos: " + inPos);
-            }
-        }
-        constantPoolLimit = inPos;
-
-        // Fix up refs, which might be out of order.
-        while (fptr > 0) {
-            if (verbose > 3)
-                Utils.log.fine("CP fixups ["+fptr/4+"]");
-            int flimit = fptr;
-            fptr = 0;
-            for (int fi = 0; fi < flimit; ) {
-                int cpi = fixups[fi++];
-                int tag = fixups[fi++];
-                int ref = fixups[fi++];
-                int ref2 = fixups[fi++];
-                if (verbose > 3)
-                    Utils.log.fine("  cp["+cpi+"] = "+ConstantPool.tagName(tag)+"{"+ref+","+ref2+"}");
-                if (ref >= 0 && cpMap[ref] == null || ref2 >= 0 && cpMap[ref2] == null) {
-                    // Defer.
-                    fixups[fptr++] = cpi;
-                    fixups[fptr++] = tag;
-                    fixups[fptr++] = ref;
-                    fixups[fptr++] = ref2;
-                    continue;
-                }
-                switch (tag) {
-                case CONSTANT_Class:
-                    cpMap[cpi] = ConstantPool.getClassEntry(cpMap[ref].stringValue());
-                    break;
-                case CONSTANT_String:
-                    cpMap[cpi] = ConstantPool.getStringEntry(cpMap[ref].stringValue());
-                    break;
-                case CONSTANT_Fieldref:
-                case CONSTANT_Methodref:
-                case CONSTANT_InterfaceMethodref:
-                    ClassEntry      mclass = (ClassEntry)      checkTag(cpMap[ref],  CONSTANT_Class);
-                    DescriptorEntry mdescr = (DescriptorEntry) checkTag(cpMap[ref2], CONSTANT_NameandType);
-                    cpMap[cpi] = ConstantPool.getMemberEntry((byte)tag, mclass, mdescr);
-                    break;
-                case CONSTANT_NameandType:
-                    Utf8Entry mname = (Utf8Entry) checkTag(cpMap[ref],  CONSTANT_Utf8);
-                    Utf8Entry mtype = (Utf8Entry) checkTag(cpMap[ref2], CONSTANT_Signature);
-                    cpMap[cpi] = ConstantPool.getDescriptorEntry(mname, mtype);
-                    break;
-                case CONSTANT_MethodType:
-                    cpMap[cpi] = ConstantPool.getMethodTypeEntry((Utf8Entry) checkTag(cpMap[ref], CONSTANT_Signature));
-                    break;
-                case CONSTANT_MethodHandle:
-                    byte refKind = (byte)(-1 ^ ref);
-                    MemberEntry memRef = (MemberEntry) checkTag(cpMap[ref2], CONSTANT_AnyMember);
-                    cpMap[cpi] = ConstantPool.getMethodHandleEntry(refKind, memRef);
-                    break;
-                case CONSTANT_InvokeDynamic:
-                    DescriptorEntry idescr = (DescriptorEntry) checkTag(cpMap[ref2], CONSTANT_NameandType);
-                    cpMap[cpi] = new UnresolvedEntry((byte)tag, (-1 ^ ref), idescr);
-                    // Note that ref must be resolved later, using the BootstrapMethods attribute.
-                    break;
-                default:
-                    assert(false);
-                }
-            }
-            assert(fptr < flimit);  // Must make progress.
-        }
-
-        cls.cpMap = cpMap;
-    }
-
-    private /*non-static*/
-    class UnresolvedEntry extends Entry {
-        final Object[] refsOrIndexes;
-        UnresolvedEntry(byte tag, Object... refsOrIndexes) {
-            super(tag);
-            this.refsOrIndexes = refsOrIndexes;
-            ClassReader.this.haveUnresolvedEntry = true;
-        }
-        Entry resolve() {
-            Class cls = ClassReader.this.cls;
-            Entry res;
-            switch (tag) {
-            case CONSTANT_InvokeDynamic:
-                BootstrapMethodEntry iboots = cls.bootstrapMethods.get((Integer) refsOrIndexes[0]);
-                DescriptorEntry         idescr = (DescriptorEntry) refsOrIndexes[1];
-                res = ConstantPool.getInvokeDynamicEntry(iboots, idescr);
-                break;
-            default:
-                throw new AssertionError();
-            }
-            return res;
-        }
-        private void unresolved() { throw new RuntimeException("unresolved entry has no string"); }
-        public int compareTo(Object x) { unresolved(); return 0; }
-        public boolean equals(Object x) { unresolved(); return false; }
-        protected int computeValueHash() { unresolved(); return 0; }
-        public String stringValue() { unresolved(); return toString(); }
-        public String toString() { return "(unresolved "+ConstantPool.tagName(tag)+")"; }
-    }
-
-    boolean haveUnresolvedEntry;
-    private void fixUnresolvedEntries() {
-        if (!haveUnresolvedEntry)  return;
-        Entry[] cpMap = cls.getCPMap();
-        for (int i = 0; i < cpMap.length; i++) {
-            Entry e = cpMap[i];
-            if (e instanceof UnresolvedEntry) {
-                cpMap[i] = e = ((UnresolvedEntry)e).resolve();
-                assert(!(e instanceof UnresolvedEntry));
-            }
-        }
-        haveUnresolvedEntry = false;
-    }
-
-    void readHeader() throws IOException {
-        cls.flags = readUnsignedShort();
-        cls.thisClass = readClassRef();
-        cls.superClass = readClassRefOrNull();
-        int ni = readUnsignedShort();
-        cls.interfaces = new ClassEntry[ni];
-        for (int i = 0; i < ni; i++) {
-            cls.interfaces[i] = readClassRef();
-        }
-    }
-
-    void readMembers(boolean doMethods) throws IOException {
-        int nm = readUnsignedShort();
-        for (int i = 0; i < nm; i++) {
-            readMember(doMethods);
-        }
-    }
-
-    void readMember(boolean doMethod) throws IOException {
-        int    mflags = readUnsignedShort();
-        Utf8Entry       mname = readUtf8Ref();
-        SignatureEntry  mtype = readSignatureRef();
-        DescriptorEntry descr = ConstantPool.getDescriptorEntry(mname, mtype);
-        Class.Member m;
-        if (!doMethod)
-            m = cls.new Field(mflags, descr);
-        else
-            m = cls.new Method(mflags, descr);
-        readAttributes(!doMethod ? ATTR_CONTEXT_FIELD : ATTR_CONTEXT_METHOD,
-                       m);
-    }
-    void readAttributes(int ctype, Attribute.Holder h) throws IOException {
-        int na = readUnsignedShort();
-        if (na == 0)  return;  // nothing to do here
-        if (verbose > 3)
-            Utils.log.fine("readAttributes "+h+" ["+na+"]");
-        for (int i = 0; i < na; i++) {
-            String name = readUtf8Ref().stringValue();
-            int length = readInt();
-            // See if there is a special command that applies.
-            if (attrCommands != null) {
-                Attribute.Layout lkey = Attribute.keyForLookup(ctype, name);
-                String cmd = attrCommands.get(lkey);
-                if (cmd != null) {
-                    switch (cmd) {
-                        case "pass":
-                            String message1 = "passing attribute bitwise in " + h;
-                            throw new Attribute.FormatException(message1, ctype, name, cmd);
-                        case "error":
-                            String message2 = "attribute not allowed in " + h;
-                            throw new Attribute.FormatException(message2, ctype, name, cmd);
-                        case "strip":
-                            skip(length, name + " attribute in " + h);
-                            continue;
-                    }
-                }
-            }
-            // Find canonical instance of the requested attribute.
-            Attribute a = Attribute.lookup(Package.attrDefs, ctype, name);
-            if (verbose > 4 && a != null)
-                Utils.log.fine("pkg_attribute_lookup "+name+" = "+a);
-            if (a == null) {
-                a = Attribute.lookup(this.attrDefs, ctype, name);
-                if (verbose > 4 && a != null)
-                    Utils.log.fine("this "+name+" = "+a);
-            }
-            if (a == null) {
-                a = Attribute.lookup(null, ctype, name);
-                if (verbose > 4 && a != null)
-                    Utils.log.fine("null_attribute_lookup "+name+" = "+a);
-            }
-            if (a == null && length == 0) {
-                // Any zero-length attr is "known"...
-                // We can assume an empty attr. has an empty layout.
-                // Handles markers like Enum, Bridge, Synthetic, Deprecated.
-                a = Attribute.find(ctype, name, "");
-            }
-            boolean isStackMap = (ctype == ATTR_CONTEXT_CODE
-                                  && (name.equals("StackMap") ||
-                                      name.equals("StackMapX")));
-            if (isStackMap) {
-                // Known attribute but with a corner case format, "pass" it.
-                Code code = (Code) h;
-                final int TOO_BIG = 0x10000;
-                if (code.max_stack   >= TOO_BIG ||
-                    code.max_locals  >= TOO_BIG ||
-                    code.getLength() >= TOO_BIG ||
-                    name.endsWith("X")) {
-                    // No, we don't really know what to do with this one.
-                    // Do not compress the rare and strange "u4" and "X" cases.
-                    a = null;
-                }
-            }
-            if (a == null) {
-                if (isStackMap) {
-                    // Known attribute but w/o a format; pass it.
-                    String message = "unsupported StackMap variant in "+h;
-                    throw new Attribute.FormatException(message, ctype, name,
-                                                        "pass");
-                } else if ("strip".equals(unknownAttrCommand)) {
-                    // Skip the unknown attribute.
-                    skip(length, "unknown "+name+" attribute in "+h);
-                    continue;
-                } else {
-                    String message = " is unknown attribute in class " + h;
-                    throw new Attribute.FormatException(message, ctype, name,
-                                                        unknownAttrCommand);
-                }
-            }
-            long pos0 = inPos;  // in case we want to check it
-            if (a.layout() == Package.attrCodeEmpty) {
-                // These are hardwired.
-                Class.Method m = (Class.Method) h;
-                m.code = new Code(m);
-                try {
-                    readCode(m.code);
-                } catch (Instruction.FormatException iie) {
-                    String message = iie.getMessage() + " in " + h;
-                    throw new ClassReader.ClassFormatException(message, iie);
-                }
-                assert(length == inPos - pos0);
-                // Keep empty attribute a...
-            } else if (a.layout() == Package.attrBootstrapMethodsEmpty) {
-                assert(h == cls);
-                readBootstrapMethods(cls);
-                assert(length == inPos - pos0);
-                // Delete the attribute; it is logically part of the constant pool.
-                continue;
-            } else if (a.layout() == Package.attrInnerClassesEmpty) {
-                // These are hardwired also.
-                assert(h == cls);
-                readInnerClasses(cls);
-                assert(length == inPos - pos0);
-                // Keep empty attribute a...
-            } else if (length > 0) {
-                byte[] bytes = new byte[length];
-                in.readFully(bytes);
-                a = a.addContent(bytes);
-            }
-            if (a.size() == 0 && !a.layout().isEmpty()) {
-                throw new ClassFormatException(name +
-                        ": attribute length cannot be zero, in " + h);
-            }
-            h.addAttribute(a);
-            if (verbose > 2)
-                Utils.log.fine("read "+a);
-        }
-    }
-
-    void readCode(Code code) throws IOException {
-        code.max_stack = readUnsignedShort();
-        code.max_locals = readUnsignedShort();
-        code.bytes = new byte[readInt()];
-        in.readFully(code.bytes);
-        Entry[] cpMap = cls.getCPMap();
-        Instruction.opcodeChecker(code.bytes, cpMap, this.cls.version);
-        int nh = readUnsignedShort();
-        code.setHandlerCount(nh);
-        for (int i = 0; i < nh; i++) {
-            code.handler_start[i] = readUnsignedShort();
-            code.handler_end[i]   = readUnsignedShort();
-            code.handler_catch[i] = readUnsignedShort();
-            code.handler_class[i] = readClassRefOrNull();
-        }
-        readAttributes(ATTR_CONTEXT_CODE, code);
-    }
-
-    void readBootstrapMethods(Class cls) throws IOException {
-        BootstrapMethodEntry[] bsms = new BootstrapMethodEntry[readUnsignedShort()];
-        for (int i = 0; i < bsms.length; i++) {
-            MethodHandleEntry bsmRef = (MethodHandleEntry) readRef(CONSTANT_MethodHandle);
-            Entry[] argRefs = new Entry[readUnsignedShort()];
-            for (int j = 0; j < argRefs.length; j++) {
-                argRefs[j] = readRef(CONSTANT_LoadableValue);
-            }
-            bsms[i] = ConstantPool.getBootstrapMethodEntry(bsmRef, argRefs);
-        }
-        cls.setBootstrapMethods(Arrays.asList(bsms));
-    }
-
-    void readInnerClasses(Class cls) throws IOException {
-        int nc = readUnsignedShort();
-        ArrayList<InnerClass> ics = new ArrayList<>(nc);
-        for (int i = 0; i < nc; i++) {
-            InnerClass ic =
-                new InnerClass(readClassRef(),
-                               readClassRefOrNull(),
-                               (Utf8Entry)readRefOrNull(CONSTANT_Utf8),
-                               readUnsignedShort());
-            ics.add(ic);
-        }
-        cls.innerClasses = ics;  // set directly; do not use setInnerClasses.
-        // (Later, ics may be transferred to the pkg.)
-    }
-
-    static class ClassFormatException extends IOException {
-        @java.io.Serial
-        private static final long serialVersionUID = -3564121733989501833L;
-
-        public ClassFormatException(String message) {
-            super(message);
-        }
-
-        public ClassFormatException(String message, Throwable cause) {
-            super(message, cause);
-        }
-    }
-}
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/ClassWriter.java	Mon Dec 09 14:59:33 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,317 +0,0 @@
-/*
- * Copyright (c) 2001, 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.
- */
-
-package com.sun.java.util.jar.pack;
-
-
-import com.sun.java.util.jar.pack.ConstantPool.Entry;
-import com.sun.java.util.jar.pack.ConstantPool.Index;
-import com.sun.java.util.jar.pack.ConstantPool.NumberEntry;
-import com.sun.java.util.jar.pack.ConstantPool.MethodHandleEntry;
-import com.sun.java.util.jar.pack.ConstantPool.BootstrapMethodEntry;
-import com.sun.java.util.jar.pack.Package.Class;
-import com.sun.java.util.jar.pack.Package.InnerClass;
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.List;
-import static com.sun.java.util.jar.pack.Constants.*;
-/**
- * Writer for a class file that is incorporated into a package.
- * @author John Rose
- */
-class ClassWriter {
-    int verbose;
-
-    Package pkg;
-    Class cls;
-    DataOutputStream out;
-    Index cpIndex;
-    Index bsmIndex;
-
-    ClassWriter(Class cls, OutputStream out) throws IOException {
-        this.pkg = cls.getPackage();
-        this.cls = cls;
-        this.verbose = pkg.verbose;
-        this.out = new DataOutputStream(new BufferedOutputStream(out));
-        this.cpIndex = ConstantPool.makeIndex(cls.toString(), cls.getCPMap());
-        this.cpIndex.flattenSigs = true;
-        if (cls.hasBootstrapMethods()) {
-            this.bsmIndex = ConstantPool.makeIndex(cpIndex.debugName+".BootstrapMethods",
-                                                   cls.getBootstrapMethodMap());
-        }
-        if (verbose > 1)
-            Utils.log.fine("local CP="+(verbose > 2 ? cpIndex.dumpString() : cpIndex.toString()));
-    }
-
-    private void writeShort(int x) throws IOException {
-        out.writeShort(x);
-    }
-
-    private void writeInt(int x) throws IOException {
-        out.writeInt(x);
-    }
-
-    /** Write a 2-byte int representing a CP entry, using the local cpIndex. */
-    private void writeRef(Entry e) throws IOException {
-        writeRef(e, cpIndex);
-    }
-
-    /** Write a 2-byte int representing a CP entry, using the given cpIndex. */
-    private void writeRef(Entry e, Index cpIndex) throws IOException {
-        int i = (e == null) ? 0 : cpIndex.indexOf(e);
-        writeShort(i);
-    }
-
-    void write() throws IOException {
-        boolean ok = false;
-        try {
-            if (verbose > 1)  Utils.log.fine("...writing "+cls);
-            writeMagicNumbers();
-            writeConstantPool();
-            writeHeader();
-            writeMembers(false);  // fields
-            writeMembers(true);   // methods
-            writeAttributes(ATTR_CONTEXT_CLASS, cls);
-            /* Closing here will cause all the underlying
-               streams to close, Causing the jar stream
-               to close prematurely, instead we just flush.
-               out.close();
-             */
-            out.flush();
-            ok = true;
-        } finally {
-            if (!ok) {
-                Utils.log.warning("Error on output of "+cls);
-            }
-        }
-    }
-
-    void writeMagicNumbers() throws IOException {
-        writeInt(cls.magic);
-        writeShort(cls.version.minor);
-        writeShort(cls.version.major);
-    }
-
-    void writeConstantPool() throws IOException {
-        Entry[] cpMap = cls.cpMap;
-        writeShort(cpMap.length);
-        for (int i = 0; i < cpMap.length; i++) {
-            Entry e = cpMap[i];
-            assert((e == null) == (i == 0 || cpMap[i-1] != null && cpMap[i-1].isDoubleWord()));
-            if (e == null)  continue;
-            byte tag = e.getTag();
-            if (verbose > 2)  Utils.log.fine("   CP["+i+"] = "+e);
-            out.write(tag);
-            switch (tag) {
-                case CONSTANT_Signature:
-                    throw new AssertionError("CP should have Signatures remapped to Utf8");
-                case CONSTANT_Utf8:
-                    out.writeUTF(e.stringValue());
-                    break;
-                case CONSTANT_Integer:
-                    out.writeInt(((NumberEntry)e).numberValue().intValue());
-                    break;
-                case CONSTANT_Float:
-                    float fval = ((NumberEntry)e).numberValue().floatValue();
-                    out.writeInt(Float.floatToRawIntBits(fval));
-                    break;
-                case CONSTANT_Long:
-                    out.writeLong(((NumberEntry)e).numberValue().longValue());
-                    break;
-                case CONSTANT_Double:
-                    double dval = ((NumberEntry)e).numberValue().doubleValue();
-                    out.writeLong(Double.doubleToRawLongBits(dval));
-                    break;
-                case CONSTANT_Class:
-                case CONSTANT_String:
-                case CONSTANT_MethodType:
-                    writeRef(e.getRef(0));
-                    break;
-                case CONSTANT_MethodHandle:
-                    MethodHandleEntry mhe = (MethodHandleEntry) e;
-                    out.writeByte(mhe.refKind);
-                    writeRef(mhe.getRef(0));
-                    break;
-                case CONSTANT_Fieldref:
-                case CONSTANT_Methodref:
-                case CONSTANT_InterfaceMethodref:
-                case CONSTANT_NameandType:
-                    writeRef(e.getRef(0));
-                    writeRef(e.getRef(1));
-                    break;
-                case CONSTANT_InvokeDynamic:
-                    writeRef(e.getRef(0), bsmIndex);
-                    writeRef(e.getRef(1));
-                    break;
-                case CONSTANT_BootstrapMethod:
-                    throw new AssertionError("CP should have BootstrapMethods moved to side-table");
-                default:
-                    throw new IOException("Bad constant pool tag "+tag);
-            }
-        }
-    }
-
-    void writeHeader() throws IOException {
-        writeShort(cls.flags);
-        writeRef(cls.thisClass);
-        writeRef(cls.superClass);
-        writeShort(cls.interfaces.length);
-        for (int i = 0; i < cls.interfaces.length; i++) {
-            writeRef(cls.interfaces[i]);
-        }
-    }
-
-    void writeMembers(boolean doMethods) throws IOException {
-        List<? extends Class.Member> mems;
-        if (!doMethods)
-            mems = cls.getFields();
-        else
-            mems = cls.getMethods();
-        writeShort(mems.size());
-        for (Class.Member m : mems) {
-            writeMember(m, doMethods);
-        }
-    }
-
-    void writeMember(Class.Member m, boolean doMethod) throws IOException {
-        if (verbose > 2)  Utils.log.fine("writeMember "+m);
-        writeShort(m.flags);
-        writeRef(m.getDescriptor().nameRef);
-        writeRef(m.getDescriptor().typeRef);
-        writeAttributes(!doMethod ? ATTR_CONTEXT_FIELD : ATTR_CONTEXT_METHOD,
-                        m);
-    }
-
-    private void reorderBSMandICS(Attribute.Holder h) {
-        Attribute bsmAttr = h.getAttribute(Package.attrBootstrapMethodsEmpty);
-        if (bsmAttr == null) return;
-
-        Attribute icsAttr = h.getAttribute(Package.attrInnerClassesEmpty);
-        if (icsAttr == null) return;
-
-        int bsmidx = h.attributes.indexOf(bsmAttr);
-        int icsidx = h.attributes.indexOf(icsAttr);
-        if (bsmidx > icsidx) {
-            h.attributes.remove(bsmAttr);
-            h.attributes.add(icsidx, bsmAttr);
-        }
-        return;
-    }
-
-    // handy buffer for collecting attrs
-    ByteArrayOutputStream buf    = new ByteArrayOutputStream();
-    DataOutputStream      bufOut = new DataOutputStream(buf);
-
-    void writeAttributes(int ctype, Attribute.Holder h) throws IOException {
-        if (h.attributes == null) {
-            writeShort(0);  // attribute size
-            return;
-        }
-        // there may be cases if an InnerClass attribute is explicit, then the
-        // ordering could be wrong, fix the ordering before we write it out.
-        if (h instanceof Package.Class)
-            reorderBSMandICS(h);
-
-        writeShort(h.attributes.size());
-        for (Attribute a : h.attributes) {
-            a.finishRefs(cpIndex);
-            writeRef(a.getNameRef());
-            if (a.layout() == Package.attrCodeEmpty ||
-                a.layout() == Package.attrBootstrapMethodsEmpty ||
-                a.layout() == Package.attrInnerClassesEmpty) {
-                // These are hardwired.
-                DataOutputStream savedOut = out;
-                assert(out != bufOut);
-                buf.reset();
-                out = bufOut;
-                if ("Code".equals(a.name())) {
-                    Class.Method m = (Class.Method) h;
-                    writeCode(m.code);
-                } else if ("BootstrapMethods".equals(a.name())) {
-                    assert(h == cls);
-                    writeBootstrapMethods(cls);
-                } else if ("InnerClasses".equals(a.name())) {
-                    assert(h == cls);
-                    writeInnerClasses(cls);
-                } else {
-                    throw new AssertionError();
-                }
-                out = savedOut;
-                if (verbose > 2)
-                    Utils.log.fine("Attribute "+a.name()+" ["+buf.size()+"]");
-                writeInt(buf.size());
-                buf.writeTo(out);
-            } else {
-                if (verbose > 2)
-                    Utils.log.fine("Attribute "+a.name()+" ["+a.size()+"]");
-                writeInt(a.size());
-                out.write(a.bytes());
-            }
-        }
-    }
-
-    void writeCode(Code code) throws IOException {
-        code.finishRefs(cpIndex);
-        writeShort(code.max_stack);
-        writeShort(code.max_locals);
-        writeInt(code.bytes.length);
-        out.write(code.bytes);
-        int nh = code.getHandlerCount();
-        writeShort(nh);
-        for (int i = 0; i < nh; i++) {
-             writeShort(code.handler_start[i]);
-             writeShort(code.handler_end[i]);
-             writeShort(code.handler_catch[i]);
-             writeRef(code.handler_class[i]);
-        }
-        writeAttributes(ATTR_CONTEXT_CODE, code);
-    }
-
-    void writeBootstrapMethods(Class cls) throws IOException {
-        List<BootstrapMethodEntry> bsms = cls.getBootstrapMethods();
-        writeShort(bsms.size());
-        for (BootstrapMethodEntry e : bsms) {
-            writeRef(e.bsmRef);
-            writeShort(e.argRefs.length);
-            for (Entry argRef : e.argRefs) {
-                writeRef(argRef);
-            }
-        }
-    }
-
-    void writeInnerClasses(Class cls) throws IOException {
-        List<InnerClass> ics = cls.getInnerClasses();
-        writeShort(ics.size());
-        for (InnerClass ic : ics) {
-            writeRef(ic.thisClass);
-            writeRef(ic.outerClass);
-            writeRef(ic.name);
-            writeShort(ic.flags);
-        }
-    }
-}
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/Code.java	Mon Dec 09 14:59:33 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,398 +0,0 @@
-/*
- * Copyright (c) 2001, 2013, 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.
- */
-
-package com.sun.java.util.jar.pack;
-
-import com.sun.java.util.jar.pack.Package.Class;
-import java.lang.reflect.Modifier;
-import java.util.Arrays;
-import java.util.Collection;
-import static com.sun.java.util.jar.pack.Constants.*;
-
-/**
- * Represents a chunk of bytecodes.
- * @author John Rose
- */
-class Code extends Attribute.Holder {
-    Class.Method m;
-
-    public Code(Class.Method m) {
-        this.m = m;
-    }
-
-    public Class.Method getMethod() {
-        return m;
-    }
-    public Class thisClass() {
-        return m.thisClass();
-    }
-    public Package getPackage() {
-        return m.thisClass().getPackage();
-    }
-
-    public ConstantPool.Entry[] getCPMap() {
-        return m.getCPMap();
-    }
-
-    private static final ConstantPool.Entry[] noRefs = ConstantPool.noRefs;
-
-    // The following fields are used directly by the ClassReader, etc.
-    int max_stack;
-    int max_locals;
-
-    ConstantPool.Entry handler_class[] = noRefs;
-    int handler_start[] = noInts;
-    int handler_end[] = noInts;
-    int handler_catch[] = noInts;
-
-    byte[] bytes;
-    Fixups fixups;  // reference relocations, if any are required
-    Object insnMap; // array of instruction boundaries
-
-    int getLength() { return bytes.length; }
-
-    int getMaxStack() {
-        return max_stack;
-    }
-    void setMaxStack(int ms) {
-        max_stack = ms;
-    }
-
-    int getMaxNALocals() {
-        int argsize = m.getArgumentSize();
-        return max_locals - argsize;
-    }
-    void setMaxNALocals(int ml) {
-        int argsize = m.getArgumentSize();
-        max_locals = argsize + ml;
-    }
-
-    int getHandlerCount() {
-        assert(handler_class.length == handler_start.length);
-        assert(handler_class.length == handler_end.length);
-        assert(handler_class.length == handler_catch.length);
-        return handler_class.length;
-    }
-    void setHandlerCount(int h) {
-        if (h > 0) {
-            handler_class = new ConstantPool.Entry[h];
-            handler_start = new int[h];
-            handler_end   = new int[h];
-            handler_catch = new int[h];
-            // caller must fill these in ASAP
-        }
-    }
-
-    void setBytes(byte[] bytes) {
-        this.bytes = bytes;
-        if (fixups != null)
-            fixups.setBytes(bytes);
-    }
-
-    void setInstructionMap(int[] insnMap, int mapLen) {
-        //int[] oldMap = null;
-        //assert((oldMap = getInstructionMap()) != null);
-        this.insnMap = allocateInstructionMap(insnMap, mapLen);
-        //assert(Arrays.equals(oldMap, getInstructionMap()));
-    }
-    void setInstructionMap(int[] insnMap) {
-        setInstructionMap(insnMap, insnMap.length);
-    }
-
-    int[] getInstructionMap() {
-        return expandInstructionMap(getInsnMap());
-    }
-
-    void addFixups(Collection<Fixups.Fixup> moreFixups) {
-        if (fixups == null) {
-            fixups = new Fixups(bytes);
-        }
-        assert(fixups.getBytes() == bytes);
-        fixups.addAll(moreFixups);
-    }
-
-    public void trimToSize() {
-        if (fixups != null) {
-            fixups.trimToSize();
-            if (fixups.size() == 0)
-                fixups = null;
-        }
-        super.trimToSize();
-    }
-
-    protected void visitRefs(int mode, Collection<ConstantPool.Entry> refs) {
-        int verbose = getPackage().verbose;
-        if (verbose > 2)
-            System.out.println("Reference scan "+this);
-        refs.addAll(Arrays.asList(handler_class));
-        if (fixups != null) {
-            fixups.visitRefs(refs);
-        } else {
-            // References (to a local cpMap) are embedded in the bytes.
-            ConstantPool.Entry[] cpMap = getCPMap();
-            for (Instruction i = instructionAt(0); i != null; i = i.next()) {
-                if (verbose > 4)
-                    System.out.println(i);
-                int cpref = i.getCPIndex();
-                if (cpref >= 0) {
-                    refs.add(cpMap[cpref]);
-                }
-            }
-        }
-        // Handle attribute list:
-        super.visitRefs(mode, refs);
-    }
-
-    // Since bytecodes are the single largest contributor to
-    // package size, it's worth a little bit of trouble
-    // to reduce the per-bytecode memory footprint.
-    // In the current scheme, half of the bulk of these arrays
-    // due to bytes, and half to shorts.  (Ints are insignificant.)
-    // Given an average of 1.8 bytes per instruction, this means
-    // instruction boundary arrays are about a 75% overhead--tolerable.
-    // (By using bytes, we get 33% savings over just shorts and ints.
-    // Using both bytes and shorts gives 66% savings over just ints.)
-    static final boolean shrinkMaps = true;
-
-    private Object allocateInstructionMap(int[] insnMap, int mapLen) {
-        int PClimit = getLength();
-        if (shrinkMaps && PClimit <= Byte.MAX_VALUE - Byte.MIN_VALUE) {
-            byte[] map = new byte[mapLen+1];
-            for (int i = 0; i < mapLen; i++) {
-                map[i] = (byte)(insnMap[i] + Byte.MIN_VALUE);
-            }
-            map[mapLen] = (byte)(PClimit + Byte.MIN_VALUE);
-            return map;
-        } else if (shrinkMaps && PClimit < Short.MAX_VALUE - Short.MIN_VALUE) {
-            short[] map = new short[mapLen+1];
-            for (int i = 0; i < mapLen; i++) {
-                map[i] = (short)(insnMap[i] + Short.MIN_VALUE);
-            }
-            map[mapLen] = (short)(PClimit + Short.MIN_VALUE);
-            return map;
-        } else {
-            int[] map = Arrays.copyOf(insnMap, mapLen + 1);
-            map[mapLen] = PClimit;
-            return map;
-        }
-    }
-    private int[] expandInstructionMap(Object map0) {
-        int[] imap;
-        if (map0 instanceof byte[]) {
-            byte[] map = (byte[]) map0;
-            imap = new int[map.length-1];
-            for (int i = 0; i < imap.length; i++) {
-                imap[i] = map[i] - Byte.MIN_VALUE;
-            }
-        } else if (map0 instanceof short[]) {
-            short[] map = (short[]) map0;
-            imap = new int[map.length-1];
-            for (int i = 0; i < imap.length; i++) {
-                imap[i] = map[i] - Byte.MIN_VALUE;
-            }
-        } else {
-            int[] map = (int[]) map0;
-            imap = Arrays.copyOfRange(map, 0, map.length - 1);
-        }
-        return imap;
-    }
-
-    Object getInsnMap() {
-        // Build a map of instruction boundaries.
-        if (insnMap != null) {
-            return insnMap;
-        }
-        int[] map = new int[getLength()];
-        int fillp = 0;
-        for (Instruction i = instructionAt(0); i != null; i = i.next()) {
-            map[fillp++] = i.getPC();
-        }
-        // Make it byte[], short[], or int[] according to the max BCI.
-        insnMap = allocateInstructionMap(map, fillp);
-        //assert(assertBCICodingsOK());
-        return insnMap;
-    }
-
-    /** Encode the given BCI as an instruction boundary number.
-     *  For completeness, irregular (non-boundary) BCIs are
-     *  encoded compactly immediately after the boundary numbers.
-     *  This encoding is the identity mapping outside 0..length,
-     *  and it is 1-1 everywhere.  All by itself this technique
-     *  improved zipped rt.jar compression by 2.6%.
-     */
-    public int encodeBCI(int bci) {
-        if (bci <= 0 || bci > getLength())  return bci;
-        Object map0 = getInsnMap();
-        int i, len;
-        if (shrinkMaps && map0 instanceof byte[]) {
-            byte[] map = (byte[]) map0;
-            len = map.length;
-            i = Arrays.binarySearch(map, (byte)(bci + Byte.MIN_VALUE));
-        } else if (shrinkMaps && map0 instanceof short[]) {
-            short[] map = (short[]) map0;
-            len = map.length;
-            i = Arrays.binarySearch(map, (short)(bci + Short.MIN_VALUE));
-        } else {
-            int[] map = (int[]) map0;
-            len = map.length;
-            i = Arrays.binarySearch(map, bci);
-        }
-        assert(i != -1);
-        assert(i != 0);
-        assert(i != len);
-        assert(i != -len-1);
-        return (i >= 0) ? i : len + bci - (-i-1);
-    }
-    public int decodeBCI(int bciCode) {
-        if (bciCode <= 0 || bciCode > getLength())  return bciCode;
-        Object map0 = getInsnMap();
-        int i, len;
-        // len == map.length
-        // If bciCode < len, result is map[bciCode], the common and fast case.
-        // Otherwise, let map[i] be the smallest map[*] larger than bci.
-        // Then, required by the return statement of encodeBCI:
-        //   bciCode == len + bci - i
-        // Thus:
-        //   bci-i == bciCode-len
-        //   map[i]-adj-i == bciCode-len ; adj in (0..map[i]-map[i-1])
-        // We can solve this by searching for adjacent entries
-        // map[i-1], map[i] such that:
-        //   map[i-1]-(i-1) <= bciCode-len < map[i]-i
-        // This can be approximated by searching map[i] for bciCode and then
-        // linear searching backward.  Given the right i, we then have:
-        //   bci == bciCode-len + i
-        // This linear search is at its worst case for indexes in the beginning
-        // of a large method, but it's not clear that this is a problem in
-        // practice, since BCIs are usually on instruction boundaries.
-        if (shrinkMaps && map0 instanceof byte[]) {
-            byte[] map = (byte[]) map0;
-            len = map.length;
-            if (bciCode < len)
-                return map[bciCode] - Byte.MIN_VALUE;
-            i = Arrays.binarySearch(map, (byte)(bciCode + Byte.MIN_VALUE));
-            if (i < 0)  i = -i-1;
-            int key = bciCode-len + Byte.MIN_VALUE;
-            for (;; i--) {
-                if (map[i-1]-(i-1) <= key)  break;
-            }
-        } else if (shrinkMaps && map0 instanceof short[]) {
-            short[] map = (short[]) map0;
-            len = map.length;
-            if (bciCode < len)
-                return map[bciCode] - Short.MIN_VALUE;
-            i = Arrays.binarySearch(map, (short)(bciCode + Short.MIN_VALUE));
-            if (i < 0)  i = -i-1;
-            int key = bciCode-len + Short.MIN_VALUE;
-            for (;; i--) {
-                if (map[i-1]-(i-1) <= key)  break;
-            }
-        } else {
-            int[] map = (int[]) map0;
-            len = map.length;
-            if (bciCode < len)
-                return map[bciCode];
-            i = Arrays.binarySearch(map, bciCode);
-            if (i < 0)  i = -i-1;
-            int key = bciCode-len;
-            for (;; i--) {
-                if (map[i-1]-(i-1) <= key)  break;
-            }
-        }
-        return bciCode-len + i;
-    }
-
-    public void finishRefs(ConstantPool.Index ix) {
-        if (fixups != null) {
-            fixups.finishRefs(ix);
-            fixups = null;
-        }
-        // Code attributes are finished in ClassWriter.writeAttributes.
-    }
-
-    Instruction instructionAt(int pc) {
-        return Instruction.at(bytes, pc);
-    }
-
-    static boolean flagsRequireCode(int flags) {
-        // A method's flags force it to have a Code attribute,
-        // if the flags are neither native nor abstract.
-        return (flags & (Modifier.NATIVE | Modifier.ABSTRACT)) == 0;
-    }
-
-    public String toString() {
-        return m+".Code";
-    }
-
-    /// Fetching values from my own array.
-    public int getInt(int pc)    { return Instruction.getInt(bytes, pc); }
-    public int getShort(int pc)  { return Instruction.getShort(bytes, pc); }
-    public int getByte(int pc)   { return Instruction.getByte(bytes, pc); }
-    void setInt(int pc, int x)   { Instruction.setInt(bytes, pc, x); }
-    void setShort(int pc, int x) { Instruction.setShort(bytes, pc, x); }
-    void setByte(int pc, int x)  { Instruction.setByte(bytes, pc, x); }
-
-/* TEST CODE ONLY
-    private boolean assertBCICodingsOK() {
-        boolean ok = true;
-        int len = java.lang.reflect.Array.getLength(insnMap);
-        int base = 0;
-        if (insnMap.getClass().getComponentType() == Byte.TYPE)
-            base = Byte.MIN_VALUE;
-        if (insnMap.getClass().getComponentType() == Short.TYPE)</