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
26package com.sun.java.util.jar.pack;
27
28import com.sun.java.util.jar.pack.ConstantPool.*;
29import com.sun.java.util.jar.pack.Package.Class;
30import com.sun.java.util.jar.pack.Package.File;
31import com.sun.java.util.jar.pack.Package.InnerClass;
32import java.io.IOException;
33import java.io.OutputStream;
34import java.io.PrintStream;
35import java.util.ArrayList;
36import java.util.Arrays;
37import java.util.Comparator;
38import java.util.HashMap;
39import java.util.HashSet;
40import java.util.List;
41import java.util.Map;
42import java.util.Set;
43import static com.sun.java.util.jar.pack.Constants.*;
44
45/**
46 * Writer for a package file.
47 * @author John Rose
48 */
49class 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().equals(""));
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}
1744