1 /*
   2  * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.java.util.jar.pack;
  27 
  28 import com.sun.java.util.jar.pack.ConstantPool.*;
  29 import com.sun.java.util.jar.pack.Package.Class;
  30 import com.sun.java.util.jar.pack.Package.File;
  31 import com.sun.java.util.jar.pack.Package.InnerClass;
  32 import java.io.IOException;
  33 import java.io.OutputStream;
  34 import java.io.PrintStream;
  35 import java.util.ArrayList;
  36 import java.util.Arrays;
  37 import java.util.Comparator;
  38 import java.util.HashMap;
  39 import java.util.HashSet;
  40 import java.util.List;
  41 import java.util.Map;
  42 import java.util.Set;
  43 import static com.sun.java.util.jar.pack.Constants.*;
  44 
  45 /**
  46  * Writer for a package file.
  47  * @author John Rose
  48  */
  49 class PackageWriter extends BandStructure {
  50     Package pkg;
  51     OutputStream finalOut;
  52     Package.Version packageVersion;
  53 
  54     PackageWriter(Package pkg, OutputStream out) throws IOException {
  55         this.pkg = pkg;
  56         this.finalOut = out;
  57         // Caller has specified maximum class file version in the package:
  58         initHighestClassVersion(pkg.getHighestClassVersion());
  59     }
  60 
  61     void write() throws IOException {
  62         boolean ok = false;
  63         try {
  64             if (verbose > 0) {
  65                 Utils.log.info("Setting up constant pool...");
  66             }
  67             setup();
  68 
  69             if (verbose > 0) {
  70                 Utils.log.info("Packing...");
  71             }
  72 
  73             // writeFileHeader() is done last, since it has ultimate counts
  74             // writeBandHeaders() is called after all other bands are done
  75             writeConstantPool();
  76             writeFiles();
  77             writeAttrDefs();
  78             writeInnerClasses();
  79             writeClassesAndByteCodes();
  80             writeAttrCounts();
  81 
  82             if (verbose > 1)  printCodeHist();
  83 
  84             // choose codings (fill band_headers if needed)
  85             if (verbose > 0) {
  86                 Utils.log.info("Coding...");
  87             }
  88             all_bands.chooseBandCodings();
  89 
  90             // now we can write the headers:
  91             writeFileHeader();
  92 
  93             writeAllBandsTo(finalOut);
  94 
  95             ok = true;
  96         } catch (Exception ee) {
  97             Utils.log.warning("Error on output: "+ee, ee);
  98             //if (verbose > 0)  ee.printStackTrace();
  99             // Write partial output only if we are verbose.
 100             if (verbose > 0)  finalOut.close();
 101             if (ee instanceof IOException)  throw (IOException)ee;
 102             if (ee instanceof RuntimeException)  throw (RuntimeException)ee;
 103             throw new Error("error packing", ee);
 104         }
 105     }
 106 
 107     Set<Entry>                       requiredEntries;  // for the CP
 108     Map<Attribute.Layout, int[]>     backCountTable;   // for layout callables
 109     int[][]     attrCounts;       // count attr. occurrences
 110 
 111     void setup() {
 112         requiredEntries = new HashSet<>();
 113         setArchiveOptions();
 114         trimClassAttributes();
 115         collectAttributeLayouts();
 116         pkg.buildGlobalConstantPool(requiredEntries);
 117         setBandIndexes();
 118         makeNewAttributeBands();
 119         collectInnerClasses();
 120     }
 121 
 122     /*
 123      * Convenience function to choose an archive version based
 124      * on the class file versions observed within the archive
 125      * or set the user defined version preset via properties.
 126      */
 127     void chooseDefaultPackageVersion() throws IOException {
 128         if (pkg.packageVersion != null) {
 129             packageVersion = pkg.packageVersion;
 130             if (verbose > 0) {
 131                 Utils.log.info("package version overridden with: "
 132                                 + packageVersion);
 133             }
 134             return;
 135         }
 136 
 137         Package.Version highV = getHighestClassVersion();
 138         // set the package version now
 139         if (highV.lessThan(JAVA6_MAX_CLASS_VERSION)) {
 140             // There are only old classfiles in this segment or resources
 141             packageVersion = JAVA5_PACKAGE_VERSION;
 142         } else if (highV.equals(JAVA6_MAX_CLASS_VERSION) ||
 143                 (highV.equals(JAVA7_MAX_CLASS_VERSION) && !pkg.cp.haveExtraTags())) {
 144             // force down the package version if we have jdk7 classes without
 145             // any Indy references, this is because jdk7 class file (51.0) without
 146             // Indy is identical to jdk6 class file (50.0).
 147             packageVersion = JAVA6_PACKAGE_VERSION;
 148         } else if (highV.equals(JAVA7_MAX_CLASS_VERSION)) {
 149             packageVersion = JAVA7_PACKAGE_VERSION;
 150         } else {
 151             // Normal case.  Use the newest archive format, when available
 152             packageVersion = JAVA8_PACKAGE_VERSION;
 153         }
 154 
 155         if (verbose > 0) {
 156             Utils.log.info("Highest version class file: " + highV
 157                     + " package version: " + packageVersion);
 158         }
 159     }
 160 
 161     void checkVersion() throws IOException {
 162         assert(packageVersion != null);
 163 
 164         if (packageVersion.lessThan(JAVA7_PACKAGE_VERSION)) {
 165             // this bit was reserved for future use in previous versions
 166             if (testBit(archiveOptions, AO_HAVE_CP_EXTRAS)) {
 167                 throw new IOException("Format bits for Java 7 must be zero in previous releases");
 168             }
 169         }
 170         if (testBit(archiveOptions, AO_UNUSED_MBZ)) {
 171             throw new IOException("High archive option bits are reserved and must be zero: " + Integer.toHexString(archiveOptions));
 172         }
 173     }
 174 
 175     void setArchiveOptions() {
 176         // Decide on some archive options early.
 177         // Does not decide on: AO_HAVE_SPECIAL_FORMATS,
 178         // AO_HAVE_CP_NUMBERS, AO_HAVE_FILE_HEADERS.
 179         // Also, AO_HAVE_FILE_OPTIONS may be forced on later.
 180         int minModtime = pkg.default_modtime;
 181         int maxModtime = pkg.default_modtime;
 182         int minOptions = -1;
 183         int maxOptions = 0;
 184 
 185         // Import defaults from package (deflate hint, etc.).
 186         archiveOptions |= pkg.default_options;
 187 
 188         for (File file : pkg.files) {
 189             int modtime = file.modtime;
 190             int options = file.options;
 191 
 192             if (minModtime == NO_MODTIME) {
 193                 minModtime = maxModtime = modtime;
 194             } else {
 195                 if (minModtime > modtime)  minModtime = modtime;
 196                 if (maxModtime < modtime)  maxModtime = modtime;
 197             }
 198             minOptions &= options;
 199             maxOptions |= options;
 200         }
 201         if (pkg.default_modtime == NO_MODTIME) {
 202             // Make everything else be a positive offset from here.
 203             pkg.default_modtime = minModtime;
 204         }
 205         if (minModtime != NO_MODTIME && minModtime != maxModtime) {
 206             // Put them into a band.
 207             archiveOptions |= AO_HAVE_FILE_MODTIME;
 208         }
 209         // If the archive deflation is set do not bother with each file.
 210         if (!testBit(archiveOptions,AO_DEFLATE_HINT) && minOptions != -1) {
 211             if (testBit(minOptions, FO_DEFLATE_HINT)) {
 212                 // Every file has the deflate_hint set.
 213                 // Set it for the whole archive, and omit options.
 214                 archiveOptions |= AO_DEFLATE_HINT;
 215                 minOptions -= FO_DEFLATE_HINT;
 216                 maxOptions -= FO_DEFLATE_HINT;
 217             }
 218             pkg.default_options |= minOptions;
 219             if (minOptions != maxOptions
 220                 || minOptions != pkg.default_options) {
 221                 archiveOptions |= AO_HAVE_FILE_OPTIONS;
 222             }
 223         }
 224         // Decide on default version number (majority rule).
 225         Map<Package.Version, int[]> verCounts = new HashMap<>();
 226         int bestCount = 0;
 227         Package.Version bestVersion = null;
 228         for (Class cls : pkg.classes) {
 229             Package.Version version = cls.getVersion();
 230             int[] var = verCounts.get(version);
 231             if (var == null) {
 232                 var = new int[1];
 233                 verCounts.put(version, var);
 234             }
 235             int count = (var[0] += 1);
 236             //System.out.println("version="+version+" count="+count);
 237             if (bestCount < count) {
 238                 bestCount = count;
 239                 bestVersion = version;
 240             }
 241         }
 242         verCounts.clear();
 243         if (bestVersion == null)  bestVersion = JAVA_MIN_CLASS_VERSION;  // degenerate case
 244         pkg.defaultClassVersion = bestVersion;
 245         if (verbose > 0)
 246            Utils.log.info("Consensus version number in segment is " + bestVersion);
 247         if (verbose > 0)
 248             Utils.log.info("Highest version number in segment is "
 249                             + pkg.getHighestClassVersion());
 250 
 251         // Now add explicit pseudo-attrs. to classes with odd versions.
 252         for (Class cls : pkg.classes) {
 253             if (!cls.getVersion().equals(bestVersion)) {
 254                 Attribute a = makeClassFileVersionAttr(cls.getVersion());
 255                 if (verbose > 1) {
 256                     Utils.log.fine("Version "+cls.getVersion() + " of " + cls
 257                                      + " doesn't match package version "
 258                                      + bestVersion);
 259                 }
 260                 // Note:  Does not add in "natural" order.  (Who cares?)
 261                 cls.addAttribute(a);
 262             }
 263         }
 264 
 265         // Decide if we are transmitting a huge resource file:
 266         for (File file : pkg.files) {
 267             long len = file.getFileLength();
 268             if (len != (int)len) {
 269                 archiveOptions |= AO_HAVE_FILE_SIZE_HI;
 270                 if (verbose > 0)
 271                    Utils.log.info("Note: Huge resource file "+file.getFileName()+" forces 64-bit sizing");
 272                 break;
 273             }
 274         }
 275 
 276         // Decide if code attributes typically have sub-attributes.
 277         // In that case, to preserve compact 1-byte code headers,
 278         // we must declare unconditional presence of code flags.
 279         int cost0 = 0;
 280         int cost1 = 0;
 281         for (Class cls : pkg.classes) {
 282             for (Class.Method m : cls.getMethods()) {
 283                 if (m.code != null) {
 284                     if (m.code.attributeSize() == 0) {
 285                         // cost of a useless unconditional flags byte
 286                         cost1 += 1;
 287                     } else if (shortCodeHeader(m.code) != LONG_CODE_HEADER) {
 288                         // cost of inflating a short header
 289                         cost0 += 3;
 290                     }
 291                 }
 292             }
 293         }
 294         if (cost0 > cost1) {
 295             archiveOptions |= AO_HAVE_ALL_CODE_FLAGS;
 296         }
 297         if (verbose > 0)
 298             Utils.log.info("archiveOptions = "
 299                              +"0b"+Integer.toBinaryString(archiveOptions));
 300     }
 301 
 302     void writeFileHeader() throws IOException {
 303         chooseDefaultPackageVersion();
 304         writeArchiveMagic();
 305         writeArchiveHeader();
 306     }
 307 
 308     // Local routine used to format fixed-format scalars
 309     // in the file_header:
 310     private void putMagicInt32(int val) throws IOException {
 311         int res = val;
 312         for (int i = 0; i < 4; i++) {
 313             archive_magic.putByte(0xFF & (res >>> 24));
 314             res <<= 8;
 315         }
 316     }
 317 
 318     void writeArchiveMagic() throws IOException {
 319         putMagicInt32(pkg.magic);
 320     }
 321 
 322     void writeArchiveHeader() throws IOException {
 323         // for debug only:  number of words optimized away
 324         int headerSizeForDebug = AH_LENGTH_MIN;
 325 
 326         // AO_HAVE_SPECIAL_FORMATS is set if non-default
 327         // coding techniques are used, or if there are
 328         // compressor-defined attributes transmitted.
 329         boolean haveSpecial = testBit(archiveOptions, AO_HAVE_SPECIAL_FORMATS);
 330         if (!haveSpecial) {
 331             haveSpecial |= (band_headers.length() != 0);
 332             haveSpecial |= (attrDefsWritten.length != 0);
 333             if (haveSpecial)
 334                 archiveOptions |= AO_HAVE_SPECIAL_FORMATS;
 335         }
 336         if (haveSpecial)
 337             headerSizeForDebug += AH_SPECIAL_FORMAT_LEN;
 338 
 339         // AO_HAVE_FILE_HEADERS is set if there is any
 340         // file or segment envelope information present.
 341         boolean haveFiles = testBit(archiveOptions, AO_HAVE_FILE_HEADERS);
 342         if (!haveFiles) {
 343             haveFiles |= (archiveNextCount > 0);
 344             haveFiles |= (pkg.default_modtime != NO_MODTIME);
 345             if (haveFiles)
 346                 archiveOptions |= AO_HAVE_FILE_HEADERS;
 347         }
 348         if (haveFiles)
 349             headerSizeForDebug += AH_FILE_HEADER_LEN;
 350 
 351         // AO_HAVE_CP_NUMBERS is set if there are any numbers
 352         // in the global constant pool.  (Numbers are in 15% of classes.)
 353         boolean haveNumbers = testBit(archiveOptions, AO_HAVE_CP_NUMBERS);
 354         if (!haveNumbers) {
 355             haveNumbers |= pkg.cp.haveNumbers();
 356             if (haveNumbers)
 357                 archiveOptions |= AO_HAVE_CP_NUMBERS;
 358         }
 359         if (haveNumbers)
 360             headerSizeForDebug += AH_CP_NUMBER_LEN;
 361 
 362         // AO_HAVE_CP_EXTRAS is set if there are constant pool entries
 363         // beyond the Java 6 version of the class file format.
 364         boolean haveCPExtra = testBit(archiveOptions, AO_HAVE_CP_EXTRAS);
 365         if (!haveCPExtra) {
 366             haveCPExtra |= pkg.cp.haveExtraTags();
 367             if (haveCPExtra)
 368                 archiveOptions |= AO_HAVE_CP_EXTRAS;
 369         }
 370         if (haveCPExtra)
 371             headerSizeForDebug += AH_CP_EXTRA_LEN;
 372 
 373         // the archiveOptions are all initialized, sanity check now!.
 374         checkVersion();
 375 
 376         archive_header_0.putInt(packageVersion.minor);
 377         archive_header_0.putInt(packageVersion.major);
 378         if (verbose > 0)
 379             Utils.log.info("Package Version for this segment:" + packageVersion);
 380         archive_header_0.putInt(archiveOptions); // controls header format
 381         assert(archive_header_0.length() == AH_LENGTH_0);
 382 
 383         final int DUMMY = 0;
 384         if (haveFiles) {
 385             assert(archive_header_S.length() == AH_ARCHIVE_SIZE_HI);
 386             archive_header_S.putInt(DUMMY); // (archiveSize1 >>> 32)
 387             assert(archive_header_S.length() == AH_ARCHIVE_SIZE_LO);
 388             archive_header_S.putInt(DUMMY); // (archiveSize1 >>> 0)
 389             assert(archive_header_S.length() == AH_LENGTH_S);
 390         }
 391 
 392         // Done with unsized part of header....
 393 
 394         if (haveFiles) {
 395             archive_header_1.putInt(archiveNextCount);  // usually zero
 396             archive_header_1.putInt(pkg.default_modtime);
 397             archive_header_1.putInt(pkg.files.size());
 398         } else {
 399             assert(pkg.files.isEmpty());
 400         }
 401 
 402         if (haveSpecial) {
 403             archive_header_1.putInt(band_headers.length());
 404             archive_header_1.putInt(attrDefsWritten.length);
 405         } else {
 406             assert(band_headers.length() == 0);
 407             assert(attrDefsWritten.length == 0);
 408         }
 409 
 410         writeConstantPoolCounts(haveNumbers, haveCPExtra);
 411 
 412         archive_header_1.putInt(pkg.getAllInnerClasses().size());
 413         archive_header_1.putInt(pkg.defaultClassVersion.minor);
 414         archive_header_1.putInt(pkg.defaultClassVersion.major);
 415         archive_header_1.putInt(pkg.classes.size());
 416 
 417         // Sanity:  Make sure we came out to 29 (less optional fields):
 418         assert(archive_header_0.length() +
 419                archive_header_S.length() +
 420                archive_header_1.length()
 421                == headerSizeForDebug);
 422 
 423         // Figure out all the sizes now, first cut:
 424         archiveSize0 = 0;
 425         archiveSize1 = all_bands.outputSize();
 426         // Second cut:
 427         archiveSize0 += archive_magic.outputSize();
 428         archiveSize0 += archive_header_0.outputSize();
 429         archiveSize0 += archive_header_S.outputSize();
 430         // Make the adjustments:
 431         archiveSize1 -= archiveSize0;
 432 
 433         // Patch the header:
 434         if (haveFiles) {
 435             int archiveSizeHi = (int)(archiveSize1 >>> 32);
 436             int archiveSizeLo = (int)(archiveSize1 >>> 0);
 437             archive_header_S.patchValue(AH_ARCHIVE_SIZE_HI, archiveSizeHi);
 438             archive_header_S.patchValue(AH_ARCHIVE_SIZE_LO, archiveSizeLo);
 439             int zeroLen = UNSIGNED5.getLength(DUMMY);
 440             archiveSize0 += UNSIGNED5.getLength(archiveSizeHi) - zeroLen;
 441             archiveSize0 += UNSIGNED5.getLength(archiveSizeLo) - zeroLen;
 442         }
 443         if (verbose > 1)
 444             Utils.log.fine("archive sizes: "+
 445                              archiveSize0+"+"+archiveSize1);
 446         assert(all_bands.outputSize() == archiveSize0+archiveSize1);
 447     }
 448 
 449     void writeConstantPoolCounts(boolean haveNumbers, boolean haveCPExtra) throws IOException {
 450         for (byte tag : ConstantPool.TAGS_IN_ORDER) {
 451             int count = pkg.cp.getIndexByTag(tag).size();
 452             switch (tag) {
 453             case CONSTANT_Utf8:
 454                 // The null string is always first.
 455                 if (count > 0)
 456                     assert(pkg.cp.getIndexByTag(tag).get(0)
 457                            == ConstantPool.getUtf8Entry(""));
 458                 break;
 459 
 460             case CONSTANT_Integer:
 461             case CONSTANT_Float:
 462             case CONSTANT_Long:
 463             case CONSTANT_Double:
 464                 // Omit counts for numbers if possible.
 465                 if (!haveNumbers) {
 466                     assert(count == 0);
 467                     continue;
 468                 }
 469                 break;
 470 
 471             case CONSTANT_MethodHandle:
 472             case CONSTANT_MethodType:
 473             case CONSTANT_InvokeDynamic:
 474             case CONSTANT_BootstrapMethod:
 475                 // Omit counts for newer entities if possible.
 476                 if (!haveCPExtra) {
 477                     assert(count == 0);
 478                     continue;
 479                 }
 480                 break;
 481             }
 482             archive_header_1.putInt(count);
 483         }
 484     }
 485 
 486     protected Index getCPIndex(byte tag) {
 487         return pkg.cp.getIndexByTag(tag);
 488     }
 489 
 490 // (The following observations are out of date; they apply only to
 491 // "banding" the constant pool itself.  Later revisions of this algorithm
 492 // applied the banding technique to every part of the package file,
 493 // applying the benefits more broadly.)
 494 
 495 // Note:  Keeping the data separate in passes (or "bands") allows the
 496 // compressor to issue significantly shorter indexes for repeated data.
 497 // The difference in zipped size is 4%, which is remarkable since the
 498 // unzipped sizes are the same (only the byte order differs).
 499 
 500 // After moving similar data into bands, it becomes natural to delta-encode
 501 // each band.  (This is especially useful if we sort the constant pool first.)
 502 // Delta encoding saves an extra 5% in the output size (13% of the CP itself).
 503 // Because a typical delta usees much less data than a byte, the savings after
 504 // zipping is even better:  A zipped delta-encoded package is 8% smaller than
 505 // a zipped non-delta-encoded package.  Thus, in the zipped file, a banded,
 506 // delta-encoded constant pool saves over 11% (of the total file size) compared
 507 // with a zipped unbanded file.
 508 
 509     void writeConstantPool() throws IOException {
 510         IndexGroup cp = pkg.cp;
 511 
 512         if (verbose > 0)  Utils.log.info("Writing CP");
 513 
 514         for (byte tag : ConstantPool.TAGS_IN_ORDER) {
 515             Index index = cp.getIndexByTag(tag);
 516 
 517             Entry[] cpMap = index.cpMap;
 518             if (verbose > 0)
 519                 Utils.log.info("Writing "+cpMap.length+" "+ConstantPool.tagName(tag)+" entries...");
 520 
 521             if (optDumpBands) {
 522                 try (PrintStream ps = new PrintStream(getDumpStream(index, ".idx"))) {
 523                     printArrayTo(ps, cpMap, 0, cpMap.length);
 524                 }
 525             }
 526 
 527             switch (tag) {
 528             case CONSTANT_Utf8:
 529                 writeUtf8Bands(cpMap);
 530                 break;
 531             case CONSTANT_Integer:
 532                 for (int i = 0; i < cpMap.length; i++) {
 533                     NumberEntry e = (NumberEntry) cpMap[i];
 534                     int x = ((Integer)e.numberValue()).intValue();
 535                     cp_Int.putInt(x);
 536                 }
 537                 break;
 538             case CONSTANT_Float:
 539                 for (int i = 0; i < cpMap.length; i++) {
 540                     NumberEntry e = (NumberEntry) cpMap[i];
 541                     float fx = ((Float)e.numberValue()).floatValue();
 542                     int x = Float.floatToIntBits(fx);
 543                     cp_Float.putInt(x);
 544                 }
 545                 break;
 546             case CONSTANT_Long:
 547                 for (int i = 0; i < cpMap.length; i++) {
 548                     NumberEntry e = (NumberEntry) cpMap[i];
 549                     long x = ((Long)e.numberValue()).longValue();
 550                     cp_Long_hi.putInt((int)(x >>> 32));
 551                     cp_Long_lo.putInt((int)(x >>> 0));
 552                 }
 553                 break;
 554             case CONSTANT_Double:
 555                 for (int i = 0; i < cpMap.length; i++) {
 556                     NumberEntry e = (NumberEntry) cpMap[i];
 557                     double dx = ((Double)e.numberValue()).doubleValue();
 558                     long x = Double.doubleToLongBits(dx);
 559                     cp_Double_hi.putInt((int)(x >>> 32));
 560                     cp_Double_lo.putInt((int)(x >>> 0));
 561                 }
 562                 break;
 563             case CONSTANT_String:
 564                 for (int i = 0; i < cpMap.length; i++) {
 565                     StringEntry e = (StringEntry) cpMap[i];
 566                     cp_String.putRef(e.ref);
 567                 }
 568                 break;
 569             case CONSTANT_Class:
 570                 for (int i = 0; i < cpMap.length; i++) {
 571                     ClassEntry e = (ClassEntry) cpMap[i];
 572                     cp_Class.putRef(e.ref);
 573                 }
 574                 break;
 575             case CONSTANT_Signature:
 576                 writeSignatureBands(cpMap);
 577                 break;
 578             case CONSTANT_NameandType:
 579                 for (int i = 0; i < cpMap.length; i++) {
 580                     DescriptorEntry e = (DescriptorEntry) cpMap[i];
 581                     cp_Descr_name.putRef(e.nameRef);
 582                     cp_Descr_type.putRef(e.typeRef);
 583                 }
 584                 break;
 585             case CONSTANT_Fieldref:
 586                 writeMemberRefs(tag, cpMap, cp_Field_class, cp_Field_desc);
 587                 break;
 588             case CONSTANT_Methodref:
 589                 writeMemberRefs(tag, cpMap, cp_Method_class, cp_Method_desc);
 590                 break;
 591             case CONSTANT_InterfaceMethodref:
 592                 writeMemberRefs(tag, cpMap, cp_Imethod_class, cp_Imethod_desc);
 593                 break;
 594             case CONSTANT_MethodHandle:
 595                 for (int i = 0; i < cpMap.length; i++) {
 596                     MethodHandleEntry e = (MethodHandleEntry) cpMap[i];
 597                     cp_MethodHandle_refkind.putInt(e.refKind);
 598                     cp_MethodHandle_member.putRef(e.memRef);
 599                 }
 600                 break;
 601             case CONSTANT_MethodType:
 602                 for (int i = 0; i < cpMap.length; i++) {
 603                     MethodTypeEntry e = (MethodTypeEntry) cpMap[i];
 604                     cp_MethodType.putRef(e.typeRef);
 605                 }
 606                 break;
 607             case CONSTANT_InvokeDynamic:
 608                 for (int i = 0; i < cpMap.length; i++) {
 609                     InvokeDynamicEntry e = (InvokeDynamicEntry) cpMap[i];
 610                     cp_InvokeDynamic_spec.putRef(e.bssRef);
 611                     cp_InvokeDynamic_desc.putRef(e.descRef);
 612                 }
 613                 break;
 614             case CONSTANT_BootstrapMethod:
 615                 for (int i = 0; i < cpMap.length; i++) {
 616                     BootstrapMethodEntry e = (BootstrapMethodEntry) cpMap[i];
 617                     cp_BootstrapMethod_ref.putRef(e.bsmRef);
 618                     cp_BootstrapMethod_arg_count.putInt(e.argRefs.length);
 619                     for (Entry argRef : e.argRefs) {
 620                         cp_BootstrapMethod_arg.putRef(argRef);
 621                     }
 622                 }
 623                 break;
 624             default:
 625                 throw new AssertionError("unexpected CP tag in package");
 626             }
 627         }
 628         if (optDumpBands || verbose > 1) {
 629             for (byte tag = CONSTANT_GroupFirst; tag < CONSTANT_GroupLimit; tag++) {
 630                 Index index = cp.getIndexByTag(tag);
 631                 if (index == null || index.isEmpty())  continue;
 632                 Entry[] cpMap = index.cpMap;
 633                 if (verbose > 1)
 634                     Utils.log.info("Index group "+ConstantPool.tagName(tag)+" contains "+cpMap.length+" entries.");
 635                 if (optDumpBands) {
 636                     try (PrintStream ps = new PrintStream(getDumpStream(index.debugName, tag, ".gidx", index))) {
 637                         printArrayTo(ps, cpMap, 0, cpMap.length, true);
 638                     }
 639                 }
 640             }
 641         }
 642     }
 643 
 644     void writeUtf8Bands(Entry[] cpMap) throws IOException {
 645         if (cpMap.length == 0)
 646             return;  // nothing to write
 647 
 648         // The first element must always be the empty string.
 649         assert(cpMap[0].stringValue().isEmpty());
 650         final int SUFFIX_SKIP_1 = 1;
 651         final int PREFIX_SKIP_2 = 2;
 652 
 653         // Fetch the char arrays, first of all.
 654         char[][] chars = new char[cpMap.length][];
 655         for (int i = 0; i < chars.length; i++) {
 656             chars[i] = cpMap[i].stringValue().toCharArray();
 657         }
 658 
 659         // First band:  Write lengths of shared prefixes.
 660         int[] prefixes = new int[cpMap.length];  // includes 2 skipped zeroes
 661         char[] prevChars = {};
 662         for (int i = 0; i < chars.length; i++) {
 663             int prefix = 0;
 664             char[] curChars = chars[i];
 665             int limit = Math.min(curChars.length, prevChars.length);
 666             while (prefix < limit && curChars[prefix] == prevChars[prefix])
 667                 prefix++;
 668             prefixes[i] = prefix;
 669             if (i >= PREFIX_SKIP_2)
 670                 cp_Utf8_prefix.putInt(prefix);
 671             else
 672                 assert(prefix == 0);
 673             prevChars = curChars;
 674         }
 675 
 676         // Second band:  Write lengths of unshared suffixes.
 677         // Third band:  Write the char values in the unshared suffixes.
 678         for (int i = 0; i < chars.length; i++) {
 679             char[] str = chars[i];
 680             int prefix = prefixes[i];
 681             int suffix = str.length - prefixes[i];
 682             boolean isPacked = false;
 683             if (suffix == 0) {
 684                 // Zero suffix length is special flag to indicate
 685                 // separate treatment in cp_Utf8_big bands.
 686                 // This suffix length never occurs naturally,
 687                 // except in the one case of a zero-length string.
 688                 // (If it occurs, it is the first, due to sorting.)
 689                 // The zero length string must, paradoxically, be
 690                 // encoded as a zero-length cp_Utf8_big band.
 691                 // This wastes exactly (& tolerably) one null byte.
 692                 isPacked = (i >= SUFFIX_SKIP_1);
 693                 // Do not bother to add an empty "(Utf8_big_0)" band.
 694                 // Also, the initial empty string does not require a band.
 695             } else if (optBigStrings && effort > 1 && suffix > 100) {
 696                 int numWide = 0;
 697                 for (int n = 0; n < suffix; n++) {
 698                     if (str[prefix+n] > 127) {
 699                         numWide++;
 700                     }
 701                 }
 702                 if (numWide > 100) {
 703                     // Try packing the chars with an alternate encoding.
 704                     isPacked = tryAlternateEncoding(i, numWide, str, prefix);
 705                 }
 706             }
 707             if (i < SUFFIX_SKIP_1) {
 708                 // No output.
 709                 assert(!isPacked);
 710                 assert(suffix == 0);
 711             } else if (isPacked) {
 712                 // Mark packed string with zero-length suffix count.
 713                 // This tells the unpacker to go elsewhere for the suffix bits.
 714                 // Fourth band:  Write unshared suffix with alternate coding.
 715                 cp_Utf8_suffix.putInt(0);
 716                 cp_Utf8_big_suffix.putInt(suffix);
 717             } else {
 718                 assert(suffix != 0);  // would be ambiguous
 719                 // Normal string.  Save suffix in third and fourth bands.
 720                 cp_Utf8_suffix.putInt(suffix);
 721                 for (int n = 0; n < suffix; n++) {
 722                     int ch = str[prefix+n];
 723                     cp_Utf8_chars.putInt(ch);
 724                 }
 725             }
 726         }
 727         if (verbose > 0) {
 728             int normCharCount = cp_Utf8_chars.length();
 729             int packCharCount = cp_Utf8_big_chars.length();
 730             int charCount = normCharCount + packCharCount;
 731             Utils.log.info("Utf8string #CHARS="+charCount+" #PACKEDCHARS="+packCharCount);
 732         }
 733     }
 734 
 735     private boolean tryAlternateEncoding(int i, int numWide,
 736                                          char[] str, int prefix) {
 737         int suffix = str.length - prefix;
 738         int[] cvals = new int[suffix];
 739         for (int n = 0; n < suffix; n++) {
 740             cvals[n] = str[prefix+n];
 741         }
 742         CodingChooser cc = getCodingChooser();
 743         Coding bigRegular = cp_Utf8_big_chars.regularCoding;
 744         String bandName = "(Utf8_big_"+i+")";
 745         int[] sizes = { 0, 0 };
 746         final int BYTE_SIZE = CodingChooser.BYTE_SIZE;
 747         final int ZIP_SIZE = CodingChooser.ZIP_SIZE;
 748         if (verbose > 1 || cc.verbose > 1) {
 749             Utils.log.fine("--- chooseCoding "+bandName);
 750         }
 751         CodingMethod special = cc.choose(cvals, bigRegular, sizes);
 752         Coding charRegular = cp_Utf8_chars.regularCoding;
 753         if (verbose > 1)
 754             Utils.log.fine("big string["+i+"] len="+suffix+" #wide="+numWide+" size="+sizes[BYTE_SIZE]+"/z="+sizes[ZIP_SIZE]+" coding "+special);
 755         if (special != charRegular) {
 756             int specialZipSize = sizes[ZIP_SIZE];
 757             int[] normalSizes = cc.computeSize(charRegular, cvals);
 758             int normalZipSize = normalSizes[ZIP_SIZE];
 759             int minWin = Math.max(5, normalZipSize/1000);
 760             if (verbose > 1)
 761                 Utils.log.fine("big string["+i+"] normalSize="+normalSizes[BYTE_SIZE]+"/z="+normalSizes[ZIP_SIZE]+" win="+(specialZipSize<normalZipSize-minWin));
 762             if (specialZipSize < normalZipSize-minWin) {
 763                 IntBand big = cp_Utf8_big_chars.newIntBand(bandName);
 764                 big.initializeValues(cvals);
 765                 return true;
 766             }
 767         }
 768         return false;
 769     }
 770 
 771     void writeSignatureBands(Entry[] cpMap) throws IOException {
 772         for (int i = 0; i < cpMap.length; i++) {
 773             SignatureEntry e = (SignatureEntry) cpMap[i];
 774             cp_Signature_form.putRef(e.formRef);
 775             for (int j = 0; j < e.classRefs.length; j++) {
 776                 cp_Signature_classes.putRef(e.classRefs[j]);
 777             }
 778         }
 779     }
 780 
 781     void writeMemberRefs(byte tag, Entry[] cpMap, CPRefBand cp_class, CPRefBand cp_desc) throws IOException {
 782         for (int i = 0; i < cpMap.length; i++) {
 783             MemberEntry e = (MemberEntry) cpMap[i];
 784             cp_class.putRef(e.classRef);
 785             cp_desc.putRef(e.descRef);
 786         }
 787     }
 788 
 789     void writeFiles() throws IOException {
 790         int numFiles = pkg.files.size();
 791         if (numFiles == 0)  return;
 792         int options = archiveOptions;
 793         boolean haveSizeHi  = testBit(options, AO_HAVE_FILE_SIZE_HI);
 794         boolean haveModtime = testBit(options, AO_HAVE_FILE_MODTIME);
 795         boolean haveOptions = testBit(options, AO_HAVE_FILE_OPTIONS);
 796         if (!haveOptions) {
 797             for (File file : pkg.files) {
 798                 if (file.isClassStub()) {
 799                     haveOptions = true;
 800                     options |= AO_HAVE_FILE_OPTIONS;
 801                     archiveOptions = options;
 802                     break;
 803                 }
 804             }
 805         }
 806         if (haveSizeHi || haveModtime || haveOptions || !pkg.files.isEmpty()) {
 807             options |= AO_HAVE_FILE_HEADERS;
 808             archiveOptions = options;
 809         }
 810         for (File file : pkg.files) {
 811             file_name.putRef(file.name);
 812             long len = file.getFileLength();
 813             file_size_lo.putInt((int)len);
 814             if (haveSizeHi)
 815                 file_size_hi.putInt((int)(len >>> 32));
 816             if (haveModtime)
 817                 file_modtime.putInt(file.modtime - pkg.default_modtime);
 818             if (haveOptions)
 819                 file_options.putInt(file.options);
 820             file.writeTo(file_bits.collectorStream());
 821             if (verbose > 1)
 822                 Utils.log.fine("Wrote "+len+" bytes of "+file.name.stringValue());
 823         }
 824         if (verbose > 0)
 825             Utils.log.info("Wrote "+numFiles+" resource files");
 826     }
 827 
 828     void collectAttributeLayouts() {
 829         maxFlags = new int[ATTR_CONTEXT_LIMIT];
 830         allLayouts = new FixedList<>(ATTR_CONTEXT_LIMIT);
 831         for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
 832             allLayouts.set(i, new HashMap<>());
 833         }
 834         // Collect maxFlags and allLayouts.
 835         for (Class cls : pkg.classes) {
 836             visitAttributeLayoutsIn(ATTR_CONTEXT_CLASS, cls);
 837             for (Class.Field f : cls.getFields()) {
 838                 visitAttributeLayoutsIn(ATTR_CONTEXT_FIELD, f);
 839             }
 840             for (Class.Method m : cls.getMethods()) {
 841                 visitAttributeLayoutsIn(ATTR_CONTEXT_METHOD, m);
 842                 if (m.code != null) {
 843                     visitAttributeLayoutsIn(ATTR_CONTEXT_CODE, m.code);
 844                 }
 845             }
 846         }
 847         // If there are many species of attributes, use 63-bit flags.
 848         for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
 849             int nl = allLayouts.get(i).size();
 850             boolean haveLongFlags = haveFlagsHi(i);
 851             final int TOO_MANY_ATTRS = 32 /*int flag size*/
 852                 - 12 /*typical flag bits in use*/
 853                 + 4  /*typical number of OK overflows*/;
 854             if (nl >= TOO_MANY_ATTRS) {  // heuristic
 855                 int mask = 1<<(LG_AO_HAVE_XXX_FLAGS_HI+i);
 856                 archiveOptions |= mask;
 857                 haveLongFlags = true;
 858                 if (verbose > 0)
 859                    Utils.log.info("Note: Many "+Attribute.contextName(i)+" attributes forces 63-bit flags");
 860             }
 861             if (verbose > 1) {
 862                 Utils.log.fine(Attribute.contextName(i)+".maxFlags = 0x"+Integer.toHexString(maxFlags[i]));
 863                 Utils.log.fine(Attribute.contextName(i)+".#layouts = "+nl);
 864             }
 865             assert(haveFlagsHi(i) == haveLongFlags);
 866         }
 867         initAttrIndexLimit();
 868 
 869         // Standard indexes can never conflict with flag bits.  Assert it.
 870         for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
 871             assert((attrFlagMask[i] & maxFlags[i]) == 0);
 872         }
 873         // Collect counts for both predefs. and custom defs.
 874         // Decide on custom, local attribute definitions.
 875         backCountTable = new HashMap<>();
 876         attrCounts = new int[ATTR_CONTEXT_LIMIT][];
 877         for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
 878             // Now the remaining defs in allLayouts[i] need attr. indexes.
 879             // Fill up unused flag bits with new defs.
 880             // Unused bits are those which are not used by predefined attrs,
 881             // and which are always clear in the classfiles.
 882             long avHiBits = ~(maxFlags[i] | attrFlagMask[i]);
 883             assert(attrIndexLimit[i] > 0);
 884             assert(attrIndexLimit[i] < 64);  // all bits fit into a Java long
 885             avHiBits &= (1L<<attrIndexLimit[i])-1;
 886             int nextLoBit = 0;
 887             Map<Attribute.Layout, int[]> defMap = allLayouts.get(i);
 888             @SuppressWarnings({"unchecked", "rawtypes"})
 889             Map.Entry<Attribute.Layout, int[]>[] layoutsAndCounts =
 890                     new Map.Entry[defMap.size()];
 891             defMap.entrySet().toArray(layoutsAndCounts);
 892             // Sort by count, most frequent first.
 893             // Predefs. participate in this sort, though it does not matter.
 894             Arrays.sort(layoutsAndCounts,
 895                         new Comparator<>() {
 896                 public int compare(Map.Entry<Attribute.Layout, int[]> e0,
 897                                    Map.Entry<Attribute.Layout, int[]> e1) {
 898                     // Primary sort key is count, reversed.
 899                     int r = -(e0.getValue()[0] - e1.getValue()[0]);
 900                     if (r != 0)  return r;
 901                     return e0.getKey().compareTo(e1.getKey());
 902                 }
 903             });
 904             attrCounts[i] = new int[attrIndexLimit[i]+layoutsAndCounts.length];
 905             for (int j = 0; j < layoutsAndCounts.length; j++) {
 906                 Map.Entry<Attribute.Layout, int[]> e = layoutsAndCounts[j];
 907                 Attribute.Layout def = e.getKey();
 908                 int count = e.getValue()[0];
 909                 int index;
 910                 Integer predefIndex = attrIndexTable.get(def);
 911                 if (predefIndex != null) {
 912                     // The index is already set.
 913                     index = predefIndex.intValue();
 914                 } else if (avHiBits != 0) {
 915                     while ((avHiBits & 1) == 0) {
 916                         avHiBits >>>= 1;
 917                         nextLoBit += 1;
 918                     }
 919                     avHiBits -= 1;  // clear low bit; we are using it now
 920                     // Update attrIndexTable:
 921                     index = setAttributeLayoutIndex(def, nextLoBit);
 922                 } else {
 923                     // Update attrIndexTable:
 924                     index = setAttributeLayoutIndex(def, ATTR_INDEX_OVERFLOW);
 925                 }
 926 
 927                 // Now that we know the index, record the count of this def.
 928                 attrCounts[i][index] = count;
 929 
 930                 // For all callables in the def, keep a tally of back-calls.
 931                 Attribute.Layout.Element[] cbles = def.getCallables();
 932                 final int[] bc = new int[cbles.length];
 933                 for (int k = 0; k < cbles.length; k++) {
 934                     assert(cbles[k].kind == Attribute.EK_CBLE);
 935                     if (!cbles[k].flagTest(Attribute.EF_BACK)) {
 936                         bc[k] = -1;  // no count to accumulate here
 937                     }
 938                 }
 939                 backCountTable.put(def, bc);
 940 
 941                 if (predefIndex == null) {
 942                     // Make sure the package CP can name the local attribute.
 943                     Entry ne = ConstantPool.getUtf8Entry(def.name());
 944                     String layout = def.layoutForClassVersion(getHighestClassVersion());
 945                     Entry le = ConstantPool.getUtf8Entry(layout);
 946                     requiredEntries.add(ne);
 947                     requiredEntries.add(le);
 948                     if (verbose > 0) {
 949                         if (index < attrIndexLimit[i])
 950                            Utils.log.info("Using free flag bit 1<<"+index+" for "+count+" occurrences of "+def);
 951                         else
 952                             Utils.log.info("Using overflow index "+index+" for "+count+" occurrences of "+def);
 953                     }
 954                 }
 955             }
 956         }
 957         // Later, when emitting attr_definition_bands, we will look at
 958         // attrDefSeen and attrDefs at position 32/63 and beyond.
 959         // The attrIndexTable will provide elements of xxx_attr_indexes bands.
 960 
 961         // Done with scratch variables:
 962         maxFlags = null;
 963         allLayouts = null;
 964     }
 965 
 966     // Scratch variables for processing attributes and flags.
 967     int[] maxFlags;
 968     List<Map<Attribute.Layout, int[]>> allLayouts;
 969 
 970     void visitAttributeLayoutsIn(int ctype, Attribute.Holder h) {
 971         // Make note of which flags appear in the class file.
 972         // Set them in maxFlags.
 973         maxFlags[ctype] |= h.flags;
 974         for (Attribute a : h.getAttributes()) {
 975             Attribute.Layout def = a.layout();
 976             Map<Attribute.Layout, int[]> defMap = allLayouts.get(ctype);
 977             int[] count = defMap.get(def);
 978             if (count == null) {
 979                 defMap.put(def, count = new int[1]);
 980             }
 981             if (count[0] < Integer.MAX_VALUE) {
 982                 count[0] += 1;
 983             }
 984         }
 985     }
 986 
 987     Attribute.Layout[] attrDefsWritten;
 988 
 989     void writeAttrDefs() throws IOException {
 990         List<Object[]> defList = new ArrayList<>();
 991         for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
 992             int limit = attrDefs.get(i).size();
 993             for (int j = 0; j < limit; j++) {
 994                 int header = i;  // ctype
 995                 if (j < attrIndexLimit[i]) {
 996                     header |= ((j + ADH_BIT_IS_LSB) << ADH_BIT_SHIFT);
 997                     assert(header < 0x100);  // must fit into a byte
 998                     // (...else header is simply ctype, with zero high bits.)
 999                     if (!testBit(attrDefSeen[i], 1L<<j)) {
1000                         // either undefined or predefined; nothing to write
1001                         continue;
1002                     }
1003                 }
1004                 Attribute.Layout def = attrDefs.get(i).get(j);
1005                 defList.add(new Object[]{ Integer.valueOf(header), def });
1006                 assert(Integer.valueOf(j).equals(attrIndexTable.get(def)));
1007             }
1008         }
1009         // Sort the new attr defs into some "natural" order.
1010         int numAttrDefs = defList.size();
1011         Object[][] defs = new Object[numAttrDefs][];
1012         defList.toArray(defs);
1013         Arrays.sort(defs, new Comparator<>() {
1014             public int compare(Object[] a0, Object[] a1) {
1015                 // Primary sort key is attr def header.
1016                 @SuppressWarnings("unchecked")
1017                 int r = ((Comparable)a0[0]).compareTo(a1[0]);
1018                 if (r != 0)  return r;
1019                 Integer ind0 = attrIndexTable.get(a0[1]);
1020                 Integer ind1 = attrIndexTable.get(a1[1]);
1021                 // Secondary sort key is attribute index.
1022                 // (This must be so, in order to keep overflow attr order.)
1023                 assert(ind0 != null);
1024                 assert(ind1 != null);
1025                 return ind0.compareTo(ind1);
1026             }
1027         });
1028         attrDefsWritten = new Attribute.Layout[numAttrDefs];
1029         try (PrintStream dump = !optDumpBands ? null
1030                  : new PrintStream(getDumpStream(attr_definition_headers, ".def")))
1031         {
1032             int[] indexForDebug = Arrays.copyOf(attrIndexLimit, ATTR_CONTEXT_LIMIT);
1033             for (int i = 0; i < defs.length; i++) {
1034                 int header = ((Integer)defs[i][0]).intValue();
1035                 Attribute.Layout def = (Attribute.Layout) defs[i][1];
1036                 attrDefsWritten[i] = def;
1037                 assert((header & ADH_CONTEXT_MASK) == def.ctype());
1038                 attr_definition_headers.putByte(header);
1039                 attr_definition_name.putRef(ConstantPool.getUtf8Entry(def.name()));
1040                 String layout = def.layoutForClassVersion(getHighestClassVersion());
1041                 attr_definition_layout.putRef(ConstantPool.getUtf8Entry(layout));
1042                 // Check that we are transmitting that correct attribute index:
1043                 boolean debug = false;
1044                 assert(debug = true);
1045                 if (debug) {
1046                     int hdrIndex = (header >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB;
1047                     if (hdrIndex < 0)  hdrIndex = indexForDebug[def.ctype()]++;
1048                     int realIndex = (attrIndexTable.get(def)).intValue();
1049                     assert(hdrIndex == realIndex);
1050                 }
1051                 if (dump != null) {
1052                     int index = (header >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB;
1053                     dump.println(index+" "+def);
1054                 }
1055             }
1056         }
1057     }
1058 
1059     void writeAttrCounts() throws IOException {
1060         // Write the four xxx_attr_calls bands.
1061         for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) {
1062             MultiBand xxx_attr_bands = attrBands[ctype];
1063             IntBand xxx_attr_calls = getAttrBand(xxx_attr_bands, AB_ATTR_CALLS);
1064             Attribute.Layout[] defs = new Attribute.Layout[attrDefs.get(ctype).size()];
1065             attrDefs.get(ctype).toArray(defs);
1066             for (boolean predef = true; ; predef = false) {
1067                 for (int ai = 0; ai < defs.length; ai++) {
1068                     Attribute.Layout def = defs[ai];
1069                     if (def == null)  continue;  // unused index
1070                     if (predef != isPredefinedAttr(ctype, ai))
1071                         continue;  // wrong pass
1072                     int totalCount = attrCounts[ctype][ai];
1073                     if (totalCount == 0)
1074                         continue;  // irrelevant
1075                     int[] bc = backCountTable.get(def);
1076                     for (int j = 0; j < bc.length; j++) {
1077                         if (bc[j] >= 0) {
1078                             int backCount = bc[j];
1079                             bc[j] = -1;  // close out; do not collect further counts
1080                             xxx_attr_calls.putInt(backCount);
1081                             assert(def.getCallables()[j].flagTest(Attribute.EF_BACK));
1082                         } else {
1083                             assert(!def.getCallables()[j].flagTest(Attribute.EF_BACK));
1084                         }
1085                     }
1086                 }
1087                 if (!predef)  break;
1088             }
1089         }
1090     }
1091 
1092     void trimClassAttributes() {
1093         for (Class cls : pkg.classes) {
1094             // Replace "obvious" SourceFile attrs by null.
1095             cls.minimizeSourceFile();
1096             // BootstrapMethods should never have been inserted.
1097             assert(cls.getAttribute(Package.attrBootstrapMethodsEmpty) == null);
1098         }
1099     }
1100 
1101     void collectInnerClasses() {
1102         // Capture inner classes, removing them from individual classes.
1103         // Irregular inner classes must stay local, though.
1104         Map<ClassEntry, InnerClass> allICMap = new HashMap<>();
1105         // First, collect a consistent global set.
1106         for (Class cls : pkg.classes) {
1107             if (!cls.hasInnerClasses())  continue;
1108             for (InnerClass ic : cls.getInnerClasses()) {
1109                 InnerClass pic = allICMap.put(ic.thisClass, ic);
1110                 if (pic != null && !pic.equals(ic) && pic.predictable) {
1111                     // Different ICs.  Choose the better to make global.
1112                     allICMap.put(pic.thisClass, pic);
1113                 }
1114             }
1115         }
1116 
1117         InnerClass[] allICs = new InnerClass[allICMap.size()];
1118         allICMap.values().toArray(allICs);
1119         allICMap = null;  // done with it
1120 
1121         // Note: The InnerClasses attribute must be in a valid order,
1122         // so that A$B always occurs earlier than A$B$C.  This is an
1123         // important side-effect of sorting lexically by class name.
1124         Arrays.sort(allICs);  // put in canonical order
1125         pkg.setAllInnerClasses(Arrays.asList(allICs));
1126 
1127         // Next, empty out of every local set the consistent entries.
1128         // Calculate whether there is any remaining need to have a local
1129         // set, and whether it needs to be locked.
1130         for (Class cls : pkg.classes) {
1131             cls.minimizeLocalICs();
1132         }
1133     }
1134 
1135     void writeInnerClasses() throws IOException {
1136         for (InnerClass ic : pkg.getAllInnerClasses()) {
1137             int flags = ic.flags;
1138             assert((flags & ACC_IC_LONG_FORM) == 0);
1139             if (!ic.predictable) {
1140                 flags |= ACC_IC_LONG_FORM;
1141             }
1142             ic_this_class.putRef(ic.thisClass);
1143             ic_flags.putInt(flags);
1144             if (!ic.predictable) {
1145                 ic_outer_class.putRef(ic.outerClass);
1146                 ic_name.putRef(ic.name);
1147             }
1148         }
1149     }
1150 
1151     /** If there are any extra InnerClasses entries to write which are
1152      *  not already implied by the global table, put them into a
1153      *  local attribute.  This is expected to be rare.
1154      */
1155     void writeLocalInnerClasses(Class cls) throws IOException {
1156         List<InnerClass> localICs = cls.getInnerClasses();
1157         class_InnerClasses_N.putInt(localICs.size());
1158         for(InnerClass ic : localICs) {
1159             class_InnerClasses_RC.putRef(ic.thisClass);
1160             // Is it redundant with the global version?
1161             if (ic.equals(pkg.getGlobalInnerClass(ic.thisClass))) {
1162                 // A zero flag means copy a global IC here.
1163                 class_InnerClasses_F.putInt(0);
1164             } else {
1165                 int flags = ic.flags;
1166                 if (flags == 0)
1167                     flags = ACC_IC_LONG_FORM;  // force it to be non-zero
1168                 class_InnerClasses_F.putInt(flags);
1169                 class_InnerClasses_outer_RCN.putRef(ic.outerClass);
1170                 class_InnerClasses_name_RUN.putRef(ic.name);
1171             }
1172         }
1173     }
1174 
1175     void writeClassesAndByteCodes() throws IOException {
1176         Class[] classes = new Class[pkg.classes.size()];
1177         pkg.classes.toArray(classes);
1178         // Note:  This code respects the order in which caller put classes.
1179         if (verbose > 0)
1180             Utils.log.info("  ...scanning "+classes.length+" classes...");
1181 
1182         int nwritten = 0;
1183         for (int i = 0; i < classes.length; i++) {
1184             // Collect the class body, sans bytecodes.
1185             Class cls = classes[i];
1186             if (verbose > 1)
1187                 Utils.log.fine("Scanning "+cls);
1188 
1189             ClassEntry   thisClass  = cls.thisClass;
1190             ClassEntry   superClass = cls.superClass;
1191             ClassEntry[] interfaces = cls.interfaces;
1192             // Encode rare case of null superClass as thisClass:
1193             assert(superClass != thisClass);  // bad class file!?
1194             if (superClass == null)  superClass = thisClass;
1195             class_this.putRef(thisClass);
1196             class_super.putRef(superClass);
1197             class_interface_count.putInt(cls.interfaces.length);
1198             for (int j = 0; j < interfaces.length; j++) {
1199                 class_interface.putRef(interfaces[j]);
1200             }
1201 
1202             writeMembers(cls);
1203             writeAttrs(ATTR_CONTEXT_CLASS, cls, cls);
1204 
1205             nwritten++;
1206             if (verbose > 0 && (nwritten % 1000) == 0)
1207                 Utils.log.info("Have scanned "+nwritten+" classes...");
1208         }
1209     }
1210 
1211     void writeMembers(Class cls) throws IOException {
1212         List<Class.Field> fields = cls.getFields();
1213         class_field_count.putInt(fields.size());
1214         for (Class.Field f : fields) {
1215             field_descr.putRef(f.getDescriptor());
1216             writeAttrs(ATTR_CONTEXT_FIELD, f, cls);
1217         }
1218 
1219         List<Class.Method> methods = cls.getMethods();
1220         class_method_count.putInt(methods.size());
1221         for (Class.Method m : methods) {
1222             method_descr.putRef(m.getDescriptor());
1223             writeAttrs(ATTR_CONTEXT_METHOD, m, cls);
1224             assert((m.code != null) == (m.getAttribute(attrCodeEmpty) != null));
1225             if (m.code != null) {
1226                 writeCodeHeader(m.code);
1227                 writeByteCodes(m.code);
1228             }
1229         }
1230     }
1231 
1232     void writeCodeHeader(Code c) throws IOException {
1233         boolean attrsOK = testBit(archiveOptions, AO_HAVE_ALL_CODE_FLAGS);
1234         int na = c.attributeSize();
1235         int sc = shortCodeHeader(c);
1236         if (!attrsOK && na > 0)
1237             // We must write flags, and can only do so for long headers.
1238             sc = LONG_CODE_HEADER;
1239         if (verbose > 2) {
1240             int siglen = c.getMethod().getArgumentSize();
1241             Utils.log.fine("Code sizes info "+c.max_stack+" "+c.max_locals+" "+c.getHandlerCount()+" "+siglen+" "+na+(sc > 0 ? " SHORT="+sc : ""));
1242         }
1243         code_headers.putByte(sc);
1244         if (sc == LONG_CODE_HEADER) {
1245             code_max_stack.putInt(c.getMaxStack());
1246             code_max_na_locals.putInt(c.getMaxNALocals());
1247             code_handler_count.putInt(c.getHandlerCount());
1248         } else {
1249             assert(attrsOK || na == 0);
1250             assert(c.getHandlerCount() < shortCodeHeader_h_limit);
1251         }
1252         writeCodeHandlers(c);
1253         if (sc == LONG_CODE_HEADER || attrsOK)
1254             writeAttrs(ATTR_CONTEXT_CODE, c, c.thisClass());
1255     }
1256 
1257     void writeCodeHandlers(Code c) throws IOException {
1258         int sum, del;
1259         for (int j = 0, jmax = c.getHandlerCount(); j < jmax; j++) {
1260             code_handler_class_RCN.putRef(c.handler_class[j]); // null OK
1261             // Encode end as offset from start, and catch as offset from end,
1262             // because they are strongly correlated.
1263             sum = c.encodeBCI(c.handler_start[j]);
1264             code_handler_start_P.putInt(sum);
1265             del = c.encodeBCI(c.handler_end[j]) - sum;
1266             code_handler_end_PO.putInt(del);
1267             sum += del;
1268             del = c.encodeBCI(c.handler_catch[j]) - sum;
1269             code_handler_catch_PO.putInt(del);
1270         }
1271     }
1272 
1273     // Generic routines for writing attributes and flags of
1274     // classes, fields, methods, and codes.
1275     void writeAttrs(int ctype,
1276                     final Attribute.Holder h,
1277                     Class cls) throws IOException {
1278         MultiBand xxx_attr_bands = attrBands[ctype];
1279         IntBand xxx_flags_hi = getAttrBand(xxx_attr_bands, AB_FLAGS_HI);
1280         IntBand xxx_flags_lo = getAttrBand(xxx_attr_bands, AB_FLAGS_LO);
1281         boolean haveLongFlags = haveFlagsHi(ctype);
1282         assert(attrIndexLimit[ctype] == (haveLongFlags? 63: 32));
1283         if (h.attributes == null) {
1284             xxx_flags_lo.putInt(h.flags);  // no extra bits to set here
1285             if (haveLongFlags)
1286                 xxx_flags_hi.putInt(0);
1287             return;
1288         }
1289         if (verbose > 3)
1290             Utils.log.fine("Transmitting attrs for "+h+" flags="+Integer.toHexString(h.flags));
1291 
1292         long flagMask = attrFlagMask[ctype];  // which flags are attr bits?
1293         long flagsToAdd = 0;
1294         int overflowCount = 0;
1295         for (Attribute a : h.attributes) {
1296             Attribute.Layout def = a.layout();
1297             int index = (attrIndexTable.get(def)).intValue();
1298             assert(attrDefs.get(ctype).get(index) == def);
1299             if (verbose > 3)
1300                 Utils.log.fine("add attr @"+index+" "+a+" in "+h);
1301             if (index < attrIndexLimit[ctype] && testBit(flagMask, 1L<<index)) {
1302                 if (verbose > 3)
1303                     Utils.log.fine("Adding flag bit 1<<"+index+" in "+Long.toHexString(flagMask));
1304                 assert(!testBit(h.flags, 1L<<index));
1305                 flagsToAdd |= (1L<<index);
1306                 flagMask -= (1L<<index);  // do not use this bit twice here
1307             } else {
1308                 // an overflow attr.
1309                 flagsToAdd |= (1L<<X_ATTR_OVERFLOW);
1310                 overflowCount += 1;
1311                 if (verbose > 3)
1312                     Utils.log.fine("Adding overflow attr #"+overflowCount);
1313                 IntBand xxx_attr_indexes = getAttrBand(xxx_attr_bands, AB_ATTR_INDEXES);
1314                 xxx_attr_indexes.putInt(index);
1315                 // System.out.println("overflow @"+index);
1316             }
1317             if (def.bandCount == 0) {
1318                 if (def == attrInnerClassesEmpty) {
1319                     // Special logic to write this attr.
1320                     writeLocalInnerClasses((Class) h);
1321                     continue;
1322                 }
1323                 // Empty attr; nothing more to write here.
1324                 continue;
1325             }
1326             assert(a.fixups == null);
1327             final Band[] ab = attrBandTable.get(def);
1328             assert(ab != null);
1329             assert(ab.length == def.bandCount);
1330             final int[] bc = backCountTable.get(def);
1331             assert(bc != null);
1332             assert(bc.length == def.getCallables().length);
1333             // Write one attribute of type def into ab.
1334             if (verbose > 2)  Utils.log.fine("writing "+a+" in "+h);
1335             boolean isCV = (ctype == ATTR_CONTEXT_FIELD && def == attrConstantValue);
1336             if (isCV)  setConstantValueIndex((Class.Field)h);
1337             a.parse(cls, a.bytes(), 0, a.size(),
1338                       new Attribute.ValueStream() {
1339                 public void putInt(int bandIndex, int value) {
1340                     ((IntBand) ab[bandIndex]).putInt(value);
1341                 }
1342                 public void putRef(int bandIndex, Entry ref) {
1343                     ((CPRefBand) ab[bandIndex]).putRef(ref);
1344                 }
1345                 public int encodeBCI(int bci) {
1346                     Code code = (Code) h;
1347                     return code.encodeBCI(bci);
1348                 }
1349                 public void noteBackCall(int whichCallable) {
1350                     assert(bc[whichCallable] >= 0);
1351                     bc[whichCallable] += 1;
1352                 }
1353             });
1354             if (isCV)  setConstantValueIndex(null);  // clean up
1355         }
1356 
1357         if (overflowCount > 0) {
1358             IntBand xxx_attr_count = getAttrBand(xxx_attr_bands, AB_ATTR_COUNT);
1359             xxx_attr_count.putInt(overflowCount);
1360         }
1361 
1362         xxx_flags_lo.putInt(h.flags | (int)flagsToAdd);
1363         if (haveLongFlags)
1364             xxx_flags_hi.putInt((int)(flagsToAdd >>> 32));
1365         else
1366             assert((flagsToAdd >>> 32) == 0);
1367         assert((h.flags & flagsToAdd) == 0)
1368             : (h+".flags="
1369                 +Integer.toHexString(h.flags)+"^"
1370                 +Long.toHexString(flagsToAdd));
1371     }
1372 
1373     // temporary scratch variables for processing code blocks
1374     private Code                 curCode;
1375     private Class                curClass;
1376     private Entry[] curCPMap;
1377     private void beginCode(Code c) {
1378         assert(curCode == null);
1379         curCode = c;
1380         curClass = c.m.thisClass();
1381         curCPMap = c.getCPMap();
1382     }
1383     private void endCode() {
1384         curCode = null;
1385         curClass = null;
1386         curCPMap = null;
1387     }
1388 
1389     // Return an _invokeinit_op variant, if the instruction matches one,
1390     // else -1.
1391     private int initOpVariant(Instruction i, Entry newClass) {
1392         if (i.getBC() != _invokespecial)  return -1;
1393         MemberEntry ref = (MemberEntry) i.getCPRef(curCPMap);
1394         if ("<init>".equals(ref.descRef.nameRef.stringValue()) == false)
1395             return -1;
1396         ClassEntry refClass = ref.classRef;
1397         if (refClass == curClass.thisClass)
1398             return _invokeinit_op+_invokeinit_self_option;
1399         if (refClass == curClass.superClass)
1400             return _invokeinit_op+_invokeinit_super_option;
1401         if (refClass == newClass)
1402             return _invokeinit_op+_invokeinit_new_option;
1403         return -1;
1404     }
1405 
1406     // Return a _self_linker_op variant, if the instruction matches one,
1407     // else -1.
1408     private int selfOpVariant(Instruction i) {
1409         int bc = i.getBC();
1410         if (!(bc >= _first_linker_op && bc <= _last_linker_op))  return -1;
1411         MemberEntry ref = (MemberEntry) i.getCPRef(curCPMap);
1412         // do not optimize this case, simply fall back to regular coding
1413         if ((bc == _invokespecial || bc == _invokestatic) &&
1414                 ref.tagEquals(CONSTANT_InterfaceMethodref))
1415             return -1;
1416         ClassEntry refClass = ref.classRef;
1417         int self_bc = _self_linker_op + (bc - _first_linker_op);
1418         if (refClass == curClass.thisClass)
1419             return self_bc;
1420         if (refClass == curClass.superClass)
1421             return self_bc + _self_linker_super_flag;
1422         return -1;
1423     }
1424 
1425     void writeByteCodes(Code code) throws IOException {
1426         beginCode(code);
1427         IndexGroup cp = pkg.cp;
1428 
1429         // true if the previous instruction is an aload to absorb
1430         boolean prevAload = false;
1431 
1432         // class of most recent new; helps compress <init> calls
1433         Entry newClass = null;
1434 
1435         for (Instruction i = code.instructionAt(0); i != null; i = i.next()) {
1436             // %%% Add a stress mode which issues _ref/_byte_escape.
1437             if (verbose > 3)  Utils.log.fine(i.toString());
1438 
1439             if (i.isNonstandard()) {
1440                 // Crash and burn with a complaint if there are funny
1441                 // bytecodes in this class file.
1442                 String complaint = code.getMethod()
1443                     +" contains an unrecognized bytecode "+i
1444                     +"; please use the pass-file option on this class.";
1445                 Utils.log.warning(complaint);
1446                 throw new IOException(complaint);
1447             }
1448 
1449             if (i.isWide()) {
1450                 if (verbose > 1) {
1451                     Utils.log.fine("_wide opcode in "+code);
1452                     Utils.log.fine(i.toString());
1453                 }
1454                 bc_codes.putByte(_wide);
1455                 codeHist[_wide]++;
1456             }
1457 
1458             int bc = i.getBC();
1459 
1460             // Begin "bc_linker" compression.
1461             if (bc == _aload_0) {
1462                 // Try to group aload_0 with a following operation.
1463                 Instruction ni = code.instructionAt(i.getNextPC());
1464                 if (selfOpVariant(ni) >= 0) {
1465                     prevAload = true;
1466                     continue;
1467                 }
1468             }
1469 
1470             // Test for <init> invocations:
1471             int init_bc = initOpVariant(i, newClass);
1472             if (init_bc >= 0) {
1473                 if (prevAload) {
1474                     // get rid of it
1475                     bc_codes.putByte(_aload_0);
1476                     codeHist[_aload_0]++;
1477                     prevAload = false;  //used up
1478                 }
1479                 // Write special bytecode.
1480                 bc_codes.putByte(init_bc);
1481                 codeHist[init_bc]++;
1482                 MemberEntry ref = (MemberEntry) i.getCPRef(curCPMap);
1483                 // Write operand to a separate band.
1484                 int coding = cp.getOverloadingIndex(ref);
1485                 bc_initref.putInt(coding);
1486                 continue;
1487             }
1488 
1489             int self_bc = selfOpVariant(i);
1490             if (self_bc >= 0) {
1491                 boolean isField = Instruction.isFieldOp(bc);
1492                 boolean isSuper = (self_bc >= _self_linker_op+_self_linker_super_flag);
1493                 boolean isAload = prevAload;
1494                 prevAload = false;  //used up
1495                 if (isAload)
1496                     self_bc += _self_linker_aload_flag;
1497                 // Write special bytecode.
1498                 bc_codes.putByte(self_bc);
1499                 codeHist[self_bc]++;
1500                 // Write field or method ref to a separate band.
1501                 MemberEntry ref = (MemberEntry) i.getCPRef(curCPMap);
1502                 CPRefBand bc_which = selfOpRefBand(self_bc);
1503                 Index which_ix = cp.getMemberIndex(ref.tag, ref.classRef);
1504                 bc_which.putRef(ref, which_ix);
1505                 continue;
1506             }
1507             assert(!prevAload);
1508             // End "bc_linker" compression.
1509 
1510             // Normal bytecode.
1511             codeHist[bc]++;
1512             switch (bc) {
1513             case _tableswitch: // apc:  (df, lo, hi, (hi-lo+1)*(label))
1514             case _lookupswitch: // apc:  (df, nc, nc*(case, label))
1515                 bc_codes.putByte(bc);
1516                 Instruction.Switch isw = (Instruction.Switch) i;
1517                 // Note that we do not write the alignment bytes.
1518                 int apc = isw.getAlignedPC();
1519                 int npc = isw.getNextPC();
1520                 // write a length specification into the bytecode stream
1521                 int caseCount = isw.getCaseCount();
1522                 bc_case_count.putInt(caseCount);
1523                 putLabel(bc_label, code, i.getPC(), isw.getDefaultLabel());
1524                 for (int j = 0; j < caseCount; j++) {
1525                     putLabel(bc_label, code, i.getPC(), isw.getCaseLabel(j));
1526                 }
1527                 // Transmit case values in their own band.
1528                 if (bc == _tableswitch) {
1529                     bc_case_value.putInt(isw.getCaseValue(0));
1530                 } else {
1531                     for (int j = 0; j < caseCount; j++) {
1532                         bc_case_value.putInt(isw.getCaseValue(j));
1533                     }
1534                 }
1535                 // Done with the switch.
1536                 continue;
1537             }
1538 
1539             int branch = i.getBranchLabel();
1540             if (branch >= 0) {
1541                 bc_codes.putByte(bc);
1542                 putLabel(bc_label, code, i.getPC(), branch);
1543                 continue;
1544             }
1545             Entry ref = i.getCPRef(curCPMap);
1546             if (ref != null) {
1547                 if (bc == _new)  newClass = ref;
1548                 if (bc == _ldc)  ldcHist[ref.tag]++;
1549                 CPRefBand bc_which;
1550                 int vbc = bc;
1551                 switch (i.getCPTag()) {
1552                 case CONSTANT_LoadableValue:
1553                     switch (ref.tag) {
1554                     case CONSTANT_Integer:
1555                         bc_which = bc_intref;
1556                         switch (bc) {
1557                         case _ldc:    vbc = _ildc; break;
1558                         case _ldc_w:  vbc = _ildc_w; break;
1559                         default:      assert(false);
1560                         }
1561                         break;
1562                     case CONSTANT_Float:
1563                         bc_which = bc_floatref;
1564                         switch (bc) {
1565                         case _ldc:    vbc = _fldc; break;
1566                         case _ldc_w:  vbc = _fldc_w; break;
1567                         default:      assert(false);
1568                         }
1569                         break;
1570                     case CONSTANT_Long:
1571                         bc_which = bc_longref;
1572                         assert(bc == _ldc2_w);
1573                         vbc = _lldc2_w;
1574                         break;
1575                     case CONSTANT_Double:
1576                         bc_which = bc_doubleref;
1577                         assert(bc == _ldc2_w);
1578                         vbc = _dldc2_w;
1579                         break;
1580                     case CONSTANT_String:
1581                         bc_which = bc_stringref;
1582                         switch (bc) {
1583                         case _ldc:    vbc = _sldc; break;
1584                         case _ldc_w:  vbc = _sldc_w; break;
1585                         default:      assert(false);
1586                         }
1587                         break;
1588                     case CONSTANT_Class:
1589                         bc_which = bc_classref;
1590                         switch (bc) {
1591                         case _ldc:    vbc = _cldc; break;
1592                         case _ldc_w:  vbc = _cldc_w; break;
1593                         default:      assert(false);
1594                         }
1595                         break;
1596                     default:
1597                         // CONSTANT_MethodHandle, etc.
1598                         if (getHighestClassVersion().lessThan(JAVA7_MAX_CLASS_VERSION)) {
1599                             throw new IOException("bad class file major version for Java 7 ldc");
1600                         }
1601                         bc_which = bc_loadablevalueref;
1602                         switch (bc) {
1603                         case _ldc:    vbc = _qldc; break;
1604                         case _ldc_w:  vbc = _qldc_w; break;
1605                         default:      assert(false);
1606                         }
1607                     }
1608                     break;
1609                 case CONSTANT_Class:
1610                     // Use a special shorthand for the current class:
1611                     if (ref == curClass.thisClass)  ref = null;
1612                     bc_which = bc_classref; break;
1613                 case CONSTANT_Fieldref:
1614                     bc_which = bc_fieldref; break;
1615                 case CONSTANT_Methodref:
1616                     if (ref.tagEquals(CONSTANT_InterfaceMethodref)) {
1617                         if (bc == _invokespecial)
1618                             vbc = _invokespecial_int;
1619                         if (bc == _invokestatic)
1620                             vbc = _invokestatic_int;
1621                         bc_which = bc_imethodref;
1622                     } else {
1623                         bc_which = bc_methodref;
1624                     }
1625                     break;
1626                 case CONSTANT_InterfaceMethodref:
1627                     bc_which = bc_imethodref; break;
1628                 case CONSTANT_InvokeDynamic:
1629                     bc_which = bc_indyref; break;
1630                 default:
1631                     bc_which = null;
1632                     assert(false);
1633                 }
1634                 if (ref != null && bc_which.index != null && !bc_which.index.contains(ref)) {
1635                     // Crash and burn with a complaint if there are funny
1636                     // references for this bytecode instruction.
1637                     // Example:  invokestatic of a CONSTANT_InterfaceMethodref.
1638                     String complaint = code.getMethod() +
1639                         " contains a bytecode " + i +
1640                         " with an unsupported constant reference; please use the pass-file option on this class.";
1641                     Utils.log.warning(complaint);
1642                     throw new IOException(complaint);
1643                 }
1644                 bc_codes.putByte(vbc);
1645                 bc_which.putRef(ref);
1646                 // handle trailing junk
1647                 if (bc == _multianewarray) {
1648                     assert(i.getConstant() == code.getByte(i.getPC()+3));
1649                     // Just dump the byte into the bipush pile
1650                     bc_byte.putByte(0xFF & i.getConstant());
1651                 } else if (bc == _invokeinterface) {
1652                     assert(i.getLength() == 5);
1653                     // Make sure the discarded bytes are sane:
1654                     assert(i.getConstant() == (1+((MemberEntry)ref).descRef.typeRef.computeSize(true)) << 8);
1655                 } else if (bc == _invokedynamic) {
1656                     if (getHighestClassVersion().lessThan(JAVA7_MAX_CLASS_VERSION)) {
1657                         throw new IOException("bad class major version for Java 7 invokedynamic");
1658                     }
1659                     assert(i.getLength() == 5);
1660                     assert(i.getConstant() == 0);  // last 2 bytes MBZ
1661                 } else {
1662                     // Make sure there is nothing else to write.
1663                     assert(i.getLength() == ((bc == _ldc)?2:3));
1664                 }
1665                 continue;
1666             }
1667             int slot = i.getLocalSlot();
1668             if (slot >= 0) {
1669                 bc_codes.putByte(bc);
1670                 bc_local.putInt(slot);
1671                 int con = i.getConstant();
1672                 if (bc == _iinc) {
1673                     if (!i.isWide()) {
1674                         bc_byte.putByte(0xFF & con);
1675                     } else {
1676                         bc_short.putInt(0xFFFF & con);
1677                     }
1678                 } else {
1679                     assert(con == 0);
1680                 }
1681                 continue;
1682             }
1683             // Generic instruction.  Copy the body.
1684             bc_codes.putByte(bc);
1685             int pc = i.getPC()+1;
1686             int npc = i.getNextPC();
1687             if (pc < npc) {
1688                 // Do a few remaining multi-byte instructions.
1689                 switch (bc) {
1690                 case _sipush:
1691                     bc_short.putInt(0xFFFF & i.getConstant());
1692                     break;
1693                 case _bipush:
1694                     bc_byte.putByte(0xFF & i.getConstant());
1695                     break;
1696                 case _newarray:
1697                     bc_byte.putByte(0xFF & i.getConstant());
1698                     break;
1699                 default:
1700                     assert(false);  // that's it
1701                 }
1702             }
1703         }
1704         bc_codes.putByte(_end_marker);
1705         bc_codes.elementCountForDebug++;
1706         codeHist[_end_marker]++;
1707         endCode();
1708     }
1709 
1710     int[] codeHist = new int[1<<8];
1711     int[] ldcHist  = new int[20];
1712     void printCodeHist() {
1713         assert(verbose > 0);
1714         String[] hist = new String[codeHist.length];
1715         int totalBytes = 0;
1716         for (int bc = 0; bc < codeHist.length; bc++) {
1717             totalBytes += codeHist[bc];
1718         }
1719         for (int bc = 0; bc < codeHist.length; bc++) {
1720             if (codeHist[bc] == 0) { hist[bc] = ""; continue; }
1721             String iname = Instruction.byteName(bc);
1722             String count = "" + codeHist[bc];
1723             count = "         ".substring(count.length()) + count;
1724             String pct = "" + (codeHist[bc] * 10000 / totalBytes);
1725             while (pct.length() < 4) {
1726                 pct = "0" + pct;
1727             }
1728             pct = pct.substring(0, pct.length()-2) + "." + pct.substring(pct.length()-2);
1729             hist[bc] = count + "  " + pct + "%  " + iname;
1730         }
1731         Arrays.sort(hist);
1732         System.out.println("Bytecode histogram ["+totalBytes+"]");
1733         for (int i = hist.length; --i >= 0; ) {
1734             if ("".equals(hist[i]))  continue;
1735             System.out.println(hist[i]);
1736         }
1737         for (int tag = 0; tag < ldcHist.length; tag++) {
1738             int count = ldcHist[tag];
1739             if (count == 0)  continue;
1740             System.out.println("ldc "+ConstantPool.tagName(tag)+" "+count);
1741         }
1742     }
1743 }