1/*
2 * Copyright (c) 2001, 2016, 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.ByteArrayOutputStream;
33import java.io.EOFException;
34import java.io.PrintStream;
35import java.io.FilterInputStream;
36import java.io.BufferedInputStream;
37import java.io.InputStream;
38import java.io.IOException;
39import java.util.ArrayList;
40import java.util.Map;
41import java.util.Arrays;
42import java.util.Collection;
43import java.util.Collections;
44import java.util.Comparator;
45import java.util.HashSet;
46import java.util.HashMap;
47import java.util.Iterator;
48import java.util.List;
49import java.util.ListIterator;
50import java.util.Set;
51import static com.sun.java.util.jar.pack.Constants.*;
52
53/**
54 * Reader for a package file.
55 *
56 * @see PackageWriter
57 * @author John Rose
58 */
59class PackageReader extends BandStructure {
60    Package pkg;
61    byte[] bytes;
62    LimitedBuffer in;
63    Package.Version packageVersion;
64
65    PackageReader(Package pkg, InputStream in) throws IOException {
66        this.pkg = pkg;
67        this.in = new LimitedBuffer(in);
68    }
69
70    /** A buffered input stream which is careful not to
71     *  read its underlying stream ahead of a given mark,
72     *  called the 'readLimit'.  This property declares
73     *  the maximum number of characters that future reads
74     *  can consume from the underlying stream.
75     */
76    static
77    class LimitedBuffer extends BufferedInputStream {
78        long served;     // total number of charburgers served
79        int  servedPos;  // ...as of this value of super.pos
80        long limit;      // current declared limit
81        long buffered;
82        public boolean atLimit() {
83            boolean z = (getBytesServed() == limit);
84            assert(!z || limit == buffered);
85            return z;
86        }
87        public long getBytesServed() {
88            return served + (pos - servedPos);
89        }
90        public void setReadLimit(long newLimit) {
91            if (newLimit == -1)
92                limit = -1;
93            else
94                limit = getBytesServed() + newLimit;
95        }
96        public long getReadLimit() {
97            if (limit == -1)
98                return limit;
99            else
100                return limit - getBytesServed();
101        }
102        public int read() throws IOException {
103            if (pos < count) {
104                // fast path
105                return buf[pos++] & 0xFF;
106            }
107            served += (pos - servedPos);
108            int ch = super.read();
109            servedPos = pos;
110            if (ch >= 0)  served += 1;
111            assert(served <= limit || limit == -1);
112            return ch;
113        }
114        public int read(byte b[], int off, int len) throws IOException {
115            served += (pos - servedPos);
116            int nr = super.read(b, off, len);
117            servedPos = pos;
118            if (nr >= 0)  served += nr;
119            //assert(served <= limit || limit == -1);
120            return nr;
121        }
122        public long skip(long n) throws IOException {
123            throw new RuntimeException("no skipping");
124        }
125        LimitedBuffer(InputStream originalIn) {
126            super(null, 1<<14);
127            servedPos = pos;
128            super.in = new FilterInputStream(originalIn) {
129                public int read() throws IOException {
130                    if (buffered == limit)
131                        return -1;
132                    ++buffered;
133                    return super.read();
134                }
135                public int read(byte b[], int off, int len) throws IOException {
136                    if (buffered == limit)
137                        return -1;
138                    if (limit != -1) {
139                        long remaining = limit - buffered;
140                        if (len > remaining)
141                            len = (int)remaining;
142                    }
143                    int nr = super.read(b, off, len);
144                    if (nr >= 0)  buffered += nr;
145                    return nr;
146                }
147            };
148        }
149    }
150
151    void read() throws IOException {
152        boolean ok = false;
153        try {
154            //  pack200_archive:
155            //        file_header
156            //        *band_headers :BYTE1
157            //        cp_bands
158            //        attr_definition_bands
159            //        ic_bands
160            //        class_bands
161            //        bc_bands
162            //        file_bands
163            readFileHeader();
164            readBandHeaders();
165            readConstantPool();  // cp_bands
166            readAttrDefs();
167            readInnerClasses();
168            Class[] classes = readClasses();
169            readByteCodes();
170            readFiles();     // file_bands
171            assert(archiveSize1 == 0 || in.atLimit());
172            assert(archiveSize1 == 0 ||
173                   in.getBytesServed() == archiveSize0+archiveSize1);
174            all_bands.doneDisbursing();
175
176            // As a post-pass, build constant pools and inner classes.
177            for (int i = 0; i < classes.length; i++) {
178                reconstructClass(classes[i]);
179            }
180
181            ok = true;
182        } catch (Exception ee) {
183            Utils.log.warning("Error on input: "+ee, ee);
184            if (verbose > 0)
185                Utils.log.info("Stream offsets:"+
186                                 " served="+in.getBytesServed()+
187                                 " buffered="+in.buffered+
188                                 " limit="+in.limit);
189            //if (verbose > 0)  ee.printStackTrace();
190            if (ee instanceof IOException)  throw (IOException)ee;
191            if (ee instanceof RuntimeException)  throw (RuntimeException)ee;
192            throw new Error("error unpacking", ee);
193        }
194    }
195
196    // Temporary count values, until band decoding gets rolling.
197    int[] tagCount = new int[CONSTANT_Limit];
198    int numFiles;
199    int numAttrDefs;
200    int numInnerClasses;
201    int numClasses;
202
203    void readFileHeader() throws IOException {
204        //  file_header:
205        //        archive_magic archive_header
206        readArchiveMagic();
207        readArchiveHeader();
208    }
209
210    // Local routine used to parse fixed-format scalars
211    // in the file_header:
212    private int getMagicInt32() throws IOException {
213        int res = 0;
214        for (int i = 0; i < 4; i++) {
215            res <<= 8;
216            res |= (archive_magic.getByte() & 0xFF);
217        }
218        return res;
219    }
220
221    static final int MAGIC_BYTES = 4;
222
223    void readArchiveMagic() throws IOException {
224        // Read a minimum of bytes in the first gulp.
225        in.setReadLimit(MAGIC_BYTES + AH_LENGTH_MIN);
226
227        //  archive_magic:
228        //        #archive_magic_word :BYTE1[4]
229        archive_magic.expectLength(MAGIC_BYTES);
230        archive_magic.readFrom(in);
231
232        // read and check magic numbers:
233        int magic = getMagicInt32();
234        if (pkg.magic != magic) {
235            throw new IOException("Unexpected package magic number: got "
236                    + magic + "; expected " + pkg.magic);
237        }
238        archive_magic.doneDisbursing();
239    }
240
241     // Fixed 6211177, converted to throw IOException
242    void checkArchiveVersion() throws IOException {
243        Package.Version versionFound = null;
244        for (Package.Version v : new Package.Version[] {
245                JAVA8_PACKAGE_VERSION,
246                JAVA7_PACKAGE_VERSION,
247                JAVA6_PACKAGE_VERSION,
248                JAVA5_PACKAGE_VERSION
249            }) {
250            if (packageVersion.equals(v)) {
251                versionFound = v;
252                break;
253            }
254        }
255        if (versionFound == null) {
256            String expVer =   JAVA8_PACKAGE_VERSION.toString()
257                            + "OR"
258                            + JAVA7_PACKAGE_VERSION.toString()
259                            + " OR "
260                            + JAVA6_PACKAGE_VERSION.toString()
261                            + " OR "
262                            + JAVA5_PACKAGE_VERSION.toString();
263            throw new IOException("Unexpected package minor version: got "
264                    +  packageVersion.toString() + "; expected " + expVer);
265        }
266    }
267
268    void readArchiveHeader() throws IOException {
269        //  archive_header:
270        //        #archive_minver :UNSIGNED5[1]
271        //        #archive_majver :UNSIGNED5[1]
272        //        #archive_options :UNSIGNED5[1]
273        //        (archive_file_counts) ** (#have_file_headers)
274        //        (archive_special_counts) ** (#have_special_formats)
275        //        cp_counts
276        //        class_counts
277        //
278        //  archive_file_counts:
279        //        #archive_size_hi :UNSIGNED5[1]
280        //        #archive_size_lo :UNSIGNED5[1]
281        //        #archive_next_count :UNSIGNED5[1]
282        //        #archive_modtime :UNSIGNED5[1]
283        //        #file_count :UNSIGNED5[1]
284        //
285        //  class_counts:
286        //        #ic_count :UNSIGNED5[1]
287        //        #default_class_minver :UNSIGNED5[1]
288        //        #default_class_majver :UNSIGNED5[1]
289        //        #class_count :UNSIGNED5[1]
290        //
291        //  archive_special_counts:
292        //        #band_headers_size :UNSIGNED5[1]
293        //        #attr_definition_count :UNSIGNED5[1]
294        //
295        archive_header_0.expectLength(AH_LENGTH_0);
296        archive_header_0.readFrom(in);
297
298        int minver = archive_header_0.getInt();
299        int majver = archive_header_0.getInt();
300        packageVersion = Package.Version.of(majver, minver);
301        checkArchiveVersion();
302        this.initHighestClassVersion(JAVA7_MAX_CLASS_VERSION);
303
304        archiveOptions = archive_header_0.getInt();
305        archive_header_0.doneDisbursing();
306
307        // detect archive optional fields in archive header
308        boolean haveSpecial = testBit(archiveOptions, AO_HAVE_SPECIAL_FORMATS);
309        boolean haveFiles   = testBit(archiveOptions, AO_HAVE_FILE_HEADERS);
310        boolean haveNumbers = testBit(archiveOptions, AO_HAVE_CP_NUMBERS);
311        boolean haveCPExtra = testBit(archiveOptions, AO_HAVE_CP_EXTRAS);
312        initAttrIndexLimit();
313
314        // now we are ready to use the data:
315        archive_header_S.expectLength(haveFiles? AH_LENGTH_S: 0);
316        archive_header_S.readFrom(in);
317        if (haveFiles) {
318            long sizeHi = archive_header_S.getInt();
319            long sizeLo = archive_header_S.getInt();
320            archiveSize1 = (sizeHi << 32) + ((sizeLo << 32) >>> 32);
321            // Set the limit, now, up to the file_bits.
322            in.setReadLimit(archiveSize1);  // for debug only
323        } else {
324            archiveSize1 = 0;
325            in.setReadLimit(-1);  // remove limitation
326        }
327        archive_header_S.doneDisbursing();
328        archiveSize0 = in.getBytesServed();
329
330        int remainingHeaders = AH_LENGTH_MIN - AH_LENGTH_0 - AH_LENGTH_S;
331        if (haveFiles)    remainingHeaders += AH_FILE_HEADER_LEN;
332        if (haveSpecial)  remainingHeaders += AH_SPECIAL_FORMAT_LEN;
333        if (haveNumbers)  remainingHeaders += AH_CP_NUMBER_LEN;
334        if (haveCPExtra)  remainingHeaders += AH_CP_EXTRA_LEN;
335        archive_header_1.expectLength(remainingHeaders);
336        archive_header_1.readFrom(in);
337
338        if (haveFiles) {
339            archiveNextCount = archive_header_1.getInt();
340            pkg.default_modtime = archive_header_1.getInt();
341            numFiles = archive_header_1.getInt();
342        } else {
343            archiveNextCount = 0;
344            numFiles = 0;
345        }
346
347        if (haveSpecial) {
348            band_headers.expectLength(archive_header_1.getInt());
349            numAttrDefs = archive_header_1.getInt();
350        } else {
351            band_headers.expectLength(0);
352            numAttrDefs = 0;
353        }
354
355        readConstantPoolCounts(haveNumbers, haveCPExtra);
356
357        numInnerClasses = archive_header_1.getInt();
358
359        minver = (short) archive_header_1.getInt();
360        majver = (short) archive_header_1.getInt();
361        pkg.defaultClassVersion = Package.Version.of(majver, minver);
362        numClasses = archive_header_1.getInt();
363
364        archive_header_1.doneDisbursing();
365
366        // set some derived archive bits
367        if (testBit(archiveOptions, AO_DEFLATE_HINT)) {
368            pkg.default_options |= FO_DEFLATE_HINT;
369        }
370    }
371
372    void readBandHeaders() throws IOException {
373        band_headers.readFrom(in);
374        bandHeaderBytePos = 1;  // Leave room to pushback the initial XB byte.
375        bandHeaderBytes = new byte[bandHeaderBytePos + band_headers.length()];
376        for (int i = bandHeaderBytePos; i < bandHeaderBytes.length; i++) {
377            bandHeaderBytes[i] = (byte) band_headers.getByte();
378        }
379        band_headers.doneDisbursing();
380    }
381
382    void readConstantPoolCounts(boolean haveNumbers, boolean haveCPExtra) throws IOException {
383        // size the constant pools:
384        for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) {
385            //  cp_counts:
386            //        #cp_Utf8_count :UNSIGNED5[1]
387            //        (cp_number_counts) ** (#have_cp_numbers)
388            //        #cp_String_count :UNSIGNED5[1]
389            //        #cp_Class_count :UNSIGNED5[1]
390            //        #cp_Signature_count :UNSIGNED5[1]
391            //        #cp_Descr_count :UNSIGNED5[1]
392            //        #cp_Field_count :UNSIGNED5[1]
393            //        #cp_Method_count :UNSIGNED5[1]
394            //        #cp_Imethod_count :UNSIGNED5[1]
395            //        (cp_attr_counts) ** (#have_cp_attr_counts)
396            //
397            //  cp_number_counts:
398            //        #cp_Int_count :UNSIGNED5[1]
399            //        #cp_Float_count :UNSIGNED5[1]
400            //        #cp_Long_count :UNSIGNED5[1]
401            //        #cp_Double_count :UNSIGNED5[1]
402            //
403            //  cp_extra_counts:
404            //        #cp_MethodHandle_count :UNSIGNED5[1]
405            //        #cp_MethodType_count :UNSIGNED5[1]
406            //        #cp_InvokeDynamic_count :UNSIGNED5[1]
407            //        #cp_BootstrapMethod_count :UNSIGNED5[1]
408            //
409            byte tag = ConstantPool.TAGS_IN_ORDER[k];
410            if (!haveNumbers) {
411                // These four counts are optional.
412                switch (tag) {
413                case CONSTANT_Integer:
414                case CONSTANT_Float:
415                case CONSTANT_Long:
416                case CONSTANT_Double:
417                    continue;
418                }
419            }
420            if (!haveCPExtra) {
421                // These four counts are optional.
422                switch (tag) {
423                case CONSTANT_MethodHandle:
424                case CONSTANT_MethodType:
425                case CONSTANT_InvokeDynamic:
426                case CONSTANT_BootstrapMethod:
427                    continue;
428                }
429            }
430            tagCount[tag] = archive_header_1.getInt();
431        }
432    }
433
434    protected Index getCPIndex(byte tag) {
435        return pkg.cp.getIndexByTag(tag);
436    }
437    Index initCPIndex(byte tag, Entry[] cpMap) {
438        if (verbose > 3) {
439            for (int i = 0; i < cpMap.length; i++) {
440                Utils.log.fine("cp.add "+cpMap[i]);
441            }
442        }
443        Index index = ConstantPool.makeIndex(ConstantPool.tagName(tag), cpMap);
444        if (verbose > 1)  Utils.log.fine("Read "+index);
445        pkg.cp.initIndexByTag(tag, index);
446        return index;
447    }
448
449    void checkLegacy(String bandname) {
450        if (packageVersion.lessThan(JAVA7_PACKAGE_VERSION)) {
451            throw new RuntimeException("unexpected band " + bandname);
452        }
453    }
454    void readConstantPool() throws IOException {
455        //  cp_bands:
456        //        cp_Utf8
457        //        *cp_Int :UDELTA5
458        //        *cp_Float :UDELTA5
459        //        cp_Long
460        //        cp_Double
461        //        *cp_String :UDELTA5  (cp_Utf8)
462        //        *cp_Class :UDELTA5  (cp_Utf8)
463        //        cp_Signature
464        //        cp_Descr
465        //        cp_Field
466        //        cp_Method
467        //        cp_Imethod
468
469        if (verbose > 0)  Utils.log.info("Reading CP");
470
471        for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) {
472            byte tag = ConstantPool.TAGS_IN_ORDER[k];
473            int  len = tagCount[tag];
474
475            Entry[] cpMap = new Entry[len];
476            if (verbose > 0)
477                Utils.log.info("Reading "+cpMap.length+" "+ConstantPool.tagName(tag)+" entries...");
478
479            switch (tag) {
480            case CONSTANT_Utf8:
481                readUtf8Bands(cpMap);
482                break;
483            case CONSTANT_Integer:
484                cp_Int.expectLength(cpMap.length);
485                cp_Int.readFrom(in);
486                for (int i = 0; i < cpMap.length; i++) {
487                    int x = cp_Int.getInt();  // coding handles signs OK
488                    cpMap[i] = ConstantPool.getLiteralEntry(x);
489                }
490                cp_Int.doneDisbursing();
491                break;
492            case CONSTANT_Float:
493                cp_Float.expectLength(cpMap.length);
494                cp_Float.readFrom(in);
495                for (int i = 0; i < cpMap.length; i++) {
496                    int x = cp_Float.getInt();
497                    float fx = Float.intBitsToFloat(x);
498                    cpMap[i] = ConstantPool.getLiteralEntry(fx);
499                }
500                cp_Float.doneDisbursing();
501                break;
502            case CONSTANT_Long:
503                //  cp_Long:
504                //        *cp_Long_hi :UDELTA5
505                //        *cp_Long_lo :DELTA5
506                cp_Long_hi.expectLength(cpMap.length);
507                cp_Long_hi.readFrom(in);
508                cp_Long_lo.expectLength(cpMap.length);
509                cp_Long_lo.readFrom(in);
510                for (int i = 0; i < cpMap.length; i++) {
511                    long hi = cp_Long_hi.getInt();
512                    long lo = cp_Long_lo.getInt();
513                    long x = (hi << 32) + ((lo << 32) >>> 32);
514                    cpMap[i] = ConstantPool.getLiteralEntry(x);
515                }
516                cp_Long_hi.doneDisbursing();
517                cp_Long_lo.doneDisbursing();
518                break;
519            case CONSTANT_Double:
520                //  cp_Double:
521                //        *cp_Double_hi :UDELTA5
522                //        *cp_Double_lo :DELTA5
523                cp_Double_hi.expectLength(cpMap.length);
524                cp_Double_hi.readFrom(in);
525                cp_Double_lo.expectLength(cpMap.length);
526                cp_Double_lo.readFrom(in);
527                for (int i = 0; i < cpMap.length; i++) {
528                    long hi = cp_Double_hi.getInt();
529                    long lo = cp_Double_lo.getInt();
530                    long x = (hi << 32) + ((lo << 32) >>> 32);
531                    double dx = Double.longBitsToDouble(x);
532                    cpMap[i] = ConstantPool.getLiteralEntry(dx);
533                }
534                cp_Double_hi.doneDisbursing();
535                cp_Double_lo.doneDisbursing();
536                break;
537            case CONSTANT_String:
538                cp_String.expectLength(cpMap.length);
539                cp_String.readFrom(in);
540                cp_String.setIndex(getCPIndex(CONSTANT_Utf8));
541                for (int i = 0; i < cpMap.length; i++) {
542                    cpMap[i] = ConstantPool.getLiteralEntry(cp_String.getRef().stringValue());
543                }
544                cp_String.doneDisbursing();
545                break;
546            case CONSTANT_Class:
547                cp_Class.expectLength(cpMap.length);
548                cp_Class.readFrom(in);
549                cp_Class.setIndex(getCPIndex(CONSTANT_Utf8));
550                for (int i = 0; i < cpMap.length; i++) {
551                    cpMap[i] = ConstantPool.getClassEntry(cp_Class.getRef().stringValue());
552                }
553                cp_Class.doneDisbursing();
554                break;
555            case CONSTANT_Signature:
556                readSignatureBands(cpMap);
557                break;
558            case CONSTANT_NameandType:
559                //  cp_Descr:
560                //        *cp_Descr_type :DELTA5  (cp_Signature)
561                //        *cp_Descr_name :UDELTA5  (cp_Utf8)
562                cp_Descr_name.expectLength(cpMap.length);
563                cp_Descr_name.readFrom(in);
564                cp_Descr_name.setIndex(getCPIndex(CONSTANT_Utf8));
565                cp_Descr_type.expectLength(cpMap.length);
566                cp_Descr_type.readFrom(in);
567                cp_Descr_type.setIndex(getCPIndex(CONSTANT_Signature));
568                for (int i = 0; i < cpMap.length; i++) {
569                    Entry ref  = cp_Descr_name.getRef();
570                    Entry ref2 = cp_Descr_type.getRef();
571                    cpMap[i] = ConstantPool.getDescriptorEntry((Utf8Entry)ref,
572                                                        (SignatureEntry)ref2);
573                }
574                cp_Descr_name.doneDisbursing();
575                cp_Descr_type.doneDisbursing();
576                break;
577            case CONSTANT_Fieldref:
578                readMemberRefs(tag, cpMap, cp_Field_class, cp_Field_desc);
579                break;
580            case CONSTANT_Methodref:
581                readMemberRefs(tag, cpMap, cp_Method_class, cp_Method_desc);
582                break;
583            case CONSTANT_InterfaceMethodref:
584                readMemberRefs(tag, cpMap, cp_Imethod_class, cp_Imethod_desc);
585                break;
586            case CONSTANT_MethodHandle:
587                if (cpMap.length > 0) {
588                    checkLegacy(cp_MethodHandle_refkind.name());
589                }
590                cp_MethodHandle_refkind.expectLength(cpMap.length);
591                cp_MethodHandle_refkind.readFrom(in);
592                cp_MethodHandle_member.expectLength(cpMap.length);
593                cp_MethodHandle_member.readFrom(in);
594                cp_MethodHandle_member.setIndex(getCPIndex(CONSTANT_AnyMember));
595                for (int i = 0; i < cpMap.length; i++) {
596                    byte        refKind = (byte)        cp_MethodHandle_refkind.getInt();
597                    MemberEntry memRef  = (MemberEntry) cp_MethodHandle_member.getRef();
598                    cpMap[i] = ConstantPool.getMethodHandleEntry(refKind, memRef);
599                }
600                cp_MethodHandle_refkind.doneDisbursing();
601                cp_MethodHandle_member.doneDisbursing();
602                break;
603            case CONSTANT_MethodType:
604                if (cpMap.length > 0) {
605                    checkLegacy(cp_MethodType.name());
606                }
607                cp_MethodType.expectLength(cpMap.length);
608                cp_MethodType.readFrom(in);
609                cp_MethodType.setIndex(getCPIndex(CONSTANT_Signature));
610                for (int i = 0; i < cpMap.length; i++) {
611                    SignatureEntry typeRef  = (SignatureEntry) cp_MethodType.getRef();
612                    cpMap[i] = ConstantPool.getMethodTypeEntry(typeRef);
613                }
614                cp_MethodType.doneDisbursing();
615                break;
616            case CONSTANT_InvokeDynamic:
617                if (cpMap.length > 0) {
618                    checkLegacy(cp_InvokeDynamic_spec.name());
619                }
620                cp_InvokeDynamic_spec.expectLength(cpMap.length);
621                cp_InvokeDynamic_spec.readFrom(in);
622                cp_InvokeDynamic_spec.setIndex(getCPIndex(CONSTANT_BootstrapMethod));
623                cp_InvokeDynamic_desc.expectLength(cpMap.length);
624                cp_InvokeDynamic_desc.readFrom(in);
625                cp_InvokeDynamic_desc.setIndex(getCPIndex(CONSTANT_NameandType));
626                for (int i = 0; i < cpMap.length; i++) {
627                    BootstrapMethodEntry bss   = (BootstrapMethodEntry) cp_InvokeDynamic_spec.getRef();
628                    DescriptorEntry      descr = (DescriptorEntry)      cp_InvokeDynamic_desc.getRef();
629                    cpMap[i] = ConstantPool.getInvokeDynamicEntry(bss, descr);
630                }
631                cp_InvokeDynamic_spec.doneDisbursing();
632                cp_InvokeDynamic_desc.doneDisbursing();
633                break;
634            case CONSTANT_BootstrapMethod:
635                if (cpMap.length > 0) {
636                    checkLegacy(cp_BootstrapMethod_ref.name());
637                }
638                cp_BootstrapMethod_ref.expectLength(cpMap.length);
639                cp_BootstrapMethod_ref.readFrom(in);
640                cp_BootstrapMethod_ref.setIndex(getCPIndex(CONSTANT_MethodHandle));
641                cp_BootstrapMethod_arg_count.expectLength(cpMap.length);
642                cp_BootstrapMethod_arg_count.readFrom(in);
643                int totalArgCount = cp_BootstrapMethod_arg_count.getIntTotal();
644                cp_BootstrapMethod_arg.expectLength(totalArgCount);
645                cp_BootstrapMethod_arg.readFrom(in);
646                cp_BootstrapMethod_arg.setIndex(getCPIndex(CONSTANT_LoadableValue));
647                for (int i = 0; i < cpMap.length; i++) {
648                    MethodHandleEntry bsm = (MethodHandleEntry) cp_BootstrapMethod_ref.getRef();
649                    int argc = cp_BootstrapMethod_arg_count.getInt();
650                    Entry[] argRefs = new Entry[argc];
651                    for (int j = 0; j < argc; j++) {
652                        argRefs[j] = cp_BootstrapMethod_arg.getRef();
653                    }
654                    cpMap[i] = ConstantPool.getBootstrapMethodEntry(bsm, argRefs);
655                }
656                cp_BootstrapMethod_ref.doneDisbursing();
657                cp_BootstrapMethod_arg_count.doneDisbursing();
658                cp_BootstrapMethod_arg.doneDisbursing();
659                break;
660            default:
661                throw new AssertionError("unexpected CP tag in package");
662            }
663
664            Index index = initCPIndex(tag, cpMap);
665
666            if (optDumpBands) {
667                try (PrintStream ps = new PrintStream(getDumpStream(index, ".idx"))) {
668                    printArrayTo(ps, index.cpMap, 0, index.cpMap.length);
669                }
670            }
671        }
672
673        cp_bands.doneDisbursing();
674
675        if (optDumpBands || verbose > 1) {
676            for (byte tag = CONSTANT_GroupFirst; tag < CONSTANT_GroupLimit; tag++) {
677                Index index = pkg.cp.getIndexByTag(tag);
678                if (index == null || index.isEmpty())  continue;
679                Entry[] cpMap = index.cpMap;
680                if (verbose > 1)
681                    Utils.log.info("Index group "+ConstantPool.tagName(tag)+" contains "+cpMap.length+" entries.");
682                if (optDumpBands) {
683                    try (PrintStream ps = new PrintStream(getDumpStream(index.debugName, tag, ".gidx", index))) {
684                        printArrayTo(ps, cpMap, 0, cpMap.length, true);
685                    }
686                }
687            }
688        }
689
690        setBandIndexes();
691    }
692
693    void readUtf8Bands(Entry[] cpMap) throws IOException {
694        //  cp_Utf8:
695        //        *cp_Utf8_prefix :DELTA5
696        //        *cp_Utf8_suffix :UNSIGNED5
697        //        *cp_Utf8_chars :CHAR3
698        //        *cp_Utf8_big_suffix :DELTA5
699        //        (*cp_Utf8_big_chars :DELTA5)
700        //          ** length(cp_Utf8_big_suffix)
701        int len = cpMap.length;
702        if (len == 0)
703            return;  // nothing to read
704
705        // Bands have implicit leading zeroes, for the empty string:
706        final int SUFFIX_SKIP_1 = 1;
707        final int PREFIX_SKIP_2 = 2;
708
709        // First band:  Read lengths of shared prefixes.
710        cp_Utf8_prefix.expectLength(Math.max(0, len - PREFIX_SKIP_2));
711        cp_Utf8_prefix.readFrom(in);
712
713        // Second band:  Read lengths of unshared suffixes:
714        cp_Utf8_suffix.expectLength(Math.max(0, len - SUFFIX_SKIP_1));
715        cp_Utf8_suffix.readFrom(in);
716
717        char[][] suffixChars = new char[len][];
718        int bigSuffixCount = 0;
719
720        // Third band:  Read the char values in the unshared suffixes:
721        cp_Utf8_chars.expectLength(cp_Utf8_suffix.getIntTotal());
722        cp_Utf8_chars.readFrom(in);
723        for (int i = 0; i < len; i++) {
724            int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt();
725            if (suffix == 0 && i >= SUFFIX_SKIP_1) {
726                // chars are packed in cp_Utf8_big_chars
727                bigSuffixCount += 1;
728                continue;
729            }
730            suffixChars[i] = new char[suffix];
731            for (int j = 0; j < suffix; j++) {
732                int ch = cp_Utf8_chars.getInt();
733                assert(ch == (char)ch);
734                suffixChars[i][j] = (char)ch;
735            }
736        }
737        cp_Utf8_chars.doneDisbursing();
738
739        // Fourth band:  Go back and size the specially packed strings.
740        int maxChars = 0;
741        cp_Utf8_big_suffix.expectLength(bigSuffixCount);
742        cp_Utf8_big_suffix.readFrom(in);
743        cp_Utf8_suffix.resetForSecondPass();
744        for (int i = 0; i < len; i++) {
745            int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt();
746            int prefix = (i < PREFIX_SKIP_2)? 0: cp_Utf8_prefix.getInt();
747            if (suffix == 0 && i >= SUFFIX_SKIP_1) {
748                assert(suffixChars[i] == null);
749                suffix = cp_Utf8_big_suffix.getInt();
750            } else {
751                assert(suffixChars[i] != null);
752            }
753            if (maxChars < prefix + suffix)
754                maxChars = prefix + suffix;
755        }
756        char[] buf = new char[maxChars];
757
758        // Fifth band(s):  Get the specially packed characters.
759        cp_Utf8_suffix.resetForSecondPass();
760        cp_Utf8_big_suffix.resetForSecondPass();
761        for (int i = 0; i < len; i++) {
762            if (i < SUFFIX_SKIP_1)  continue;
763            int suffix = cp_Utf8_suffix.getInt();
764            if (suffix != 0)  continue;  // already input
765            suffix = cp_Utf8_big_suffix.getInt();
766            suffixChars[i] = new char[suffix];
767            if (suffix == 0) {
768                // Do not bother to add an empty "(Utf8_big_0)" band.
769                continue;
770            }
771            IntBand packed = cp_Utf8_big_chars.newIntBand("(Utf8_big_"+i+")");
772            packed.expectLength(suffix);
773            packed.readFrom(in);
774            for (int j = 0; j < suffix; j++) {
775                int ch = packed.getInt();
776                assert(ch == (char)ch);
777                suffixChars[i][j] = (char)ch;
778            }
779            packed.doneDisbursing();
780        }
781        cp_Utf8_big_chars.doneDisbursing();
782
783        // Finally, sew together all the prefixes and suffixes.
784        cp_Utf8_prefix.resetForSecondPass();
785        cp_Utf8_suffix.resetForSecondPass();
786        cp_Utf8_big_suffix.resetForSecondPass();
787        for (int i = 0; i < len; i++) {
788            int prefix = (i < PREFIX_SKIP_2)? 0: cp_Utf8_prefix.getInt();
789            int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt();
790            if (suffix == 0 && i >= SUFFIX_SKIP_1)
791                suffix = cp_Utf8_big_suffix.getInt();
792
793            // by induction, the buffer is already filled with the prefix
794            System.arraycopy(suffixChars[i], 0, buf, prefix, suffix);
795
796            cpMap[i] = ConstantPool.getUtf8Entry(new String(buf, 0, prefix+suffix));
797        }
798
799        cp_Utf8_prefix.doneDisbursing();
800        cp_Utf8_suffix.doneDisbursing();
801        cp_Utf8_big_suffix.doneDisbursing();
802    }
803
804    Map<Utf8Entry, SignatureEntry> utf8Signatures;
805
806    void readSignatureBands(Entry[] cpMap) throws IOException {
807        //  cp_Signature:
808        //        *cp_Signature_form :DELTA5  (cp_Utf8)
809        //        *cp_Signature_classes :UDELTA5  (cp_Class)
810        cp_Signature_form.expectLength(cpMap.length);
811        cp_Signature_form.readFrom(in);
812        cp_Signature_form.setIndex(getCPIndex(CONSTANT_Utf8));
813        int[] numSigClasses = new int[cpMap.length];
814        for (int i = 0; i < cpMap.length; i++) {
815            Utf8Entry formRef = (Utf8Entry) cp_Signature_form.getRef();
816            numSigClasses[i] = ConstantPool.countClassParts(formRef);
817        }
818        cp_Signature_form.resetForSecondPass();
819        cp_Signature_classes.expectLength(getIntTotal(numSigClasses));
820        cp_Signature_classes.readFrom(in);
821        cp_Signature_classes.setIndex(getCPIndex(CONSTANT_Class));
822        utf8Signatures = new HashMap<>();
823        for (int i = 0; i < cpMap.length; i++) {
824            Utf8Entry formRef = (Utf8Entry) cp_Signature_form.getRef();
825            ClassEntry[] classRefs = new ClassEntry[numSigClasses[i]];
826            for (int j = 0; j < classRefs.length; j++) {
827                classRefs[j] = (ClassEntry) cp_Signature_classes.getRef();
828            }
829            SignatureEntry se = ConstantPool.getSignatureEntry(formRef, classRefs);
830            cpMap[i] = se;
831            utf8Signatures.put(se.asUtf8Entry(), se);
832        }
833        cp_Signature_form.doneDisbursing();
834        cp_Signature_classes.doneDisbursing();
835    }
836
837    void readMemberRefs(byte tag, Entry[] cpMap, CPRefBand cp_class, CPRefBand cp_desc) throws IOException {
838        //  cp_Field:
839        //        *cp_Field_class :DELTA5  (cp_Class)
840        //        *cp_Field_desc :UDELTA5  (cp_Descr)
841        //  cp_Method:
842        //        *cp_Method_class :DELTA5  (cp_Class)
843        //        *cp_Method_desc :UDELTA5  (cp_Descr)
844        //  cp_Imethod:
845        //        *cp_Imethod_class :DELTA5  (cp_Class)
846        //        *cp_Imethod_desc :UDELTA5  (cp_Descr)
847        cp_class.expectLength(cpMap.length);
848        cp_class.readFrom(in);
849        cp_class.setIndex(getCPIndex(CONSTANT_Class));
850        cp_desc.expectLength(cpMap.length);
851        cp_desc.readFrom(in);
852        cp_desc.setIndex(getCPIndex(CONSTANT_NameandType));
853        for (int i = 0; i < cpMap.length; i++) {
854            ClassEntry      mclass = (ClassEntry     ) cp_class.getRef();
855            DescriptorEntry mdescr = (DescriptorEntry) cp_desc.getRef();
856            cpMap[i] = ConstantPool.getMemberEntry(tag, mclass, mdescr);
857        }
858        cp_class.doneDisbursing();
859        cp_desc.doneDisbursing();
860    }
861
862    void readFiles() throws IOException {
863        //  file_bands:
864        //        *file_name :UNSIGNED5  (cp_Utf8)
865        //        *file_size_hi :UNSIGNED5
866        //        *file_size_lo :UNSIGNED5
867        //        *file_modtime :DELTA5
868        //        *file_options :UNSIGNED5
869        //        *file_bits :BYTE1
870        if (verbose > 0)
871            Utils.log.info("  ...building "+numFiles+" files...");
872        file_name.expectLength(numFiles);
873        file_size_lo.expectLength(numFiles);
874        int options = archiveOptions;
875        boolean haveSizeHi  = testBit(options, AO_HAVE_FILE_SIZE_HI);
876        boolean haveModtime = testBit(options, AO_HAVE_FILE_MODTIME);
877        boolean haveOptions = testBit(options, AO_HAVE_FILE_OPTIONS);
878        if (haveSizeHi)
879            file_size_hi.expectLength(numFiles);
880        if (haveModtime)
881            file_modtime.expectLength(numFiles);
882        if (haveOptions)
883            file_options.expectLength(numFiles);
884
885        file_name.readFrom(in);
886        file_size_hi.readFrom(in);
887        file_size_lo.readFrom(in);
888        file_modtime.readFrom(in);
889        file_options.readFrom(in);
890        file_bits.setInputStreamFrom(in);
891
892        Iterator<Class> nextClass = pkg.getClasses().iterator();
893
894        // Compute file lengths before reading any file bits.
895        long totalFileLength = 0;
896        long[] fileLengths = new long[numFiles];
897        for (int i = 0; i < numFiles; i++) {
898            long size = ((long)file_size_lo.getInt() << 32) >>> 32;
899            if (haveSizeHi)
900                size += (long)file_size_hi.getInt() << 32;
901            fileLengths[i] = size;
902            totalFileLength += size;
903        }
904        assert(in.getReadLimit() == -1 || in.getReadLimit() == totalFileLength);
905
906        byte[] buf = new byte[1<<16];
907        for (int i = 0; i < numFiles; i++) {
908            // %%% Use a big temp file for file bits?
909            Utf8Entry name = (Utf8Entry) file_name.getRef();
910            long size = fileLengths[i];
911            File file = pkg.new File(name);
912            file.modtime = pkg.default_modtime;
913            file.options = pkg.default_options;
914            if (haveModtime)
915                file.modtime += file_modtime.getInt();
916            if (haveOptions)
917                file.options |= file_options.getInt();
918            if (verbose > 1)
919                Utils.log.fine("Reading "+size+" bytes of "+name.stringValue());
920            long toRead = size;
921            while (toRead > 0) {
922                int nr = buf.length;
923                if (nr > toRead)  nr = (int) toRead;
924                nr = file_bits.getInputStream().read(buf, 0, nr);
925                if (nr < 0)  throw new EOFException();
926                file.addBytes(buf, 0, nr);
927                toRead -= nr;
928            }
929            pkg.addFile(file);
930            if (file.isClassStub()) {
931                assert(file.getFileLength() == 0);
932                Class cls = nextClass.next();
933                cls.initFile(file);
934            }
935        }
936
937        // Do the rest of the classes.
938        while (nextClass.hasNext()) {
939            Class cls = nextClass.next();
940            cls.initFile(null);  // implicitly initialize to a trivial one
941            cls.file.modtime = pkg.default_modtime;
942        }
943
944        file_name.doneDisbursing();
945        file_size_hi.doneDisbursing();
946        file_size_lo.doneDisbursing();
947        file_modtime.doneDisbursing();
948        file_options.doneDisbursing();
949        file_bits.doneDisbursing();
950        file_bands.doneDisbursing();
951
952        if (archiveSize1 != 0 && !in.atLimit()) {
953            throw new RuntimeException("Predicted archive_size "+
954                                       archiveSize1+" != "+
955                                       (in.getBytesServed()-archiveSize0));
956        }
957    }
958
959    void readAttrDefs() throws IOException {
960        //  attr_definition_bands:
961        //        *attr_definition_headers :BYTE1
962        //        *attr_definition_name :UNSIGNED5  (cp_Utf8)
963        //        *attr_definition_layout :UNSIGNED5  (cp_Utf8)
964        attr_definition_headers.expectLength(numAttrDefs);
965        attr_definition_name.expectLength(numAttrDefs);
966        attr_definition_layout.expectLength(numAttrDefs);
967        attr_definition_headers.readFrom(in);
968        attr_definition_name.readFrom(in);
969        attr_definition_layout.readFrom(in);
970        try (PrintStream dump = !optDumpBands ? null
971                 : new PrintStream(getDumpStream(attr_definition_headers, ".def")))
972        {
973            for (int i = 0; i < numAttrDefs; i++) {
974                int       header = attr_definition_headers.getByte();
975                Utf8Entry name   = (Utf8Entry) attr_definition_name.getRef();
976                Utf8Entry layout = (Utf8Entry) attr_definition_layout.getRef();
977                int       ctype  = (header &  ADH_CONTEXT_MASK);
978                int       index  = (header >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB;
979                Attribute.Layout def = new Attribute.Layout(ctype,
980                                                            name.stringValue(),
981                                                            layout.stringValue());
982                // Check layout string for Java 6 extensions.
983                String pvLayout = def.layoutForClassVersion(getHighestClassVersion());
984                if (!pvLayout.equals(def.layout())) {
985                    throw new IOException("Bad attribute layout in archive: "+def.layout());
986                }
987                this.setAttributeLayoutIndex(def, index);
988                if (dump != null)  dump.println(index+" "+def);
989            }
990        }
991        attr_definition_headers.doneDisbursing();
992        attr_definition_name.doneDisbursing();
993        attr_definition_layout.doneDisbursing();
994        // Attribute layouts define bands, one per layout element.
995        // Create them now, all at once.
996        makeNewAttributeBands();
997        attr_definition_bands.doneDisbursing();
998    }
999
1000    void readInnerClasses() throws IOException {
1001        //  ic_bands:
1002        //        *ic_this_class :UDELTA5  (cp_Class)
1003        //        *ic_flags :UNSIGNED5
1004        //        *ic_outer_class :DELTA5  (null or cp_Class)
1005        //        *ic_name :DELTA5  (null or cp_Utf8)
1006        ic_this_class.expectLength(numInnerClasses);
1007        ic_this_class.readFrom(in);
1008        ic_flags.expectLength(numInnerClasses);
1009        ic_flags.readFrom(in);
1010        int longICCount = 0;
1011        for (int i = 0; i < numInnerClasses; i++) {
1012            int flags = ic_flags.getInt();
1013            boolean longForm = (flags & ACC_IC_LONG_FORM) != 0;
1014            if (longForm) {
1015                longICCount += 1;
1016            }
1017        }
1018        ic_outer_class.expectLength(longICCount);
1019        ic_outer_class.readFrom(in);
1020        ic_name.expectLength(longICCount);
1021        ic_name.readFrom(in);
1022        ic_flags.resetForSecondPass();
1023        List<InnerClass> icList = new ArrayList<>(numInnerClasses);
1024        for (int i = 0; i < numInnerClasses; i++) {
1025            int flags = ic_flags.getInt();
1026            boolean longForm = (flags & ACC_IC_LONG_FORM) != 0;
1027            flags &= ~ACC_IC_LONG_FORM;
1028            ClassEntry thisClass = (ClassEntry) ic_this_class.getRef();
1029            ClassEntry outerClass;
1030            Utf8Entry  thisName;
1031            if (longForm) {
1032                outerClass = (ClassEntry) ic_outer_class.getRef();
1033                thisName   = (Utf8Entry)  ic_name.getRef();
1034            } else {
1035                String n = thisClass.stringValue();
1036                String[] parse = Package.parseInnerClassName(n);
1037                assert(parse != null);
1038                String pkgOuter = parse[0];
1039                //String number = parse[1];
1040                String name     = parse[2];
1041                if (pkgOuter == null)
1042                    outerClass = null;
1043                else
1044                    outerClass = ConstantPool.getClassEntry(pkgOuter);
1045                if (name == null)
1046                    thisName   = null;
1047                else
1048                    thisName   = ConstantPool.getUtf8Entry(name);
1049            }
1050            InnerClass ic =
1051                new InnerClass(thisClass, outerClass, thisName, flags);
1052            assert(longForm || ic.predictable);
1053            icList.add(ic);
1054        }
1055        ic_flags.doneDisbursing();
1056        ic_this_class.doneDisbursing();
1057        ic_outer_class.doneDisbursing();
1058        ic_name.doneDisbursing();
1059        pkg.setAllInnerClasses(icList);
1060        ic_bands.doneDisbursing();
1061    }
1062
1063    void readLocalInnerClasses(Class cls) throws IOException {
1064        int nc = class_InnerClasses_N.getInt();
1065        List<InnerClass> localICs = new ArrayList<>(nc);
1066        for (int i = 0; i < nc; i++) {
1067            ClassEntry thisClass = (ClassEntry) class_InnerClasses_RC.getRef();
1068            int        flags     =              class_InnerClasses_F.getInt();
1069            if (flags == 0) {
1070                // A zero flag means copy a global IC here.
1071                InnerClass ic = pkg.getGlobalInnerClass(thisClass);
1072                assert(ic != null);  // must be a valid global IC reference
1073                localICs.add(ic);
1074            } else {
1075                if (flags == ACC_IC_LONG_FORM)
1076                    flags = 0;  // clear the marker bit
1077                ClassEntry outer = (ClassEntry) class_InnerClasses_outer_RCN.getRef();
1078                Utf8Entry name   = (Utf8Entry)  class_InnerClasses_name_RUN.getRef();
1079                localICs.add(new InnerClass(thisClass, outer, name, flags));
1080            }
1081        }
1082        cls.setInnerClasses(localICs);
1083        // cls.expandLocalICs may add more tuples to ics also,
1084        // or may even delete tuples.
1085        // We cannot do that now, because we do not know the
1086        // full contents of the local constant pool yet.
1087    }
1088
1089    static final int NO_FLAGS_YET = 0;  // placeholder for later flag read-in
1090
1091    Class[] readClasses() throws IOException {
1092        //  class_bands:
1093        //        *class_this :DELTA5  (cp_Class)
1094        //        *class_super :DELTA5  (cp_Class)
1095        //        *class_interface_count :DELTA5
1096        //        *class_interface :DELTA5  (cp_Class)
1097        //        ...(member bands)...
1098        //        class_attr_bands
1099        //        code_bands
1100        Class[] classes = new Class[numClasses];
1101        if (verbose > 0)
1102            Utils.log.info("  ...building "+classes.length+" classes...");
1103
1104        class_this.expectLength(numClasses);
1105        class_super.expectLength(numClasses);
1106        class_interface_count.expectLength(numClasses);
1107
1108        class_this.readFrom(in);
1109        class_super.readFrom(in);
1110        class_interface_count.readFrom(in);
1111        class_interface.expectLength(class_interface_count.getIntTotal());
1112        class_interface.readFrom(in);
1113        for (int i = 0; i < classes.length; i++) {
1114            ClassEntry   thisClass  = (ClassEntry) class_this.getRef();
1115            ClassEntry   superClass = (ClassEntry) class_super.getRef();
1116            ClassEntry[] interfaces = new ClassEntry[class_interface_count.getInt()];
1117            for (int j = 0; j < interfaces.length; j++) {
1118                interfaces[j] = (ClassEntry) class_interface.getRef();
1119            }
1120            // Packer encoded rare case of null superClass as thisClass:
1121            if (superClass == thisClass)  superClass = null;
1122            Class cls = pkg.new Class(NO_FLAGS_YET,
1123                                      thisClass, superClass, interfaces);
1124            classes[i] = cls;
1125        }
1126        class_this.doneDisbursing();
1127        class_super.doneDisbursing();
1128        class_interface_count.doneDisbursing();
1129        class_interface.doneDisbursing();
1130        readMembers(classes);
1131        countAndReadAttrs(ATTR_CONTEXT_CLASS, Arrays.asList(classes));
1132        pkg.trimToSize();
1133        readCodeHeaders();
1134        //code_bands.doneDisbursing(); // still need to read code attrs
1135        //class_bands.doneDisbursing(); // still need to read code attrs
1136        return classes;
1137    }
1138
1139    private int getOutputIndex(Entry e) {
1140        // Output CPs do not contain signatures.
1141        assert(e.tag != CONSTANT_Signature);
1142        int k = pkg.cp.untypedIndexOf(e);
1143        // In the output ordering, input signatures can serve
1144        // in place of Utf8s.
1145        if (k >= 0)
1146            return k;
1147        if (e.tag == CONSTANT_Utf8) {
1148            Entry se = utf8Signatures.get(e);
1149            return pkg.cp.untypedIndexOf(se);
1150        }
1151        return -1;
1152    }
1153
1154    Comparator<Entry> entryOutputOrder = new Comparator<>() {
1155        public int compare(Entry e0, Entry e1) {
1156            int k0 = getOutputIndex(e0);
1157            int k1 = getOutputIndex(e1);
1158            if (k0 >= 0 && k1 >= 0)
1159                // If both have keys, use the keys.
1160                return k0 - k1;
1161            if (k0 == k1)
1162                // If neither have keys, use their native tags & spellings.
1163                return e0.compareTo(e1);
1164            // Otherwise, the guy with the key comes first.
1165            return (k0 >= 0)? 0-1: 1-0;
1166        }
1167    };
1168
1169    void reconstructClass(Class cls) {
1170        if (verbose > 1)  Utils.log.fine("reconstruct "+cls);
1171
1172        // check for local .ClassFile.version
1173        Attribute retroVersion = cls.getAttribute(attrClassFileVersion);
1174        if (retroVersion != null) {
1175            cls.removeAttribute(retroVersion);
1176            cls.version = parseClassFileVersionAttr(retroVersion);
1177        } else {
1178            cls.version = pkg.defaultClassVersion;
1179        }
1180
1181        // Replace null SourceFile by "obvious" string.
1182        cls.expandSourceFile();
1183
1184        // record the local cp:
1185        cls.setCPMap(reconstructLocalCPMap(cls));
1186    }
1187
1188    Entry[] reconstructLocalCPMap(Class cls) {
1189        Set<Entry> ldcRefs = ldcRefMap.get(cls);
1190        Set<Entry> cpRefs = new HashSet<>();
1191
1192        // look for constant pool entries:
1193        cls.visitRefs(VRM_CLASSIC, cpRefs);
1194
1195        ArrayList<BootstrapMethodEntry> bsms = new ArrayList<>();
1196        // flesh out the local constant pool
1197        ConstantPool.completeReferencesIn(cpRefs, true, bsms);
1198
1199        // add the bsm and references as required
1200        if (!bsms.isEmpty()) {
1201            cls.addAttribute(Package.attrBootstrapMethodsEmpty.canonicalInstance());
1202            cpRefs.add(Package.getRefString("BootstrapMethods"));
1203            Collections.sort(bsms);
1204            cls.setBootstrapMethods(bsms);
1205        }
1206
1207        // Now that we know all our local class references,
1208        // compute the InnerClasses attribute.
1209        // An InnerClasses attribute usually gets added here,
1210        // although it might already have been present.
1211        int changed = cls.expandLocalICs();
1212
1213        if (changed != 0) {
1214            if (changed > 0) {
1215                // Just visit the expanded InnerClasses attr.
1216                cls.visitInnerClassRefs(VRM_CLASSIC, cpRefs);
1217            } else {
1218                // Have to recompute from scratch, because of deletions.
1219                cpRefs.clear();
1220                cls.visitRefs(VRM_CLASSIC, cpRefs);
1221            }
1222
1223            // flesh out the local constant pool, again
1224            ConstantPool.completeReferencesIn(cpRefs, true, bsms);
1225        }
1226
1227        // construct a local constant pool
1228        int numDoubles = 0;
1229        for (Entry e : cpRefs) {
1230            if (e.isDoubleWord())  numDoubles++;
1231        }
1232        Entry[] cpMap = new Entry[1+numDoubles+cpRefs.size()];
1233        int fillp = 1;
1234
1235        // Add all ldc operands first.
1236        if (ldcRefs != null) {
1237            assert(cpRefs.containsAll(ldcRefs));
1238            for (Entry e : ldcRefs) {
1239                cpMap[fillp++] = e;
1240            }
1241            assert(fillp == 1+ldcRefs.size());
1242            cpRefs.removeAll(ldcRefs);
1243            ldcRefs = null;  // done with it
1244        }
1245
1246        // Next add all the two-byte references.
1247        Set<Entry> wideRefs = cpRefs;
1248        cpRefs = null;  // do not use!
1249        int narrowLimit = fillp;
1250        for (Entry e : wideRefs) {
1251            cpMap[fillp++] = e;
1252        }
1253        assert(fillp == narrowLimit+wideRefs.size());
1254        Arrays.sort(cpMap, 1, narrowLimit, entryOutputOrder);
1255        Arrays.sort(cpMap, narrowLimit, fillp, entryOutputOrder);
1256
1257        if (verbose > 3) {
1258            Utils.log.fine("CP of "+this+" {");
1259            for (int i = 0; i < fillp; i++) {
1260                Entry e = cpMap[i];
1261                Utils.log.fine("  "+((e==null)?-1:getOutputIndex(e))
1262                                   +" : "+e);
1263            }
1264            Utils.log.fine("}");
1265        }
1266
1267        // Now repack backwards, introducing null elements.
1268        int revp = cpMap.length;
1269        for (int i = fillp; --i >= 1; ) {
1270            Entry e = cpMap[i];
1271            if (e.isDoubleWord())
1272                cpMap[--revp] = null;
1273            cpMap[--revp] = e;
1274        }
1275        assert(revp == 1);  // do not process the initial null
1276
1277        return cpMap;
1278    }
1279
1280    void readMembers(Class[] classes) throws IOException {
1281        //  class_bands:
1282        //        ...
1283        //        *class_field_count :DELTA5
1284        //        *class_method_count :DELTA5
1285        //
1286        //        *field_descr :DELTA5  (cp_Descr)
1287        //        field_attr_bands
1288        //
1289        //        *method_descr :MDELTA5  (cp_Descr)
1290        //        method_attr_bands
1291        //        ...
1292        assert(classes.length == numClasses);
1293        class_field_count.expectLength(numClasses);
1294        class_method_count.expectLength(numClasses);
1295        class_field_count.readFrom(in);
1296        class_method_count.readFrom(in);
1297
1298        // Make a pre-pass over field and method counts to size the descrs:
1299        int totalNF = class_field_count.getIntTotal();
1300        int totalNM = class_method_count.getIntTotal();
1301        field_descr.expectLength(totalNF);
1302        method_descr.expectLength(totalNM);
1303        if (verbose > 1)  Utils.log.fine("expecting #fields="+totalNF+
1304                " and #methods="+totalNM+" in #classes="+numClasses);
1305
1306        List<Class.Field> fields = new ArrayList<>(totalNF);
1307        field_descr.readFrom(in);
1308        for (int i = 0; i < classes.length; i++) {
1309            Class c = classes[i];
1310            int nf = class_field_count.getInt();
1311            for (int j = 0; j < nf; j++) {
1312                Class.Field f = c.new Field(NO_FLAGS_YET, (DescriptorEntry)
1313                                            field_descr.getRef());
1314                fields.add(f);
1315            }
1316        }
1317        class_field_count.doneDisbursing();
1318        field_descr.doneDisbursing();
1319        countAndReadAttrs(ATTR_CONTEXT_FIELD, fields);
1320        fields = null;  // release to GC
1321
1322        List<Class.Method> methods = new ArrayList<>(totalNM);
1323        method_descr.readFrom(in);
1324        for (int i = 0; i < classes.length; i++) {
1325            Class c = classes[i];
1326            int nm = class_method_count.getInt();
1327            for (int j = 0; j < nm; j++) {
1328                Class.Method m = c.new Method(NO_FLAGS_YET, (DescriptorEntry)
1329                                              method_descr.getRef());
1330                methods.add(m);
1331            }
1332        }
1333        class_method_count.doneDisbursing();
1334        method_descr.doneDisbursing();
1335        countAndReadAttrs(ATTR_CONTEXT_METHOD, methods);
1336
1337        // Up to this point, Code attributes look like empty attributes.
1338        // Now we start to special-case them.  The empty canonical Code
1339        // attributes stay in the method attribute lists, however.
1340        allCodes = buildCodeAttrs(methods);
1341    }
1342
1343    Code[] allCodes;
1344    List<Code> codesWithFlags;
1345    Map<Class, Set<Entry>> ldcRefMap = new HashMap<>();
1346
1347    Code[] buildCodeAttrs(List<Class.Method> methods) {
1348        List<Code> codes = new ArrayList<>(methods.size());
1349        for (Class.Method m : methods) {
1350            if (m.getAttribute(attrCodeEmpty) != null) {
1351                m.code = new Code(m);
1352                codes.add(m.code);
1353            }
1354        }
1355        Code[] a = new Code[codes.size()];
1356        codes.toArray(a);
1357        return a;
1358    }
1359
1360    void readCodeHeaders() throws IOException {
1361        //  code_bands:
1362        //        *code_headers :BYTE1
1363        //
1364        //        *code_max_stack :UNSIGNED5
1365        //        *code_max_na_locals :UNSIGNED5
1366        //        *code_handler_count :UNSIGNED5
1367        //        ...
1368        //        code_attr_bands
1369        boolean attrsOK = testBit(archiveOptions, AO_HAVE_ALL_CODE_FLAGS);
1370        code_headers.expectLength(allCodes.length);
1371        code_headers.readFrom(in);
1372        List<Code> longCodes = new ArrayList<>(allCodes.length / 10);
1373        for (int i = 0; i < allCodes.length; i++) {
1374            Code c = allCodes[i];
1375            int sc = code_headers.getByte();
1376            assert(sc == (sc & 0xFF));
1377            if (verbose > 2)
1378                Utils.log.fine("codeHeader "+c+" = "+sc);
1379            if (sc == LONG_CODE_HEADER) {
1380                // We will read ms/ml/nh/flags from bands shortly.
1381                longCodes.add(c);
1382                continue;
1383            }
1384            // Short code header is the usual case:
1385            c.setMaxStack(     shortCodeHeader_max_stack(sc) );
1386            c.setMaxNALocals(  shortCodeHeader_max_na_locals(sc) );
1387            c.setHandlerCount( shortCodeHeader_handler_count(sc) );
1388            assert(shortCodeHeader(c) == sc);
1389        }
1390        code_headers.doneDisbursing();
1391        code_max_stack.expectLength(longCodes.size());
1392        code_max_na_locals.expectLength(longCodes.size());
1393        code_handler_count.expectLength(longCodes.size());
1394
1395        // Do the long headers now.
1396        code_max_stack.readFrom(in);
1397        code_max_na_locals.readFrom(in);
1398        code_handler_count.readFrom(in);
1399        for (Code c : longCodes) {
1400            c.setMaxStack(     code_max_stack.getInt() );
1401            c.setMaxNALocals(  code_max_na_locals.getInt() );
1402            c.setHandlerCount( code_handler_count.getInt() );
1403        }
1404        code_max_stack.doneDisbursing();
1405        code_max_na_locals.doneDisbursing();
1406        code_handler_count.doneDisbursing();
1407
1408        readCodeHandlers();
1409
1410        if (attrsOK) {
1411            // Code attributes are common (debug info not stripped).
1412            codesWithFlags = Arrays.asList(allCodes);
1413        } else {
1414            // Code attributes are very sparse (debug info is stripped).
1415            codesWithFlags = longCodes;
1416        }
1417        countAttrs(ATTR_CONTEXT_CODE, codesWithFlags);
1418        // do readAttrs later, after BCs are scanned
1419    }
1420
1421    void readCodeHandlers() throws IOException {
1422        //  code_bands:
1423        //        ...
1424        //        *code_handler_start_P :BCI5
1425        //        *code_handler_end_PO :BRANCH5
1426        //        *code_handler_catch_PO :BRANCH5
1427        //        *code_handler_class_RCN :UNSIGNED5  (null or cp_Class)
1428        //        ...
1429        int nh = 0;
1430        for (int i = 0; i < allCodes.length; i++) {
1431            Code c = allCodes[i];
1432            nh += c.getHandlerCount();
1433        }
1434
1435        ValueBand[] code_handler_bands = {
1436            code_handler_start_P,
1437            code_handler_end_PO,
1438            code_handler_catch_PO,
1439            code_handler_class_RCN
1440        };
1441
1442        for (int i = 0; i < code_handler_bands.length; i++) {
1443            code_handler_bands[i].expectLength(nh);
1444            code_handler_bands[i].readFrom(in);
1445        }
1446
1447        for (int i = 0; i < allCodes.length; i++) {
1448            Code c = allCodes[i];
1449            for (int j = 0, jmax = c.getHandlerCount(); j < jmax; j++) {
1450                c.handler_class[j] = code_handler_class_RCN.getRef();
1451                // For now, just record the raw BCI codes.
1452                // We must wait until we have instruction boundaries.
1453                c.handler_start[j] = code_handler_start_P.getInt();
1454                c.handler_end[j]   = code_handler_end_PO.getInt();
1455                c.handler_catch[j] = code_handler_catch_PO.getInt();
1456            }
1457        }
1458        for (int i = 0; i < code_handler_bands.length; i++) {
1459            code_handler_bands[i].doneDisbursing();
1460        }
1461    }
1462
1463    void fixupCodeHandlers() {
1464        // Actually decode (renumber) the BCIs now.
1465        for (int i = 0; i < allCodes.length; i++) {
1466            Code c = allCodes[i];
1467            for (int j = 0, jmax = c.getHandlerCount(); j < jmax; j++) {
1468                int sum = c.handler_start[j];
1469                c.handler_start[j] = c.decodeBCI(sum);
1470                sum += c.handler_end[j];
1471                c.handler_end[j]   = c.decodeBCI(sum);
1472                sum += c.handler_catch[j];
1473                c.handler_catch[j] = c.decodeBCI(sum);
1474            }
1475        }
1476    }
1477
1478    // Generic routines for reading attributes of
1479    // classes, fields, methods, and codes.
1480    // The holders is a global list, already collected,
1481    // of attribute "customers".
1482    void countAndReadAttrs(int ctype, Collection<? extends Attribute.Holder> holders)
1483            throws IOException {
1484        //  class_attr_bands:
1485        //        *class_flags :UNSIGNED5
1486        //        *class_attr_count :UNSIGNED5
1487        //        *class_attr_indexes :UNSIGNED5
1488        //        *class_attr_calls :UNSIGNED5
1489        //        *class_Signature_RS :UNSIGNED5 (cp_Signature)
1490        //        class_metadata_bands
1491        //        *class_SourceFile_RU :UNSIGNED5 (cp_Utf8)
1492        //        *class_EnclosingMethod_RM :UNSIGNED5 (cp_Method)
1493        //        ic_local_bands
1494        //        *class_ClassFile_version_minor_H :UNSIGNED5
1495        //        *class_ClassFile_version_major_H :UNSIGNED5
1496        //        class_type_metadata_bands
1497        //
1498        //  field_attr_bands:
1499        //        *field_flags :UNSIGNED5
1500        //        *field_attr_count :UNSIGNED5
1501        //        *field_attr_indexes :UNSIGNED5
1502        //        *field_attr_calls :UNSIGNED5
1503        //        *field_Signature_RS :UNSIGNED5 (cp_Signature)
1504        //        field_metadata_bands
1505        //        *field_ConstantValue_KQ :UNSIGNED5 (cp_Int, etc.; see note)
1506        //        field_type_metadata_bands
1507        //
1508        //  method_attr_bands:
1509        //        *method_flags :UNSIGNED5
1510        //        *method_attr_count :UNSIGNED5
1511        //        *method_attr_indexes :UNSIGNED5
1512        //        *method_attr_calls :UNSIGNED5
1513        //        *method_Signature_RS :UNSIGNED5 (cp_Signature)
1514        //        method_metadata_bands
1515        //        *method_Exceptions_N :UNSIGNED5
1516        //        *method_Exceptions_RC :UNSIGNED5  (cp_Class)
1517        //        *method_MethodParameters_NB: BYTE1
1518        //        *method_MethodParameters_RUN: UNSIGNED5 (cp_Utf8)
1519        //        *method_MethodParameters_FH:  UNSIGNED5 (flag)
1520        //        method_type_metadata_bands
1521        //
1522        //  code_attr_bands:
1523        //        *code_flags :UNSIGNED5
1524        //        *code_attr_count :UNSIGNED5
1525        //        *code_attr_indexes :UNSIGNED5
1526        //        *code_attr_calls :UNSIGNED5
1527        //        *code_LineNumberTable_N :UNSIGNED5
1528        //        *code_LineNumberTable_bci_P :BCI5
1529        //        *code_LineNumberTable_line :UNSIGNED5
1530        //        *code_LocalVariableTable_N :UNSIGNED5
1531        //        *code_LocalVariableTable_bci_P :BCI5
1532        //        *code_LocalVariableTable_span_O :BRANCH5
1533        //        *code_LocalVariableTable_name_RU :UNSIGNED5 (cp_Utf8)
1534        //        *code_LocalVariableTable_type_RS :UNSIGNED5 (cp_Signature)
1535        //        *code_LocalVariableTable_slot :UNSIGNED5
1536        //        code_type_metadata_bands
1537
1538        countAttrs(ctype, holders);
1539        readAttrs(ctype, holders);
1540    }
1541
1542    // Read flags and count the attributes that are to be placed
1543    // on the given holders.
1544    void countAttrs(int ctype, Collection<? extends Attribute.Holder> holders)
1545            throws IOException {
1546        // Here, xxx stands for one of class, field, method, code.
1547        MultiBand xxx_attr_bands = attrBands[ctype];
1548        long flagMask = attrFlagMask[ctype];
1549        if (verbose > 1) {
1550            Utils.log.fine("scanning flags and attrs for "+
1551                    Attribute.contextName(ctype)+"["+holders.size()+"]");
1552        }
1553
1554        // Fetch the attribute layout definitions which govern the bands
1555        // we are about to read.
1556        List<Attribute.Layout> defList = attrDefs.get(ctype);
1557        Attribute.Layout[] defs = new Attribute.Layout[defList.size()];
1558        defList.toArray(defs);
1559        IntBand xxx_flags_hi = getAttrBand(xxx_attr_bands, AB_FLAGS_HI);
1560        IntBand xxx_flags_lo = getAttrBand(xxx_attr_bands, AB_FLAGS_LO);
1561        IntBand xxx_attr_count = getAttrBand(xxx_attr_bands, AB_ATTR_COUNT);
1562        IntBand xxx_attr_indexes = getAttrBand(xxx_attr_bands, AB_ATTR_INDEXES);
1563        IntBand xxx_attr_calls = getAttrBand(xxx_attr_bands, AB_ATTR_CALLS);
1564
1565        // Count up the number of holders which have overflow attrs.
1566        int overflowMask = attrOverflowMask[ctype];
1567        int overflowHolderCount = 0;
1568        boolean haveLongFlags = haveFlagsHi(ctype);
1569        xxx_flags_hi.expectLength(haveLongFlags? holders.size(): 0);
1570        xxx_flags_hi.readFrom(in);
1571        xxx_flags_lo.expectLength(holders.size());
1572        xxx_flags_lo.readFrom(in);
1573        assert((flagMask & overflowMask) == overflowMask);
1574        for (Attribute.Holder h : holders) {
1575            int flags = xxx_flags_lo.getInt();
1576            h.flags = flags;
1577            if ((flags & overflowMask) != 0)
1578                overflowHolderCount += 1;
1579        }
1580
1581        // For each holder with overflow attrs, read a count.
1582        xxx_attr_count.expectLength(overflowHolderCount);
1583        xxx_attr_count.readFrom(in);
1584        xxx_attr_indexes.expectLength(xxx_attr_count.getIntTotal());
1585        xxx_attr_indexes.readFrom(in);
1586
1587        // Now it's time to check flag bits that indicate attributes.
1588        // We accumulate (a) a list of attribute types for each holder
1589        // (class/field/method/code), and also we accumulate (b) a total
1590        // count for each attribute type.
1591        int[] totalCounts = new int[defs.length];
1592        for (Attribute.Holder h : holders) {
1593            assert(h.attributes == null);
1594            // System.out.println("flags="+h.flags+" using fm="+flagMask);
1595            long attrBits = ((h.flags & flagMask) << 32) >>> 32;
1596            // Clean up the flags now.
1597            h.flags -= (int)attrBits;   // strip attr bits
1598            assert(h.flags == (char)h.flags);  // 16 bits only now
1599            assert((ctype != ATTR_CONTEXT_CODE) || h.flags == 0);
1600            if (haveLongFlags)
1601                attrBits += (long)xxx_flags_hi.getInt() << 32;
1602            if (attrBits == 0)  continue;  // no attrs on this guy
1603
1604            int noa = 0;  // number of overflow attrs
1605            long overflowBit = (attrBits & overflowMask);
1606            assert(overflowBit >= 0);
1607            attrBits -= overflowBit;
1608            if (overflowBit != 0) {
1609                noa = xxx_attr_count.getInt();
1610            }
1611
1612            int nfa = 0;  // number of flag attrs
1613            long bits = attrBits;
1614            for (int ai = 0; bits != 0; ai++) {
1615                if ((bits & (1L<<ai)) == 0)  continue;
1616                bits -= (1L<<ai);
1617                nfa += 1;
1618            }
1619            List<Attribute> ha = new ArrayList<>(nfa + noa);
1620            h.attributes = ha;
1621            bits = attrBits;  // iterate again
1622            for (int ai = 0; bits != 0; ai++) {
1623                if ((bits & (1L<<ai)) == 0)  continue;
1624                bits -= (1L<<ai);
1625                totalCounts[ai] += 1;
1626                // This definition index is live in this holder.
1627                if (defs[ai] == null)  badAttrIndex(ai, ctype);
1628                Attribute canonical = defs[ai].canonicalInstance();
1629                ha.add(canonical);
1630                nfa -= 1;
1631            }
1632            assert(nfa == 0);
1633            for (; noa > 0; noa--) {
1634                int ai = xxx_attr_indexes.getInt();
1635                totalCounts[ai] += 1;
1636                // This definition index is live in this holder.
1637                if (defs[ai] == null)  badAttrIndex(ai, ctype);
1638                Attribute canonical = defs[ai].canonicalInstance();
1639                ha.add(canonical);
1640            }
1641        }
1642
1643        xxx_flags_hi.doneDisbursing();
1644        xxx_flags_lo.doneDisbursing();
1645        xxx_attr_count.doneDisbursing();
1646        xxx_attr_indexes.doneDisbursing();
1647
1648        // Now each holder has a list of canonical attribute instances.
1649        // For layouts with no elements, we are done.  However, for
1650        // layouts with bands, we must replace each canonical (empty)
1651        // instance with a value-bearing one, initialized from the
1652        // appropriate bands.
1653
1654        // Make a small pass to detect and read backward call counts.
1655        int callCounts = 0;
1656        for (boolean predef = true; ; predef = false) {
1657            for (int ai = 0; ai < defs.length; ai++) {
1658                Attribute.Layout def = defs[ai];
1659                if (def == null)  continue;  // unused index
1660                if (predef != isPredefinedAttr(ctype, ai))
1661                    continue;  // wrong pass
1662                int totalCount = totalCounts[ai];
1663                if (totalCount == 0)
1664                    continue;  // irrelevant
1665                Attribute.Layout.Element[] cbles = def.getCallables();
1666                for (int j = 0; j < cbles.length; j++) {
1667                    assert(cbles[j].kind == Attribute.EK_CBLE);
1668                    if (cbles[j].flagTest(Attribute.EF_BACK))
1669                        callCounts += 1;
1670                }
1671            }
1672            if (!predef)  break;
1673        }
1674        xxx_attr_calls.expectLength(callCounts);
1675        xxx_attr_calls.readFrom(in);
1676
1677        // Finally, size all the attribute bands.
1678        for (boolean predef = true; ; predef = false) {
1679            for (int ai = 0; ai < defs.length; ai++) {
1680                Attribute.Layout def = defs[ai];
1681                if (def == null)  continue;  // unused index
1682                if (predef != isPredefinedAttr(ctype, ai))
1683                    continue;  // wrong pass
1684                int totalCount = totalCounts[ai];
1685                Band[] ab = attrBandTable.get(def);
1686                if (def == attrInnerClassesEmpty) {
1687                    // Special case.
1688                    // Size the bands as if using the following layout:
1689                    //    [RCH TI[ (0)[] ()[RCNH RUNH] ]].
1690                    class_InnerClasses_N.expectLength(totalCount);
1691                    class_InnerClasses_N.readFrom(in);
1692                    int tupleCount = class_InnerClasses_N.getIntTotal();
1693                    class_InnerClasses_RC.expectLength(tupleCount);
1694                    class_InnerClasses_RC.readFrom(in);
1695                    class_InnerClasses_F.expectLength(tupleCount);
1696                    class_InnerClasses_F.readFrom(in);
1697                    // Drop remaining columns wherever flags are zero:
1698                    tupleCount -= class_InnerClasses_F.getIntCount(0);
1699                    class_InnerClasses_outer_RCN.expectLength(tupleCount);
1700                    class_InnerClasses_outer_RCN.readFrom(in);
1701                    class_InnerClasses_name_RUN.expectLength(tupleCount);
1702                    class_InnerClasses_name_RUN.readFrom(in);
1703                } else if (!optDebugBands && totalCount == 0) {
1704                    // Expect no elements at all.  Skip quickly. however if we
1705                    // are debugging bands, read all bands regardless
1706                    for (int j = 0; j < ab.length; j++) {
1707                        ab[j].doneWithUnusedBand();
1708                    }
1709                } else {
1710                    // Read these bands in sequence.
1711                    boolean hasCallables = def.hasCallables();
1712                    if (!hasCallables) {
1713                        readAttrBands(def.elems, totalCount, new int[0], ab);
1714                    } else {
1715                        Attribute.Layout.Element[] cbles = def.getCallables();
1716                        // At first, record initial calls.
1717                        // Later, forward calls may also accumulate here:
1718                        int[] forwardCounts = new int[cbles.length];
1719                        forwardCounts[0] = totalCount;
1720                        for (int j = 0; j < cbles.length; j++) {
1721                            assert(cbles[j].kind == Attribute.EK_CBLE);
1722                            int entryCount = forwardCounts[j];
1723                            forwardCounts[j] = -1;  // No more, please!
1724                            if (totalCount > 0 && cbles[j].flagTest(Attribute.EF_BACK))
1725                                entryCount += xxx_attr_calls.getInt();
1726                            readAttrBands(cbles[j].body, entryCount, forwardCounts, ab);
1727                        }
1728                    }
1729                    // mark them read,  to satisfy asserts
1730                    if (optDebugBands && totalCount == 0) {
1731                        for (int j = 0; j < ab.length; j++) {
1732                            ab[j].doneDisbursing();
1733                        }
1734                    }
1735                }
1736            }
1737            if (!predef)  break;
1738        }
1739        xxx_attr_calls.doneDisbursing();
1740    }
1741
1742    void badAttrIndex(int ai, int ctype) throws IOException {
1743        throw new IOException("Unknown attribute index "+ai+" for "+
1744                                   ATTR_CONTEXT_NAME[ctype]+" attribute");
1745    }
1746
1747    void readAttrs(int ctype, Collection<? extends Attribute.Holder> holders)
1748            throws IOException {
1749        // Decode band values into attributes.
1750        Set<Attribute.Layout> sawDefs = new HashSet<>();
1751        ByteArrayOutputStream buf = new ByteArrayOutputStream();
1752        for (final Attribute.Holder h : holders) {
1753            if (h.attributes == null)  continue;
1754            for (ListIterator<Attribute> j = h.attributes.listIterator(); j.hasNext(); ) {
1755                Attribute a = j.next();
1756                Attribute.Layout def = a.layout();
1757                if (def.bandCount == 0) {
1758                    if (def == attrInnerClassesEmpty) {
1759                        // Special logic to read this attr.
1760                        readLocalInnerClasses((Class) h);
1761                        continue;
1762                    }
1763                    // Canonical empty attr works fine (e.g., Synthetic).
1764                    continue;
1765                }
1766                sawDefs.add(def);
1767                boolean isCV = (ctype == ATTR_CONTEXT_FIELD && def == attrConstantValue);
1768                if (isCV)  setConstantValueIndex((Class.Field)h);
1769                if (verbose > 2)
1770                    Utils.log.fine("read "+a+" in "+h);
1771                final Band[] ab = attrBandTable.get(def);
1772                // Read one attribute of type def from ab into a byte array.
1773                buf.reset();
1774                Object fixups = a.unparse(new Attribute.ValueStream() {
1775                    public int getInt(int bandIndex) {
1776                        return ((IntBand) ab[bandIndex]).getInt();
1777                    }
1778                    public Entry getRef(int bandIndex) {
1779                        return ((CPRefBand) ab[bandIndex]).getRef();
1780                    }
1781                    public int decodeBCI(int bciCode) {
1782                        Code code = (Code) h;
1783                        return code.decodeBCI(bciCode);
1784                    }
1785                }, buf);
1786                // Replace the canonical attr with the one just read.
1787                j.set(a.addContent(buf.toByteArray(), fixups));
1788                if (isCV)  setConstantValueIndex(null);  // clean up
1789            }
1790        }
1791
1792        // Mark the bands we just used as done disbursing.
1793        for (Attribute.Layout def : sawDefs) {
1794            if (def == null)  continue;  // unused index
1795            Band[] ab = attrBandTable.get(def);
1796            for (int j = 0; j < ab.length; j++) {
1797                ab[j].doneDisbursing();
1798            }
1799        }
1800
1801        if (ctype == ATTR_CONTEXT_CLASS) {
1802            class_InnerClasses_N.doneDisbursing();
1803            class_InnerClasses_RC.doneDisbursing();
1804            class_InnerClasses_F.doneDisbursing();
1805            class_InnerClasses_outer_RCN.doneDisbursing();
1806            class_InnerClasses_name_RUN.doneDisbursing();
1807        }
1808
1809        MultiBand xxx_attr_bands = attrBands[ctype];
1810        for (int i = 0; i < xxx_attr_bands.size(); i++) {
1811            Band b = xxx_attr_bands.get(i);
1812            if (b instanceof MultiBand)
1813                b.doneDisbursing();
1814        }
1815        xxx_attr_bands.doneDisbursing();
1816    }
1817
1818    private
1819    void readAttrBands(Attribute.Layout.Element[] elems,
1820                       int count, int[] forwardCounts,
1821                       Band[] ab)
1822            throws IOException {
1823        for (int i = 0; i < elems.length; i++) {
1824            Attribute.Layout.Element e = elems[i];
1825            Band eBand = null;
1826            if (e.hasBand()) {
1827                eBand = ab[e.bandIndex];
1828                eBand.expectLength(count);
1829                eBand.readFrom(in);
1830            }
1831            switch (e.kind) {
1832            case Attribute.EK_REPL:
1833                // Recursive call.
1834                int repCount = ((IntBand)eBand).getIntTotal();
1835                // Note:  getIntTotal makes an extra pass over this band.
1836                readAttrBands(e.body, repCount, forwardCounts, ab);
1837                break;
1838            case Attribute.EK_UN:
1839                int remainingCount = count;
1840                for (int j = 0; j < e.body.length; j++) {
1841                    int caseCount;
1842                    if (j == e.body.length-1) {
1843                        caseCount = remainingCount;
1844                    } else {
1845                        caseCount = 0;
1846                        for (int j0 = j;
1847                             (j == j0)
1848                             || (j < e.body.length
1849                                 && e.body[j].flagTest(Attribute.EF_BACK));
1850                             j++) {
1851                            caseCount += ((IntBand)eBand).getIntCount(e.body[j].value);
1852                        }
1853                        --j;  // back up to last occurrence of this body
1854                    }
1855                    remainingCount -= caseCount;
1856                    readAttrBands(e.body[j].body, caseCount, forwardCounts, ab);
1857                }
1858                assert(remainingCount == 0);
1859                break;
1860            case Attribute.EK_CALL:
1861                assert(e.body.length == 1);
1862                assert(e.body[0].kind == Attribute.EK_CBLE);
1863                if (!e.flagTest(Attribute.EF_BACK)) {
1864                    // Backward calls are pre-counted, but forwards are not.
1865                    // Push the present count forward.
1866                    assert(forwardCounts[e.value] >= 0);
1867                    forwardCounts[e.value] += count;
1868                }
1869                break;
1870            case Attribute.EK_CBLE:
1871                assert(false);
1872                break;
1873            }
1874        }
1875    }
1876
1877    void readByteCodes() throws IOException {
1878        //  bc_bands:
1879        //        *bc_codes :BYTE1
1880        //        *bc_case_count :UNSIGNED5
1881        //        *bc_case_value :DELTA5
1882        //        *bc_byte :BYTE1
1883        //        *bc_short :DELTA5
1884        //        *bc_local :UNSIGNED5
1885        //        *bc_label :BRANCH5
1886        //        *bc_intref :DELTA5  (cp_Int)
1887        //        *bc_floatref :DELTA5  (cp_Float)
1888        //        *bc_longref :DELTA5  (cp_Long)
1889        //        *bc_doubleref :DELTA5  (cp_Double)
1890        //        *bc_stringref :DELTA5  (cp_String)
1891        //        *bc_classref :UNSIGNED5  (current class or cp_Class)
1892        //        *bc_fieldref :DELTA5  (cp_Field)
1893        //        *bc_methodref :UNSIGNED5  (cp_Method)
1894        //        *bc_imethodref :DELTA5  (cp_Imethod)
1895        //        *bc_thisfield :UNSIGNED5 (cp_Field, only for current class)
1896        //        *bc_superfield :UNSIGNED5 (cp_Field, only for current super)
1897        //        *bc_thismethod :UNSIGNED5 (cp_Method, only for current class)
1898        //        *bc_supermethod :UNSIGNED5 (cp_Method, only for current super)
1899        //        *bc_initref :UNSIGNED5 (cp_Field, only for most recent new)
1900        //        *bc_escref :UNSIGNED5 (cp_All)
1901        //        *bc_escrefsize :UNSIGNED5
1902        //        *bc_escsize :UNSIGNED5
1903        //        *bc_escbyte :BYTE1
1904        bc_codes.elementCountForDebug = allCodes.length;
1905        bc_codes.setInputStreamFrom(in);
1906        readByteCodeOps();  // reads from bc_codes and bc_case_count
1907        bc_codes.doneDisbursing();
1908
1909        // All the operand bands have now been sized.  Read them all in turn.
1910        Band[] operand_bands = {
1911            bc_case_value,
1912            bc_byte, bc_short,
1913            bc_local, bc_label,
1914            bc_intref, bc_floatref,
1915            bc_longref, bc_doubleref, bc_stringref,
1916            bc_loadablevalueref,
1917            bc_classref, bc_fieldref,
1918            bc_methodref, bc_imethodref,
1919            bc_indyref,
1920            bc_thisfield, bc_superfield,
1921            bc_thismethod, bc_supermethod,
1922            bc_initref,
1923            bc_escref, bc_escrefsize, bc_escsize
1924        };
1925        for (int i = 0; i < operand_bands.length; i++) {
1926            operand_bands[i].readFrom(in);
1927        }
1928        bc_escbyte.expectLength(bc_escsize.getIntTotal());
1929        bc_escbyte.readFrom(in);
1930
1931        expandByteCodeOps();
1932
1933        // Done fetching values from operand bands:
1934        bc_case_count.doneDisbursing();
1935        for (int i = 0; i < operand_bands.length; i++) {
1936            operand_bands[i].doneDisbursing();
1937        }
1938        bc_escbyte.doneDisbursing();
1939        bc_bands.doneDisbursing();
1940
1941        // We must delay the parsing of Code attributes until we
1942        // have a complete model of bytecodes, for BCI encodings.
1943        readAttrs(ATTR_CONTEXT_CODE, codesWithFlags);
1944        // Ditto for exception handlers in codes.
1945        fixupCodeHandlers();
1946        // Now we can finish with class_bands; cf. readClasses().
1947        code_bands.doneDisbursing();
1948        class_bands.doneDisbursing();
1949    }
1950
1951    private void readByteCodeOps() throws IOException {
1952        // scratch buffer for collecting code::
1953        byte[] buf = new byte[1<<12];
1954        // record of all switch opcodes (these are variable-length)
1955        List<Integer> allSwitchOps = new ArrayList<>();
1956        for (int k = 0; k < allCodes.length; k++) {
1957            Code c = allCodes[k];
1958        scanOneMethod:
1959            for (int i = 0; ; i++) {
1960                int bc = bc_codes.getByte();
1961                if (i + 10 > buf.length)  buf = realloc(buf);
1962                buf[i] = (byte)bc;
1963                boolean isWide = false;
1964                if (bc == _wide) {
1965                    bc = bc_codes.getByte();
1966                    buf[++i] = (byte)bc;
1967                    isWide = true;
1968                }
1969                assert(bc == (0xFF & bc));
1970                // Adjust expectations of various band sizes.
1971                switch (bc) {
1972                case _tableswitch:
1973                case _lookupswitch:
1974                    bc_case_count.expectMoreLength(1);
1975                    allSwitchOps.add(bc);
1976                    break;
1977                case _iinc:
1978                    bc_local.expectMoreLength(1);
1979                    if (isWide)
1980                        bc_short.expectMoreLength(1);
1981                    else
1982                        bc_byte.expectMoreLength(1);
1983                    break;
1984                case _sipush:
1985                    bc_short.expectMoreLength(1);
1986                    break;
1987                case _bipush:
1988                    bc_byte.expectMoreLength(1);
1989                    break;
1990                case _newarray:
1991                    bc_byte.expectMoreLength(1);
1992                    break;
1993                case _multianewarray:
1994                    assert(getCPRefOpBand(bc) == bc_classref);
1995                    bc_classref.expectMoreLength(1);
1996                    bc_byte.expectMoreLength(1);
1997                    break;
1998                case _ref_escape:
1999                    bc_escrefsize.expectMoreLength(1);
2000                    bc_escref.expectMoreLength(1);
2001                    break;
2002                case _byte_escape:
2003                    bc_escsize.expectMoreLength(1);
2004                    // bc_escbyte will have to be counted too
2005                    break;
2006                default:
2007                    if (Instruction.isInvokeInitOp(bc)) {
2008                        bc_initref.expectMoreLength(1);
2009                        break;
2010                    }
2011                    if (Instruction.isSelfLinkerOp(bc)) {
2012                        CPRefBand bc_which = selfOpRefBand(bc);
2013                        bc_which.expectMoreLength(1);
2014                        break;
2015                    }
2016                    if (Instruction.isBranchOp(bc)) {
2017                        bc_label.expectMoreLength(1);
2018                        break;
2019                    }
2020                    if (Instruction.isCPRefOp(bc)) {
2021                        CPRefBand bc_which = getCPRefOpBand(bc);
2022                        bc_which.expectMoreLength(1);
2023                        assert(bc != _multianewarray);  // handled elsewhere
2024                        break;
2025                    }
2026                    if (Instruction.isLocalSlotOp(bc)) {
2027                        bc_local.expectMoreLength(1);
2028                        break;
2029                    }
2030                    break;
2031                case _end_marker:
2032                    {
2033                        // Transfer from buf to a more permanent place:
2034                        c.bytes = realloc(buf, i);
2035                        break scanOneMethod;
2036                    }
2037                }
2038            }
2039        }
2040
2041        // To size instruction bands correctly, we need info on switches:
2042        bc_case_count.readFrom(in);
2043        for (Integer i : allSwitchOps) {
2044            int bc = i.intValue();
2045            int caseCount = bc_case_count.getInt();
2046            bc_label.expectMoreLength(1+caseCount); // default label + cases
2047            bc_case_value.expectMoreLength(bc == _tableswitch ? 1 : caseCount);
2048        }
2049        bc_case_count.resetForSecondPass();
2050    }
2051
2052    private void expandByteCodeOps() throws IOException {
2053        // scratch buffer for collecting code:
2054        byte[] buf = new byte[1<<12];
2055        // scratch buffer for collecting instruction boundaries:
2056        int[] insnMap = new int[1<<12];
2057        // list of label carriers, for label decoding post-pass:
2058        int[] labels = new int[1<<10];
2059        // scratch buffer for registering CP refs:
2060        Fixups fixupBuf = new Fixups();
2061
2062        for (int k = 0; k < allCodes.length; k++) {
2063            Code code = allCodes[k];
2064            byte[] codeOps = code.bytes;
2065            code.bytes = null;  // just for now, while we accumulate bits
2066
2067            Class curClass = code.thisClass();
2068
2069            Set<Entry> ldcRefSet = ldcRefMap.get(curClass);
2070            if (ldcRefSet == null)
2071                ldcRefMap.put(curClass, ldcRefSet = new HashSet<>());
2072
2073            ClassEntry thisClass  = curClass.thisClass;
2074            ClassEntry superClass = curClass.superClass;
2075            ClassEntry newClass   = null;  // class of last _new opcode
2076
2077            int pc = 0;  // fill pointer in buf; actual bytecode PC
2078            int numInsns = 0;
2079            int numLabels = 0;
2080            boolean hasEscs = false;
2081            fixupBuf.clear();
2082            for (int i = 0; i < codeOps.length; i++) {
2083                int bc = Instruction.getByte(codeOps, i);
2084                int curPC = pc;
2085                insnMap[numInsns++] = curPC;
2086                if (pc + 10 > buf.length)  buf = realloc(buf);
2087                if (numInsns+10 > insnMap.length)  insnMap = realloc(insnMap);
2088                if (numLabels+10 > labels.length)  labels = realloc(labels);
2089                boolean isWide = false;
2090                if (bc == _wide) {
2091                    buf[pc++] = (byte) bc;
2092                    bc = Instruction.getByte(codeOps, ++i);
2093                    isWide = true;
2094                }
2095                switch (bc) {
2096                case _tableswitch: // apc:  (df, lo, hi, (hi-lo+1)*(label))
2097                case _lookupswitch: // apc:  (df, nc, nc*(case, label))
2098                    {
2099                        int caseCount = bc_case_count.getInt();
2100                        while ((pc + 30 + caseCount*8) > buf.length)
2101                            buf = realloc(buf);
2102                        buf[pc++] = (byte) bc;
2103                        //initialize apc, df, lo, hi bytes to reasonable bits:
2104                        Arrays.fill(buf, pc, pc+30, (byte)0);
2105                        Instruction.Switch isw = (Instruction.Switch)
2106                            Instruction.at(buf, curPC);
2107                        //isw.setDefaultLabel(getLabel(bc_label, code, curPC));
2108                        isw.setCaseCount(caseCount);
2109                        if (bc == _tableswitch) {
2110                            isw.setCaseValue(0, bc_case_value.getInt());
2111                        } else {
2112                            for (int j = 0; j < caseCount; j++) {
2113                                isw.setCaseValue(j, bc_case_value.getInt());
2114                            }
2115                        }
2116                        // Make our getLabel calls later.
2117                        labels[numLabels++] = curPC;
2118                        pc = isw.getNextPC();
2119                        continue;
2120                    }
2121                case _iinc:
2122                    {
2123                        buf[pc++] = (byte) bc;
2124                        int local = bc_local.getInt();
2125                        int delta;
2126                        if (isWide) {
2127                            delta = bc_short.getInt();
2128                            Instruction.setShort(buf, pc, local); pc += 2;
2129                            Instruction.setShort(buf, pc, delta); pc += 2;
2130                        } else {
2131                            delta = (byte) bc_byte.getByte();
2132                            buf[pc++] = (byte)local;
2133                            buf[pc++] = (byte)delta;
2134                        }
2135                        continue;
2136                    }
2137                case _sipush:
2138                    {
2139                        int val = bc_short.getInt();
2140                        buf[pc++] = (byte) bc;
2141                        Instruction.setShort(buf, pc, val); pc += 2;
2142                        continue;
2143                    }
2144                case _bipush:
2145                case _newarray:
2146                    {
2147                        int val = bc_byte.getByte();
2148                        buf[pc++] = (byte) bc;
2149                        buf[pc++] = (byte) val;
2150                        continue;
2151                    }
2152                case _ref_escape:
2153                    {
2154                        // Note that insnMap has one entry for this.
2155                        hasEscs = true;
2156                        int size = bc_escrefsize.getInt();
2157                        Entry ref = bc_escref.getRef();
2158                        if (size == 1)  ldcRefSet.add(ref);
2159                        int fmt;
2160                        switch (size) {
2161                        case 1: fixupBuf.addU1(pc, ref); break;
2162                        case 2: fixupBuf.addU2(pc, ref); break;
2163                        default: assert(false); fmt = 0;
2164                        }
2165                        buf[pc+0] = buf[pc+1] = 0;
2166                        pc += size;
2167                    }
2168                    continue;
2169                case _byte_escape:
2170                    {
2171                        // Note that insnMap has one entry for all these bytes.
2172                        hasEscs = true;
2173                        int size = bc_escsize.getInt();
2174                        while ((pc + size) > buf.length)
2175                            buf = realloc(buf);
2176                        while (size-- > 0) {
2177                            buf[pc++] = (byte) bc_escbyte.getByte();
2178                        }
2179                    }
2180                    continue;
2181                default:
2182                    if (Instruction.isInvokeInitOp(bc)) {
2183                        int idx = (bc - _invokeinit_op);
2184                        int origBC = _invokespecial;
2185                        ClassEntry classRef;
2186                        switch (idx) {
2187                        case _invokeinit_self_option:
2188                            classRef = thisClass; break;
2189                        case _invokeinit_super_option:
2190                            classRef = superClass; break;
2191                        default:
2192                            assert(idx == _invokeinit_new_option);
2193                            classRef = newClass; break;
2194                        }
2195                        buf[pc++] = (byte) origBC;
2196                        int coding = bc_initref.getInt();
2197                        // Find the nth overloading of <init> in classRef.
2198                        MemberEntry ref = pkg.cp.getOverloadingForIndex(CONSTANT_Methodref, classRef, "<init>", coding);
2199                        fixupBuf.addU2(pc, ref);
2200                        buf[pc+0] = buf[pc+1] = 0;
2201                        pc += 2;
2202                        assert(Instruction.opLength(origBC) == (pc - curPC));
2203                        continue;
2204                    }
2205                    if (Instruction.isSelfLinkerOp(bc)) {
2206                        int idx = (bc - _self_linker_op);
2207                        boolean isSuper = (idx >= _self_linker_super_flag);
2208                        if (isSuper)  idx -= _self_linker_super_flag;
2209                        boolean isAload = (idx >= _self_linker_aload_flag);
2210                        if (isAload)  idx -= _self_linker_aload_flag;
2211                        int origBC = _first_linker_op + idx;
2212                        boolean isField = Instruction.isFieldOp(origBC);
2213                        CPRefBand bc_which;
2214                        ClassEntry which_cls  = isSuper ? superClass : thisClass;
2215                        Index which_ix;
2216                        if (isField) {
2217                            bc_which = isSuper ? bc_superfield  : bc_thisfield;
2218                            which_ix = pkg.cp.getMemberIndex(CONSTANT_Fieldref, which_cls);
2219                        } else {
2220                            bc_which = isSuper ? bc_supermethod : bc_thismethod;
2221                            which_ix = pkg.cp.getMemberIndex(CONSTANT_Methodref, which_cls);
2222                        }
2223                        assert(bc_which == selfOpRefBand(bc));
2224                        MemberEntry ref = (MemberEntry) bc_which.getRef(which_ix);
2225                        if (isAload) {
2226                            buf[pc++] = (byte) _aload_0;
2227                            curPC = pc;
2228                            // Note: insnMap keeps the _aload_0 separate.
2229                            insnMap[numInsns++] = curPC;
2230                        }
2231                        buf[pc++] = (byte) origBC;
2232                        fixupBuf.addU2(pc, ref);
2233                        buf[pc+0] = buf[pc+1] = 0;
2234                        pc += 2;
2235                        assert(Instruction.opLength(origBC) == (pc - curPC));
2236                        continue;
2237                    }
2238                    if (Instruction.isBranchOp(bc)) {
2239                        buf[pc++] = (byte) bc;
2240                        assert(!isWide);  // no wide prefix for branches
2241                        int nextPC = curPC + Instruction.opLength(bc);
2242                        // Make our getLabel calls later.
2243                        labels[numLabels++] = curPC;
2244                        //Instruction.at(buf, curPC).setBranchLabel(getLabel(bc_label, code, curPC));
2245                        while (pc < nextPC)  buf[pc++] = 0;
2246                        continue;
2247                    }
2248                    if (Instruction.isCPRefOp(bc)) {
2249                        CPRefBand bc_which = getCPRefOpBand(bc);
2250                        Entry ref = bc_which.getRef();
2251                        if (ref == null) {
2252                            if (bc_which == bc_classref) {
2253                                // Shorthand for class self-references.
2254                                ref = thisClass;
2255                            } else {
2256                                assert(false);
2257                            }
2258                        }
2259                        int origBC = bc;
2260                        int size = 2;
2261                        switch (bc) {
2262                        case _invokestatic_int:
2263                            origBC = _invokestatic;
2264                            break;
2265                        case _invokespecial_int:
2266                            origBC = _invokespecial;
2267                            break;
2268                        case _ildc:
2269                        case _cldc:
2270                        case _fldc:
2271                        case _sldc:
2272                        case _qldc:
2273                            origBC = _ldc;
2274                            size = 1;
2275                            ldcRefSet.add(ref);
2276                            break;
2277                        case _ildc_w:
2278                        case _cldc_w:
2279                        case _fldc_w:
2280                        case _sldc_w:
2281                        case _qldc_w:
2282                            origBC = _ldc_w;
2283                            break;
2284                        case _lldc2_w:
2285                        case _dldc2_w:
2286                            origBC = _ldc2_w;
2287                            break;
2288                        case _new:
2289                            newClass = (ClassEntry) ref;
2290                            break;
2291                        }
2292                        buf[pc++] = (byte) origBC;
2293                        int fmt;
2294                        switch (size) {
2295                        case 1: fixupBuf.addU1(pc, ref); break;
2296                        case 2: fixupBuf.addU2(pc, ref); break;
2297                        default: assert(false); fmt = 0;
2298                        }
2299                        buf[pc+0] = buf[pc+1] = 0;
2300                        pc += size;
2301                        if (origBC == _multianewarray) {
2302                            // Copy the trailing byte also.
2303                            int val = bc_byte.getByte();
2304                            buf[pc++] = (byte) val;
2305                        } else if (origBC == _invokeinterface) {
2306                            int argSize = ((MemberEntry)ref).descRef.typeRef.computeSize(true);
2307                            buf[pc++] = (byte)( 1 + argSize );
2308                            buf[pc++] = 0;
2309                        } else if (origBC == _invokedynamic) {
2310                            buf[pc++] = 0;
2311                            buf[pc++] = 0;
2312                        }
2313                        assert(Instruction.opLength(origBC) == (pc - curPC));
2314                        continue;
2315                    }
2316                    if (Instruction.isLocalSlotOp(bc)) {
2317                        buf[pc++] = (byte) bc;
2318                        int local = bc_local.getInt();
2319                        if (isWide) {
2320                            Instruction.setShort(buf, pc, local);
2321                            pc += 2;
2322                            if (bc == _iinc) {
2323                                int iVal = bc_short.getInt();
2324                                Instruction.setShort(buf, pc, iVal);
2325                                pc += 2;
2326                            }
2327                        } else {
2328                            Instruction.setByte(buf, pc, local);
2329                            pc += 1;
2330                            if (bc == _iinc) {
2331                                int iVal = bc_byte.getByte();
2332                                Instruction.setByte(buf, pc, iVal);
2333                                pc += 1;
2334                            }
2335                        }
2336                        assert(Instruction.opLength(bc) == (pc - curPC));
2337                        continue;
2338                    }
2339                    // Random bytecode.  Just copy it.
2340                    if (bc >= _bytecode_limit)
2341                        Utils.log.warning("unrecognized bytescode "+bc
2342                                            +" "+Instruction.byteName(bc));
2343                    assert(bc < _bytecode_limit);
2344                    buf[pc++] = (byte) bc;
2345                    assert(Instruction.opLength(bc) == (pc - curPC));
2346                    continue;
2347                }
2348            }
2349            // now make a permanent copy of the bytecodes
2350            code.setBytes(realloc(buf, pc));
2351            code.setInstructionMap(insnMap, numInsns);
2352            // fix up labels, now that code has its insnMap
2353            Instruction ibr = null;  // temporary branch instruction
2354            for (int i = 0; i < numLabels; i++) {
2355                int curPC = labels[i];
2356                // (Note:  Passing ibr in allows reuse, a speed hack.)
2357                ibr = Instruction.at(code.bytes, curPC, ibr);
2358                if (ibr instanceof Instruction.Switch) {
2359                    Instruction.Switch isw = (Instruction.Switch) ibr;
2360                    isw.setDefaultLabel(getLabel(bc_label, code, curPC));
2361                    int caseCount = isw.getCaseCount();
2362                    for (int j = 0; j < caseCount; j++) {
2363                        isw.setCaseLabel(j, getLabel(bc_label, code, curPC));
2364                    }
2365                } else {
2366                    ibr.setBranchLabel(getLabel(bc_label, code, curPC));
2367                }
2368            }
2369            if (fixupBuf.size() > 0) {
2370                if (verbose > 2)
2371                    Utils.log.fine("Fixups in code: "+fixupBuf);
2372                code.addFixups(fixupBuf);
2373            }
2374        }
2375    }
2376}
2377