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