Source Code Cross Referenced for PackageReader.java in  » 6.0-JDK-Modules-com.sun.java » util » com » sun » java » util » jar » pack » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules com.sun.java » util » com.sun.java.util.jar.pack 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2001-2005 Sun Microsystems, Inc.  All Rights Reserved.
0003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004:         *
0005:         * This code is free software; you can redistribute it and/or modify it
0006:         * under the terms of the GNU General Public License version 2 only, as
0007:         * published by the Free Software Foundation.  Sun designates this
0008:         * particular file as subject to the "Classpath" exception as provided
0009:         * by Sun in the LICENSE file that accompanied this code.
0010:         *
0011:         * This code is distributed in the hope that it will be useful, but WITHOUT
0012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014:         * version 2 for more details (a copy is included in the LICENSE file that
0015:         * accompanied this code).
0016:         *
0017:         * You should have received a copy of the GNU General Public License version
0018:         * 2 along with this work; if not, write to the Free Software Foundation,
0019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020:         *
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022:         * CA 95054 USA or visit www.sun.com if you need additional information or
0023:         * have any questions.
0024:         */
0025:
0026:        package com.sun.java.util.jar.pack;
0027:
0028:        import java.io.*;
0029:        import java.util.*;
0030:        import java.util.logging.Level;
0031:        import com.sun.java.util.jar.pack.Package.Class;
0032:        import com.sun.java.util.jar.pack.Package.File;
0033:        import com.sun.java.util.jar.pack.Package.InnerClass;
0034:        import com.sun.java.util.jar.pack.ConstantPool.*;
0035:
0036:        /**
0037:         * Reader for a package file.
0038:         *
0039:         * @see PackageWriter
0040:         * @author John Rose
0041:         * @version 1.32, 05/05/07
0042:         */
0043:        class PackageReader extends BandStructure {
0044:            Package pkg;
0045:            byte[] bytes;
0046:            LimitedBuffer in;
0047:
0048:            PackageReader(Package pkg, InputStream in) throws IOException {
0049:                this .pkg = pkg;
0050:                this .in = new LimitedBuffer(in);
0051:            }
0052:
0053:            /** A buffered input stream which is careful not to
0054:             *  read its underlying stream ahead of a given mark,
0055:             *  called the 'readLimit'.  This property declares
0056:             *  the maximum number of characters that future reads
0057:             *  can consume from the underlying stream.
0058:             */
0059:            static class LimitedBuffer extends BufferedInputStream {
0060:                long served; // total number of charburgers served
0061:                int servedPos; // ...as of this value of super.pos
0062:                long limit; // current declared limit
0063:                long buffered;
0064:
0065:                public boolean atLimit() {
0066:                    boolean z = (getBytesServed() == limit);
0067:                    assert (!z || limit == buffered);
0068:                    return z;
0069:                }
0070:
0071:                public long getBytesServed() {
0072:                    return served + (pos - servedPos);
0073:                }
0074:
0075:                public void setReadLimit(long newLimit) {
0076:                    if (newLimit == -1)
0077:                        limit = -1;
0078:                    else
0079:                        limit = getBytesServed() + newLimit;
0080:                }
0081:
0082:                public long getReadLimit() {
0083:                    if (limit == -1)
0084:                        return limit;
0085:                    else
0086:                        return limit - getBytesServed();
0087:                }
0088:
0089:                public int read() throws IOException {
0090:                    if (pos < count) {
0091:                        // fast path
0092:                        return buf[pos++] & 0xFF;
0093:                    }
0094:                    served += (pos - servedPos);
0095:                    int ch = super .read();
0096:                    servedPos = pos;
0097:                    if (ch >= 0)
0098:                        served += 1;
0099:                    assert (served <= limit || limit == -1);
0100:                    return ch;
0101:                }
0102:
0103:                public int read(byte b[], int off, int len) throws IOException {
0104:                    served += (pos - servedPos);
0105:                    int nr = super .read(b, off, len);
0106:                    servedPos = pos;
0107:                    if (nr >= 0)
0108:                        served += nr;
0109:                    assert (served <= limit || limit == -1);
0110:                    return nr;
0111:                }
0112:
0113:                public long skip(long n) throws IOException {
0114:                    throw new RuntimeException("no skipping");
0115:                }
0116:
0117:                LimitedBuffer(InputStream originalIn) {
0118:                    super (null, 1 << 14);
0119:                    servedPos = pos;
0120:                    super .in = new FilterInputStream(originalIn) {
0121:                        public int read() throws IOException {
0122:                            if (buffered == limit)
0123:                                return -1;
0124:                            ++buffered;
0125:                            return super .read();
0126:                        }
0127:
0128:                        public int read(byte b[], int off, int len)
0129:                                throws IOException {
0130:                            if (buffered == limit)
0131:                                return -1;
0132:                            if (limit != -1) {
0133:                                long remaining = limit - buffered;
0134:                                if (len > remaining)
0135:                                    len = (int) remaining;
0136:                            }
0137:                            int nr = super .read(b, off, len);
0138:                            if (nr >= 0)
0139:                                buffered += nr;
0140:                            return nr;
0141:                        }
0142:                    };
0143:                }
0144:            }
0145:
0146:            void read() throws IOException {
0147:                boolean ok = false;
0148:                try {
0149:                    //  pack200_archive:
0150:                    //        file_header
0151:                    //        *band_headers :BYTE1
0152:                    //        cp_bands
0153:                    //        attr_definition_bands
0154:                    //        ic_bands
0155:                    //        class_bands
0156:                    //        bc_bands
0157:                    //        file_bands
0158:                    readFileHeader();
0159:                    readBandHeaders();
0160:                    readConstantPool(); // cp_bands
0161:                    readAttrDefs();
0162:                    readInnerClasses();
0163:                    Class[] classes = readClasses();
0164:                    readByteCodes();
0165:                    readFiles(); // file_bands
0166:                    assert (archiveSize1 == 0 || in.atLimit());
0167:                    assert (archiveSize1 == 0 || in.getBytesServed() == archiveSize0
0168:                            + archiveSize1);
0169:                    all_bands.doneDisbursing();
0170:
0171:                    // As a post-pass, build constant pools and inner classes.
0172:                    for (int i = 0; i < classes.length; i++) {
0173:                        reconstructClass(classes[i]);
0174:                    }
0175:
0176:                    ok = true;
0177:                } catch (Exception ee) {
0178:                    Utils.log.log(Level.WARNING, "Error on input: " + ee, ee);
0179:                    if (verbose > 0)
0180:                        Utils.log.info("Stream offsets:" + " served="
0181:                                + in.getBytesServed() + " buffered="
0182:                                + in.buffered + " limit=" + in.limit);
0183:                    //if (verbose > 0)  ee.printStackTrace();
0184:                    if (ee instanceof  IOException)
0185:                        throw (IOException) ee;
0186:                    if (ee instanceof  RuntimeException)
0187:                        throw (RuntimeException) ee;
0188:                    throw new Error("error unpacking", ee);
0189:                }
0190:            }
0191:
0192:            // Temporary count values, until band decoding gets rolling.
0193:            int[] tagCount = new int[CONSTANT_Limit];
0194:            int numFiles;
0195:            int numAttrDefs;
0196:            int numInnerClasses;
0197:            int numClasses;
0198:
0199:            void readFileHeader() throws IOException {
0200:                //  file_header:
0201:                //        archive_magic archive_header
0202:                readArchiveMagic();
0203:                readArchiveHeader();
0204:            }
0205:
0206:            // Local routine used to parse fixed-format scalars
0207:            // in the file_header:
0208:            private int getMagicInt32() throws IOException {
0209:                int res = 0;
0210:                for (int i = 0; i < 4; i++) {
0211:                    res <<= 8;
0212:                    res |= (archive_magic.getByte() & 0xFF);
0213:                }
0214:                return res;
0215:            }
0216:
0217:            final static int MAGIC_BYTES = 4;
0218:
0219:            void readArchiveMagic() throws IOException {
0220:
0221:                // Read a minimum of bytes in the first gulp.
0222:                in.setReadLimit(MAGIC_BYTES + AH_LENGTH_MIN);
0223:
0224:                //  archive_magic:
0225:                //        #archive_magic_word :BYTE1[4]
0226:                archive_magic.expectLength(MAGIC_BYTES);
0227:                archive_magic.readFrom(in);
0228:
0229:                // read and check magic numbers:
0230:                pkg.magic = getMagicInt32();
0231:                archive_magic.doneDisbursing();
0232:            }
0233:
0234:            void readArchiveHeader() throws IOException {
0235:                //  archive_header:
0236:                //        #archive_minver :UNSIGNED5[1]
0237:                //        #archive_majver :UNSIGNED5[1]
0238:                //        #archive_options :UNSIGNED5[1]
0239:                //        (archive_file_counts) ** (#have_file_headers)
0240:                //        (archive_special_counts) ** (#have_special_formats)
0241:                //        cp_counts
0242:                //        class_counts
0243:                //
0244:                //  archive_file_counts:
0245:                //        #archive_size_hi :UNSIGNED5[1]
0246:                //        #archive_size_lo :UNSIGNED5[1]
0247:                //        #archive_next_count :UNSIGNED5[1]
0248:                //        #archive_modtime :UNSIGNED5[1]
0249:                //        #file_count :UNSIGNED5[1]
0250:                //
0251:                //  class_counts:
0252:                //        #ic_count :UNSIGNED5[1]
0253:                //        #default_class_minver :UNSIGNED5[1]
0254:                //        #default_class_majver :UNSIGNED5[1]
0255:                //        #class_count :UNSIGNED5[1]
0256:                //
0257:                //  archive_special_counts:
0258:                //        #band_headers_size :UNSIGNED5[1]
0259:                //        #attr_definition_count :UNSIGNED5[1]
0260:                //        
0261:                assert (AH_LENGTH == 8 + (ConstantPool.TAGS_IN_ORDER.length) + 6);
0262:                archive_header_0.expectLength(AH_LENGTH_0);
0263:                archive_header_0.readFrom(in);
0264:
0265:                pkg.package_minver = archive_header_0.getInt();
0266:                pkg.package_majver = archive_header_0.getInt();
0267:                pkg.checkVersion();
0268:                this .initPackageMajver(pkg.package_majver);
0269:
0270:                archiveOptions = archive_header_0.getInt();
0271:                archive_header_0.doneDisbursing();
0272:
0273:                // detect archive optional fields in archive header
0274:                boolean haveSpecial = testBit(archiveOptions,
0275:                        AO_HAVE_SPECIAL_FORMATS);
0276:                boolean haveFiles = testBit(archiveOptions,
0277:                        AO_HAVE_FILE_HEADERS);
0278:                boolean haveNumbers = testBit(archiveOptions,
0279:                        AO_HAVE_CP_NUMBERS);
0280:                initAttrIndexLimit();
0281:
0282:                // now we are ready to use the data:
0283:                archive_header_S.expectLength(haveFiles ? AH_LENGTH_S : 0);
0284:                archive_header_S.readFrom(in);
0285:                if (haveFiles) {
0286:                    long sizeHi = archive_header_S.getInt();
0287:                    long sizeLo = archive_header_S.getInt();
0288:                    archiveSize1 = (sizeHi << 32) + ((sizeLo << 32) >>> 32);
0289:                    // Set the limit, now, up to the file_bits.
0290:                    in.setReadLimit(archiveSize1); // for debug only
0291:                } else {
0292:                    archiveSize1 = 0;
0293:                    in.setReadLimit(-1); // remove limitation
0294:                }
0295:                archive_header_S.doneDisbursing();
0296:                archiveSize0 = in.getBytesServed();
0297:
0298:                int remainingHeaders = AH_LENGTH - AH_LENGTH_0 - AH_LENGTH_S;
0299:                if (!haveFiles)
0300:                    remainingHeaders -= AH_FILE_HEADER_LEN - AH_LENGTH_S;
0301:                if (!haveSpecial)
0302:                    remainingHeaders -= AH_SPECIAL_FORMAT_LEN;
0303:                if (!haveNumbers)
0304:                    remainingHeaders -= AH_CP_NUMBER_LEN;
0305:                assert (remainingHeaders >= AH_LENGTH_MIN - AH_LENGTH_0);
0306:                archive_header_1.expectLength(remainingHeaders);
0307:                archive_header_1.readFrom(in);
0308:
0309:                if (haveFiles) {
0310:                    archiveNextCount = archive_header_1.getInt();
0311:                    pkg.default_modtime = archive_header_1.getInt();
0312:                    numFiles = archive_header_1.getInt();
0313:                } else {
0314:                    archiveNextCount = 0;
0315:                    numFiles = 0;
0316:                }
0317:
0318:                if (haveSpecial) {
0319:                    band_headers.expectLength(archive_header_1.getInt());
0320:                    numAttrDefs = archive_header_1.getInt();
0321:                } else {
0322:                    band_headers.expectLength(0);
0323:                    numAttrDefs = 0;
0324:                }
0325:
0326:                readConstantPoolCounts(haveNumbers);
0327:
0328:                numInnerClasses = archive_header_1.getInt();
0329:
0330:                pkg.default_class_minver = (short) archive_header_1.getInt();
0331:                pkg.default_class_majver = (short) archive_header_1.getInt();
0332:                numClasses = archive_header_1.getInt();
0333:
0334:                archive_header_1.doneDisbursing();
0335:
0336:                // set some derived archive bits
0337:                if (testBit(archiveOptions, AO_DEFLATE_HINT)) {
0338:                    pkg.default_options |= FO_DEFLATE_HINT;
0339:                }
0340:            }
0341:
0342:            void readBandHeaders() throws IOException {
0343:                band_headers.readFrom(in);
0344:                bandHeaderBytePos = 1; // Leave room to pushback the initial XB byte.
0345:                bandHeaderBytes = new byte[bandHeaderBytePos
0346:                        + band_headers.length()];
0347:                for (int i = bandHeaderBytePos; i < bandHeaderBytes.length; i++) {
0348:                    bandHeaderBytes[i] = (byte) band_headers.getByte();
0349:                }
0350:                band_headers.doneDisbursing();
0351:            }
0352:
0353:            void readConstantPoolCounts(boolean haveNumbers) throws IOException {
0354:                // size the constant pools:
0355:                for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) {
0356:                    //  cp_counts:
0357:                    //        #cp_Utf8_count :UNSIGNED5[1]
0358:                    //        (cp_number_counts) ** (#have_cp_numbers)
0359:                    //        #cp_String_count :UNSIGNED5[1]
0360:                    //        #cp_Class_count :UNSIGNED5[1]
0361:                    //        #cp_Signature_count :UNSIGNED5[1]
0362:                    //        #cp_Descr_count :UNSIGNED5[1]
0363:                    //        #cp_Field_count :UNSIGNED5[1]
0364:                    //        #cp_Method_count :UNSIGNED5[1]
0365:                    //        #cp_Imethod_count :UNSIGNED5[1]
0366:                    //
0367:                    //  cp_number_counts:
0368:                    //        #cp_Int_count :UNSIGNED5[1]
0369:                    //        #cp_Float_count :UNSIGNED5[1]
0370:                    //        #cp_Long_count :UNSIGNED5[1]
0371:                    //        #cp_Double_count :UNSIGNED5[1]
0372:                    //
0373:                    byte tag = ConstantPool.TAGS_IN_ORDER[k];
0374:                    if (!haveNumbers) {
0375:                        // These four counts are optional.
0376:                        switch (tag) {
0377:                        case CONSTANT_Integer:
0378:                        case CONSTANT_Float:
0379:                        case CONSTANT_Long:
0380:                        case CONSTANT_Double:
0381:                            continue;
0382:                        }
0383:                    }
0384:                    tagCount[tag] = archive_header_1.getInt();
0385:                }
0386:            }
0387:
0388:            protected Index getCPIndex(byte tag) {
0389:                return pkg.cp.getIndexByTag(tag);
0390:            }
0391:
0392:            Index initCPIndex(byte tag, Entry[] cpMap) {
0393:                if (verbose > 3) {
0394:                    for (int i = 0; i < cpMap.length; i++) {
0395:                        Utils.log.fine("cp.add " + cpMap[i]);
0396:                    }
0397:                }
0398:                Index index = ConstantPool.makeIndex(ConstantPool.tagName(tag),
0399:                        cpMap);
0400:                if (verbose > 1)
0401:                    Utils.log.fine("Read " + index);
0402:                pkg.cp.initIndexByTag(tag, index);
0403:                return index;
0404:            }
0405:
0406:            void readConstantPool() throws IOException {
0407:                //  cp_bands:
0408:                //        cp_Utf8
0409:                //        *cp_Int :UDELTA5
0410:                //        *cp_Float :UDELTA5
0411:                //        cp_Long
0412:                //        cp_Double
0413:                //        *cp_String :UDELTA5  (cp_Utf8)
0414:                //        *cp_Class :UDELTA5  (cp_Utf8)
0415:                //        cp_Signature
0416:                //        cp_Descr
0417:                //        cp_Field
0418:                //        cp_Method
0419:                //        cp_Imethod
0420:
0421:                if (verbose > 0)
0422:                    Utils.log.info("Reading CP");
0423:
0424:                for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) {
0425:                    byte tag = ConstantPool.TAGS_IN_ORDER[k];
0426:                    int len = tagCount[tag];
0427:
0428:                    Entry[] cpMap = new Entry[len];
0429:                    if (verbose > 0)
0430:                        Utils.log.info("Reading " + cpMap.length + " "
0431:                                + ConstantPool.tagName(tag) + " entries...");
0432:
0433:                    switch (tag) {
0434:                    case CONSTANT_Utf8:
0435:                        readUtf8Bands(cpMap);
0436:                        break;
0437:                    case CONSTANT_Integer:
0438:                        cp_Int.expectLength(cpMap.length);
0439:                        cp_Int.readFrom(in);
0440:                        for (int i = 0; i < cpMap.length; i++) {
0441:                            int x = cp_Int.getInt(); // coding handles signs OK
0442:                            cpMap[i] = ConstantPool
0443:                                    .getLiteralEntry(new Integer(x));
0444:                        }
0445:                        cp_Int.doneDisbursing();
0446:                        break;
0447:                    case CONSTANT_Float:
0448:                        cp_Float.expectLength(cpMap.length);
0449:                        cp_Float.readFrom(in);
0450:                        for (int i = 0; i < cpMap.length; i++) {
0451:                            int x = cp_Float.getInt();
0452:                            float fx = Float.intBitsToFloat(x);
0453:                            cpMap[i] = ConstantPool.getLiteralEntry(new Float(
0454:                                    fx));
0455:                        }
0456:                        cp_Float.doneDisbursing();
0457:                        break;
0458:                    case CONSTANT_Long:
0459:                        //  cp_Long:
0460:                        //        *cp_Long_hi :UDELTA5
0461:                        //        *cp_Long_lo :DELTA5
0462:                        cp_Long_hi.expectLength(cpMap.length);
0463:                        cp_Long_hi.readFrom(in);
0464:                        cp_Long_lo.expectLength(cpMap.length);
0465:                        cp_Long_lo.readFrom(in);
0466:                        for (int i = 0; i < cpMap.length; i++) {
0467:                            long hi = cp_Long_hi.getInt();
0468:                            long lo = cp_Long_lo.getInt();
0469:                            long x = (hi << 32) + ((lo << 32) >>> 32);
0470:                            cpMap[i] = ConstantPool
0471:                                    .getLiteralEntry(new Long(x));
0472:                        }
0473:                        cp_Long_hi.doneDisbursing();
0474:                        cp_Long_lo.doneDisbursing();
0475:                        break;
0476:                    case CONSTANT_Double:
0477:                        //  cp_Double:
0478:                        //        *cp_Double_hi :UDELTA5
0479:                        //        *cp_Double_lo :DELTA5
0480:                        cp_Double_hi.expectLength(cpMap.length);
0481:                        cp_Double_hi.readFrom(in);
0482:                        cp_Double_lo.expectLength(cpMap.length);
0483:                        cp_Double_lo.readFrom(in);
0484:                        for (int i = 0; i < cpMap.length; i++) {
0485:                            long hi = cp_Double_hi.getInt();
0486:                            long lo = cp_Double_lo.getInt();
0487:                            long x = (hi << 32) + ((lo << 32) >>> 32);
0488:                            double dx = Double.longBitsToDouble(x);
0489:                            cpMap[i] = ConstantPool.getLiteralEntry(new Double(
0490:                                    dx));
0491:                        }
0492:                        cp_Double_hi.doneDisbursing();
0493:                        cp_Double_lo.doneDisbursing();
0494:                        break;
0495:                    case CONSTANT_String:
0496:                        cp_String.expectLength(cpMap.length);
0497:                        cp_String.readFrom(in);
0498:                        cp_String.setIndex(getCPIndex(CONSTANT_Utf8));
0499:                        for (int i = 0; i < cpMap.length; i++) {
0500:                            cpMap[i] = ConstantPool.getLiteralEntry(cp_String
0501:                                    .getRef().stringValue());
0502:                        }
0503:                        cp_String.doneDisbursing();
0504:                        break;
0505:                    case CONSTANT_Class:
0506:                        cp_Class.expectLength(cpMap.length);
0507:                        cp_Class.readFrom(in);
0508:                        cp_Class.setIndex(getCPIndex(CONSTANT_Utf8));
0509:                        for (int i = 0; i < cpMap.length; i++) {
0510:                            cpMap[i] = ConstantPool.getClassEntry(cp_Class
0511:                                    .getRef().stringValue());
0512:                        }
0513:                        cp_Class.doneDisbursing();
0514:                        break;
0515:                    case CONSTANT_Signature:
0516:                        readSignatureBands(cpMap);
0517:                        break;
0518:                    case CONSTANT_NameandType:
0519:                        //  cp_Descr:
0520:                        //        *cp_Descr_type :DELTA5  (cp_Signature)
0521:                        //        *cp_Descr_name :UDELTA5  (cp_Utf8)
0522:                        cp_Descr_name.expectLength(cpMap.length);
0523:                        cp_Descr_name.readFrom(in);
0524:                        cp_Descr_name.setIndex(getCPIndex(CONSTANT_Utf8));
0525:                        cp_Descr_type.expectLength(cpMap.length);
0526:                        cp_Descr_type.readFrom(in);
0527:                        cp_Descr_type.setIndex(getCPIndex(CONSTANT_Signature));
0528:                        for (int i = 0; i < cpMap.length; i++) {
0529:                            Entry ref = cp_Descr_name.getRef();
0530:                            Entry ref2 = cp_Descr_type.getRef();
0531:                            cpMap[i] = ConstantPool.getDescriptorEntry(
0532:                                    (Utf8Entry) ref, (SignatureEntry) ref2);
0533:                        }
0534:                        cp_Descr_name.doneDisbursing();
0535:                        cp_Descr_type.doneDisbursing();
0536:                        break;
0537:                    case CONSTANT_Fieldref:
0538:                        readMemberRefs(tag, cpMap, cp_Field_class,
0539:                                cp_Field_desc);
0540:                        break;
0541:                    case CONSTANT_Methodref:
0542:                        readMemberRefs(tag, cpMap, cp_Method_class,
0543:                                cp_Method_desc);
0544:                        break;
0545:                    case CONSTANT_InterfaceMethodref:
0546:                        readMemberRefs(tag, cpMap, cp_Imethod_class,
0547:                                cp_Imethod_desc);
0548:                        break;
0549:                    default:
0550:                        assert (false);
0551:                    }
0552:
0553:                    Index index = initCPIndex(tag, cpMap);
0554:
0555:                    if (optDumpBands) {
0556:                        PrintStream ps = new PrintStream(getDumpStream(index,
0557:                                ".idx"));
0558:                        printArrayTo(ps, index.cpMap, 0, index.cpMap.length);
0559:                        ps.close();
0560:                    }
0561:                }
0562:
0563:                cp_bands.doneDisbursing();
0564:
0565:                setBandIndexes();
0566:            }
0567:
0568:            void readUtf8Bands(Entry[] cpMap) throws IOException {
0569:                //  cp_Utf8:                           
0570:                //        *cp_Utf8_prefix :DELTA5
0571:                //        *cp_Utf8_suffix :UNSIGNED5
0572:                //        *cp_Utf8_chars :CHAR3
0573:                //        *cp_Utf8_big_suffix :DELTA5
0574:                //        (*cp_Utf8_big_chars :DELTA5)
0575:                //          ** length(cp_Utf8_big_suffix)
0576:                int len = cpMap.length;
0577:                if (len == 0)
0578:                    return; // nothing to read
0579:
0580:                // Bands have implicit leading zeroes, for the empty string:
0581:                final int SUFFIX_SKIP_1 = 1;
0582:                final int PREFIX_SKIP_2 = 2;
0583:
0584:                // First band:  Read lengths of shared prefixes.
0585:                cp_Utf8_prefix.expectLength(Math.max(0, len - PREFIX_SKIP_2));
0586:                cp_Utf8_prefix.readFrom(in);
0587:
0588:                // Second band:  Read lengths of unshared suffixes:
0589:                cp_Utf8_suffix.expectLength(Math.max(0, len - SUFFIX_SKIP_1));
0590:                cp_Utf8_suffix.readFrom(in);
0591:
0592:                char[][] suffixChars = new char[len][];
0593:                int bigSuffixCount = 0;
0594:
0595:                // Third band:  Read the char values in the unshared suffixes:
0596:                cp_Utf8_chars.expectLength(cp_Utf8_suffix.getIntTotal());
0597:                cp_Utf8_chars.readFrom(in);
0598:                for (int i = 0; i < len; i++) {
0599:                    int suffix = (i < SUFFIX_SKIP_1) ? 0 : cp_Utf8_suffix
0600:                            .getInt();
0601:                    if (suffix == 0 && i >= SUFFIX_SKIP_1) {
0602:                        // chars are packed in cp_Utf8_big_chars
0603:                        bigSuffixCount += 1;
0604:                        continue;
0605:                    }
0606:                    suffixChars[i] = new char[suffix];
0607:                    for (int j = 0; j < suffix; j++) {
0608:                        int ch = cp_Utf8_chars.getInt();
0609:                        assert (ch == (char) ch);
0610:                        suffixChars[i][j] = (char) ch;
0611:                    }
0612:                }
0613:                cp_Utf8_chars.doneDisbursing();
0614:
0615:                // Fourth band:  Go back and size the specially packed strings.
0616:                int maxChars = 0;
0617:                cp_Utf8_big_suffix.expectLength(bigSuffixCount);
0618:                cp_Utf8_big_suffix.readFrom(in);
0619:                cp_Utf8_suffix.resetForSecondPass();
0620:                for (int i = 0; i < len; i++) {
0621:                    int suffix = (i < SUFFIX_SKIP_1) ? 0 : cp_Utf8_suffix
0622:                            .getInt();
0623:                    int prefix = (i < PREFIX_SKIP_2) ? 0 : cp_Utf8_prefix
0624:                            .getInt();
0625:                    if (suffix == 0 && i >= SUFFIX_SKIP_1) {
0626:                        assert (suffixChars[i] == null);
0627:                        suffix = cp_Utf8_big_suffix.getInt();
0628:                    } else {
0629:                        assert (suffixChars[i] != null);
0630:                    }
0631:                    if (maxChars < prefix + suffix)
0632:                        maxChars = prefix + suffix;
0633:                }
0634:                char[] buf = new char[maxChars];
0635:
0636:                // Fifth band(s):  Get the specially packed characters.
0637:                cp_Utf8_suffix.resetForSecondPass();
0638:                cp_Utf8_big_suffix.resetForSecondPass();
0639:                for (int i = 0; i < len; i++) {
0640:                    if (i < SUFFIX_SKIP_1)
0641:                        continue;
0642:                    int suffix = cp_Utf8_suffix.getInt();
0643:                    if (suffix != 0)
0644:                        continue; // already input
0645:                    suffix = cp_Utf8_big_suffix.getInt();
0646:                    suffixChars[i] = new char[suffix];
0647:                    if (suffix == 0) {
0648:                        // Do not bother to add an empty "(Utf8_big_0)" band.
0649:                        continue;
0650:                    }
0651:                    IntBand packed = cp_Utf8_big_chars.newIntBand("(Utf8_big_"
0652:                            + i + ")");
0653:                    packed.expectLength(suffix);
0654:                    packed.readFrom(in);
0655:                    for (int j = 0; j < suffix; j++) {
0656:                        int ch = packed.getInt();
0657:                        assert (ch == (char) ch);
0658:                        suffixChars[i][j] = (char) ch;
0659:                    }
0660:                    packed.doneDisbursing();
0661:                }
0662:                cp_Utf8_big_chars.doneDisbursing();
0663:
0664:                // Finally, sew together all the prefixes and suffixes.
0665:                cp_Utf8_prefix.resetForSecondPass();
0666:                cp_Utf8_suffix.resetForSecondPass();
0667:                cp_Utf8_big_suffix.resetForSecondPass();
0668:                for (int i = 0; i < len; i++) {
0669:                    int prefix = (i < PREFIX_SKIP_2) ? 0 : cp_Utf8_prefix
0670:                            .getInt();
0671:                    int suffix = (i < SUFFIX_SKIP_1) ? 0 : cp_Utf8_suffix
0672:                            .getInt();
0673:                    if (suffix == 0 && i >= SUFFIX_SKIP_1)
0674:                        suffix = cp_Utf8_big_suffix.getInt();
0675:
0676:                    // by induction, the buffer is already filled with the prefix
0677:                    System.arraycopy(suffixChars[i], 0, buf, prefix, suffix);
0678:
0679:                    cpMap[i] = ConstantPool.getUtf8Entry(new String(buf, 0,
0680:                            prefix + suffix));
0681:                }
0682:
0683:                cp_Utf8_prefix.doneDisbursing();
0684:                cp_Utf8_suffix.doneDisbursing();
0685:                cp_Utf8_big_suffix.doneDisbursing();
0686:            }
0687:
0688:            HashMap utf8Signatures; // Utf8Entry->SignatureEntry
0689:
0690:            void readSignatureBands(Entry[] cpMap) throws IOException {
0691:                //  cp_Signature:
0692:                //        *cp_Signature_form :DELTA5  (cp_Utf8)
0693:                //        *cp_Signature_classes :UDELTA5  (cp_Class)
0694:                cp_Signature_form.expectLength(cpMap.length);
0695:                cp_Signature_form.readFrom(in);
0696:                cp_Signature_form.setIndex(getCPIndex(CONSTANT_Utf8));
0697:                int[] numSigClasses = new int[cpMap.length];
0698:                for (int i = 0; i < cpMap.length; i++) {
0699:                    Utf8Entry formRef = (Utf8Entry) cp_Signature_form.getRef();
0700:                    numSigClasses[i] = ConstantPool.countClassParts(formRef);
0701:                }
0702:                cp_Signature_form.resetForSecondPass();
0703:                cp_Signature_classes.expectLength(getIntTotal(numSigClasses));
0704:                cp_Signature_classes.readFrom(in);
0705:                cp_Signature_classes.setIndex(getCPIndex(CONSTANT_Class));
0706:                utf8Signatures = new HashMap();
0707:                for (int i = 0; i < cpMap.length; i++) {
0708:                    Utf8Entry formRef = (Utf8Entry) cp_Signature_form.getRef();
0709:                    ClassEntry[] classRefs = new ClassEntry[numSigClasses[i]];
0710:                    for (int j = 0; j < classRefs.length; j++) {
0711:                        classRefs[j] = (ClassEntry) cp_Signature_classes
0712:                                .getRef();
0713:                    }
0714:                    SignatureEntry se = ConstantPool.getSignatureEntry(formRef,
0715:                            classRefs);
0716:                    cpMap[i] = se;
0717:                    utf8Signatures.put(se.asUtf8Entry(), se);
0718:                }
0719:                cp_Signature_form.doneDisbursing();
0720:                cp_Signature_classes.doneDisbursing();
0721:            }
0722:
0723:            void readMemberRefs(byte tag, Entry[] cpMap, CPRefBand cp_class,
0724:                    CPRefBand cp_desc) throws IOException {
0725:                //  cp_Field:
0726:                //        *cp_Field_class :DELTA5  (cp_Class)
0727:                //        *cp_Field_desc :UDELTA5  (cp_Descr)
0728:                //  cp_Method:
0729:                //        *cp_Method_class :DELTA5  (cp_Class)
0730:                //        *cp_Method_desc :UDELTA5  (cp_Descr)
0731:                //  cp_Imethod:
0732:                //        *cp_Imethod_class :DELTA5  (cp_Class)
0733:                //        *cp_Imethod_desc :UDELTA5  (cp_Descr)
0734:                cp_class.expectLength(cpMap.length);
0735:                cp_class.readFrom(in);
0736:                cp_class.setIndex(getCPIndex(CONSTANT_Class));
0737:                cp_desc.expectLength(cpMap.length);
0738:                cp_desc.readFrom(in);
0739:                cp_desc.setIndex(getCPIndex(CONSTANT_NameandType));
0740:                for (int i = 0; i < cpMap.length; i++) {
0741:                    ClassEntry mclass = (ClassEntry) cp_class.getRef();
0742:                    DescriptorEntry mdescr = (DescriptorEntry) cp_desc.getRef();
0743:                    cpMap[i] = ConstantPool.getMemberEntry(tag, mclass, mdescr);
0744:                }
0745:                cp_class.doneDisbursing();
0746:                cp_desc.doneDisbursing();
0747:            }
0748:
0749:            void readFiles() throws IOException {
0750:                //  file_bands:
0751:                //        *file_name :UNSIGNED5  (cp_Utf8)
0752:                //        *file_size_hi :UNSIGNED5
0753:                //        *file_size_lo :UNSIGNED5
0754:                //        *file_modtime :DELTA5
0755:                //        *file_options :UNSIGNED5
0756:                //        *file_bits :BYTE1
0757:                if (verbose > 0)
0758:                    Utils.log.info("  ...building " + numFiles + " files...");
0759:                file_name.expectLength(numFiles);
0760:                file_size_lo.expectLength(numFiles);
0761:                int options = archiveOptions;
0762:                boolean haveSizeHi = testBit(options, AO_HAVE_FILE_SIZE_HI);
0763:                boolean haveModtime = testBit(options, AO_HAVE_FILE_MODTIME);
0764:                boolean haveOptions = testBit(options, AO_HAVE_FILE_OPTIONS);
0765:                if (haveSizeHi)
0766:                    file_size_hi.expectLength(numFiles);
0767:                if (haveModtime)
0768:                    file_modtime.expectLength(numFiles);
0769:                if (haveOptions)
0770:                    file_options.expectLength(numFiles);
0771:
0772:                file_name.readFrom(in);
0773:                file_size_hi.readFrom(in);
0774:                file_size_lo.readFrom(in);
0775:                file_modtime.readFrom(in);
0776:                file_options.readFrom(in);
0777:                file_bits.setInputStreamFrom(in);
0778:
0779:                Iterator nextClass = pkg.getClasses().iterator();
0780:
0781:                // Compute file lengths before reading any file bits.
0782:                long totalFileLength = 0;
0783:                long[] fileLengths = new long[numFiles];
0784:                for (int i = 0; i < numFiles; i++) {
0785:                    long size = ((long) file_size_lo.getInt() << 32) >>> 32;
0786:                    if (haveSizeHi)
0787:                        size += (long) file_size_hi.getInt() << 32;
0788:                    fileLengths[i] = size;
0789:                    totalFileLength += size;
0790:                }
0791:                assert (in.getReadLimit() == -1 || in.getReadLimit() == totalFileLength);
0792:
0793:                byte[] buf = new byte[1 << 16];
0794:                for (int i = 0; i < numFiles; i++) {
0795:                    // %%% Use a big temp file for file bits?
0796:                    Utf8Entry name = (Utf8Entry) file_name.getRef();
0797:                    long size = fileLengths[i];
0798:                    File file = pkg.new File(name);
0799:                    file.modtime = pkg.default_modtime;
0800:                    file.options = pkg.default_options;
0801:                    if (haveModtime)
0802:                        file.modtime += file_modtime.getInt();
0803:                    if (haveOptions)
0804:                        file.options |= file_options.getInt();
0805:                    if (verbose > 1)
0806:                        Utils.log.fine("Reading " + size + " bytes of "
0807:                                + name.stringValue());
0808:                    long toRead = size;
0809:                    while (toRead > 0) {
0810:                        int nr = buf.length;
0811:                        if (nr > toRead)
0812:                            nr = (int) toRead;
0813:                        nr = file_bits.getInputStream().read(buf, 0, nr);
0814:                        if (nr < 0)
0815:                            throw new EOFException();
0816:                        file.addBytes(buf, 0, nr);
0817:                        toRead -= nr;
0818:                    }
0819:                    pkg.addFile(file);
0820:                    if (file.isClassStub()) {
0821:                        assert (file.getFileLength() == 0);
0822:                        Class cls = (Class) nextClass.next();
0823:                        cls.initFile(file);
0824:                    }
0825:                }
0826:
0827:                // Do the rest of the classes.
0828:                while (nextClass.hasNext()) {
0829:                    Class cls = (Class) nextClass.next();
0830:                    cls.initFile(null); // implicitly initialize to a trivial one
0831:                    cls.file.modtime = pkg.default_modtime;
0832:                }
0833:
0834:                file_name.doneDisbursing();
0835:                file_size_hi.doneDisbursing();
0836:                file_size_lo.doneDisbursing();
0837:                file_modtime.doneDisbursing();
0838:                file_options.doneDisbursing();
0839:                file_bits.doneDisbursing();
0840:                file_bands.doneDisbursing();
0841:
0842:                if (archiveSize1 != 0 && !in.atLimit()) {
0843:                    throw new RuntimeException("Predicted archive_size "
0844:                            + archiveSize1 + " != "
0845:                            + (in.getBytesServed() - archiveSize0));
0846:                }
0847:            }
0848:
0849:            void readAttrDefs() throws IOException {
0850:                //  attr_definition_bands:
0851:                //        *attr_definition_headers :BYTE1
0852:                //        *attr_definition_name :UNSIGNED5  (cp_Utf8)
0853:                //        *attr_definition_layout :UNSIGNED5  (cp_Utf8)
0854:                attr_definition_headers.expectLength(numAttrDefs);
0855:                attr_definition_name.expectLength(numAttrDefs);
0856:                attr_definition_layout.expectLength(numAttrDefs);
0857:                attr_definition_headers.readFrom(in);
0858:                attr_definition_name.readFrom(in);
0859:                attr_definition_layout.readFrom(in);
0860:                PrintStream dump = !optDumpBands ? null : new PrintStream(
0861:                        getDumpStream(attr_definition_headers, ".def"));
0862:                for (int i = 0; i < numAttrDefs; i++) {
0863:                    int header = attr_definition_headers.getByte();
0864:                    Utf8Entry name = (Utf8Entry) attr_definition_name.getRef();
0865:                    Utf8Entry layout = (Utf8Entry) attr_definition_layout
0866:                            .getRef();
0867:                    int ctype = (header & ADH_CONTEXT_MASK);
0868:                    int index = (header >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB;
0869:                    Attribute.Layout def = new Attribute.Layout(ctype, name
0870:                            .stringValue(), layout.stringValue());
0871:                    // Check layout string for Java 6 extensions.
0872:                    String pvLayout = def
0873:                            .layoutForPackageMajver(getPackageMajver());
0874:                    if (!pvLayout.equals(def.layout())) {
0875:                        throw new IOException(
0876:                                "Bad attribute layout in version 150 archive: "
0877:                                        + def.layout());
0878:                    }
0879:                    this .setAttributeLayoutIndex(def, index);
0880:                    if (dump != null)
0881:                        dump.println(index + " " + def);
0882:                }
0883:                if (dump != null)
0884:                    dump.close();
0885:                attr_definition_headers.doneDisbursing();
0886:                attr_definition_name.doneDisbursing();
0887:                attr_definition_layout.doneDisbursing();
0888:                // Attribute layouts define bands, one per layout element.
0889:                // Create them now, all at once.
0890:                makeNewAttributeBands();
0891:                attr_definition_bands.doneDisbursing();
0892:            }
0893:
0894:            void readInnerClasses() throws IOException {
0895:                //  ic_bands:
0896:                //        *ic_this_class :UDELTA5  (cp_Class)
0897:                //        *ic_flags :UNSIGNED5
0898:                //        *ic_outer_class :DELTA5  (null or cp_Class)
0899:                //        *ic_name :DELTA5  (null or cp_Utf8)
0900:                ic_this _class.expectLength(numInnerClasses);
0901:                ic_this _class.readFrom(in);
0902:                ic_flags.expectLength(numInnerClasses);
0903:                ic_flags.readFrom(in);
0904:                int longICCount = 0;
0905:                for (int i = 0; i < numInnerClasses; i++) {
0906:                    int flags = ic_flags.getInt();
0907:                    boolean longForm = (flags & ACC_IC_LONG_FORM) != 0;
0908:                    if (longForm) {
0909:                        longICCount += 1;
0910:                    }
0911:                }
0912:                ic_outer_class.expectLength(longICCount);
0913:                ic_outer_class.readFrom(in);
0914:                ic_name.expectLength(longICCount);
0915:                ic_name.readFrom(in);
0916:                ic_flags.resetForSecondPass();
0917:                ArrayList icList = new ArrayList(numInnerClasses);
0918:                for (int i = 0; i < numInnerClasses; i++) {
0919:                    int flags = ic_flags.getInt();
0920:                    boolean longForm = (flags & ACC_IC_LONG_FORM) != 0;
0921:                    flags &= ~ACC_IC_LONG_FORM;
0922:                    ClassEntry this Class = (ClassEntry) ic_this _class.getRef();
0923:                    ClassEntry outerClass;
0924:                    Utf8Entry this Name;
0925:                    if (longForm) {
0926:                        outerClass = (ClassEntry) ic_outer_class.getRef();
0927:                        this Name = (Utf8Entry) ic_name.getRef();
0928:                    } else {
0929:                        String n = this Class.stringValue();
0930:                        String[] parse = pkg.parseInnerClassName(n);
0931:                        assert (parse != null);
0932:                        String pkgOuter = parse[0];
0933:                        //String number = parse[1];
0934:                        String name = parse[2];
0935:                        if (pkgOuter == null)
0936:                            outerClass = null;
0937:                        else
0938:                            outerClass = ConstantPool.getClassEntry(pkgOuter);
0939:                        if (name == null)
0940:                            this Name = null;
0941:                        else
0942:                            this Name = ConstantPool.getUtf8Entry(name);
0943:                    }
0944:                    InnerClass ic = new InnerClass(this Class, outerClass,
0945:                            this Name, flags);
0946:                    assert (longForm || ic.predictable);
0947:                    icList.add(ic);
0948:                }
0949:                ic_flags.doneDisbursing();
0950:                ic_this _class.doneDisbursing();
0951:                ic_outer_class.doneDisbursing();
0952:                ic_name.doneDisbursing();
0953:                pkg.setAllInnerClasses(icList);
0954:                ic_bands.doneDisbursing();
0955:            }
0956:
0957:            void readLocalInnerClasses(Class cls) throws IOException {
0958:                int nc = class_InnerClasses_N.getInt();
0959:                ArrayList localICs = new ArrayList(nc);
0960:                for (int i = 0; i < nc; i++) {
0961:                    ClassEntry this Class = (ClassEntry) class_InnerClasses_RC
0962:                            .getRef();
0963:                    int flags = class_InnerClasses_F.getInt();
0964:                    if (flags == 0) {
0965:                        // A zero flag means copy a global IC here.
0966:                        InnerClass ic = pkg.getGlobalInnerClass(this Class);
0967:                        assert (ic != null); // must be a valid global IC reference
0968:                        localICs.add(ic);
0969:                    } else {
0970:                        if (flags == ACC_IC_LONG_FORM)
0971:                            flags = 0; // clear the marker bit
0972:                        ClassEntry outer = (ClassEntry) class_InnerClasses_outer_RCN
0973:                                .getRef();
0974:                        Utf8Entry name = (Utf8Entry) class_InnerClasses_name_RUN
0975:                                .getRef();
0976:                        localICs.add(new InnerClass(this Class, outer, name,
0977:                                flags));
0978:                    }
0979:                }
0980:                cls.setInnerClasses(localICs);
0981:                // cls.expandLocalICs may add more tuples to ics also,
0982:                // or may even delete tuples.
0983:                // We cannot do that now, because we do not know the
0984:                // full contents of the local constant pool yet.
0985:            }
0986:
0987:            static final int NO_FLAGS_YET = 0; // placeholder for later flag read-in
0988:
0989:            Class[] readClasses() throws IOException {
0990:                //  class_bands:
0991:                //        *class_this :DELTA5  (cp_Class)
0992:                //        *class_super :DELTA5  (cp_Class)
0993:                //        *class_interface_count :DELTA5
0994:                //        *class_interface :DELTA5  (cp_Class)
0995:                //        ...(member bands)...
0996:                //        class_attr_bands
0997:                //        code_bands
0998:                Class[] classes = new Class[numClasses];
0999:                if (verbose > 0)
1000:                    Utils.log.info("  ...building " + classes.length
1001:                            + " classes...");
1002:
1003:                class_this .expectLength(numClasses);
1004:                class_super .expectLength(numClasses);
1005:                class_interface_count.expectLength(numClasses);
1006:
1007:                class_this .readFrom(in);
1008:                class_super .readFrom(in);
1009:                class_interface_count.readFrom(in);
1010:                class_interface.expectLength(class_interface_count
1011:                        .getIntTotal());
1012:                class_interface.readFrom(in);
1013:                for (int i = 0; i < classes.length; i++) {
1014:                    ClassEntry this Class = (ClassEntry) class_this .getRef();
1015:                    ClassEntry super Class = (ClassEntry) class_super .getRef();
1016:                    ClassEntry[] interfaces = new ClassEntry[class_interface_count
1017:                            .getInt()];
1018:                    for (int j = 0; j < interfaces.length; j++) {
1019:                        interfaces[j] = (ClassEntry) class_interface.getRef();
1020:                    }
1021:                    // Packer encoded rare case of null superClass as thisClass:
1022:                    if (super Class == this Class)
1023:                        super Class = null;
1024:                    Class cls = pkg.new Class(NO_FLAGS_YET, this Class,
1025:                            super Class, interfaces);
1026:                    classes[i] = cls;
1027:                }
1028:                class_this .doneDisbursing();
1029:                class_super .doneDisbursing();
1030:                class_interface_count.doneDisbursing();
1031:                class_interface.doneDisbursing();
1032:                readMembers(classes);
1033:                countAndReadAttrs(ATTR_CONTEXT_CLASS, Arrays.asList(classes));
1034:                pkg.trimToSize();
1035:                readCodeHeaders();
1036:                //code_bands.doneDisbursing(); // still need to read code attrs
1037:                //class_bands.doneDisbursing(); // still need to read code attrs
1038:                return classes;
1039:            }
1040:
1041:            private int getOutputIndex(Entry e) {
1042:                // Output CPs do not contain signatures.
1043:                assert (e.tag != CONSTANT_Signature);
1044:                int k = pkg.cp.untypedIndexOf(e);
1045:                // In the output ordering, input signatures can serve
1046:                // in place of Utf8s.
1047:                if (k >= 0)
1048:                    return k;
1049:                if (e.tag == CONSTANT_Utf8) {
1050:                    Entry se = (Entry) utf8Signatures.get(e);
1051:                    return pkg.cp.untypedIndexOf(se);
1052:                }
1053:                return -1;
1054:            }
1055:
1056:            Comparator entryOutputOrder = new Comparator() {
1057:                public int compare(Object o0, Object o1) {
1058:                    Entry e0 = (Entry) o0;
1059:                    Entry e1 = (Entry) o1;
1060:                    int k0 = getOutputIndex(e0);
1061:                    int k1 = getOutputIndex(e1);
1062:                    if (k0 >= 0 && k1 >= 0)
1063:                        // If both have keys, use the keys.
1064:                        return k0 - k1;
1065:                    if (k0 == k1)
1066:                        // If neither have keys, use their native tags & spellings.
1067:                        return e0.compareTo(e1);
1068:                    // Otherwise, the guy with the key comes first.
1069:                    return (k0 >= 0) ? 0 - 1 : 1 - 0;
1070:                }
1071:            };
1072:
1073:            void reconstructClass(Class cls) {
1074:                if (verbose > 1)
1075:                    Utils.log.fine("reconstruct " + cls);
1076:
1077:                // check for local .ClassFile.version
1078:                Attribute retroVersion = cls.getAttribute(attrClassFileVersion);
1079:                if (retroVersion != null) {
1080:                    cls.removeAttribute(retroVersion);
1081:                    short[] minmajver = parseClassFileVersionAttr(retroVersion);
1082:                    cls.minver = minmajver[0];
1083:                    cls.majver = minmajver[1];
1084:                } else {
1085:                    cls.minver = pkg.default_class_minver;
1086:                    cls.majver = pkg.default_class_majver;
1087:                }
1088:
1089:                // Replace null SourceFile by "obvious" string.
1090:                cls.expandSourceFile();
1091:
1092:                // record the local cp:
1093:                cls.setCPMap(reconstructLocalCPMap(cls));
1094:            }
1095:
1096:            Entry[] reconstructLocalCPMap(Class cls) {
1097:                HashSet ldcRefs = (HashSet) ldcRefMap.get(cls);
1098:                HashSet cpRefs = new HashSet();
1099:                HashSet sigSet = new HashSet();
1100:
1101:                // look for constant pool entries:
1102:                cls.visitRefs(VRM_CLASSIC, cpRefs);
1103:
1104:                // flesh out the local constant pool
1105:                ConstantPool.completeReferencesIn(cpRefs, true);
1106:
1107:                // Now that we know all our local class references,
1108:                // compute the InnerClasses attribute.
1109:                int changed = cls.expandLocalICs();
1110:
1111:                if (changed != 0) {
1112:                    if (changed > 0) {
1113:                        // Just visit the expanded InnerClasses attr.
1114:                        cls.visitInnerClassRefs(VRM_CLASSIC, cpRefs);
1115:                    } else {
1116:                        // Have to recompute from scratch, because of deletions.
1117:                        cpRefs.clear();
1118:                        cls.visitRefs(VRM_CLASSIC, cpRefs);
1119:                    }
1120:
1121:                    // flesh out the local constant pool, again
1122:                    ConstantPool.completeReferencesIn(cpRefs, true);
1123:                }
1124:
1125:                // construct a local constant pool
1126:                int numDoubles = 0;
1127:                for (Iterator i = cpRefs.iterator(); i.hasNext();) {
1128:                    Entry e = (Entry) i.next();
1129:                    if (e.isDoubleWord())
1130:                        numDoubles++;
1131:                    assert (e.tag != CONSTANT_Signature) : (e);
1132:                }
1133:                Entry[] cpMap = new Entry[1 + numDoubles + cpRefs.size()];
1134:                int fillp = 1;
1135:
1136:                // Add all ldc operands first.
1137:                if (ldcRefs != null) {
1138:                    assert (cpRefs.containsAll(ldcRefs));
1139:                    for (Iterator i = ldcRefs.iterator(); i.hasNext();) {
1140:                        Entry e = (Entry) i.next();
1141:                        cpMap[fillp++] = e;
1142:                    }
1143:                    assert (fillp == 1 + ldcRefs.size());
1144:                    cpRefs.removeAll(ldcRefs);
1145:                    ldcRefs = null; // done with it
1146:                }
1147:
1148:                // Next add all the two-byte references.
1149:                HashSet wideRefs = cpRefs;
1150:                cpRefs = null; // do not use!
1151:                int narrowLimit = fillp;
1152:                for (Iterator i = wideRefs.iterator(); i.hasNext();) {
1153:                    Entry e = (Entry) i.next();
1154:                    cpMap[fillp++] = e;
1155:                }
1156:                assert (fillp == narrowLimit + wideRefs.size());
1157:                Arrays.sort(cpMap, 1, narrowLimit, entryOutputOrder);
1158:                Arrays.sort(cpMap, narrowLimit, fillp, entryOutputOrder);
1159:
1160:                if (verbose > 3) {
1161:                    Utils.log.fine("CP of " + this  + " {");
1162:                    for (int i = 0; i < fillp; i++) {
1163:                        Entry e = cpMap[i];
1164:                        Utils.log.fine("  "
1165:                                + ((e == null) ? -1 : getOutputIndex(e))
1166:                                + " : " + e);
1167:                    }
1168:                    Utils.log.fine("}");
1169:                }
1170:
1171:                // Now repack backwards, introducing null elements.
1172:                int revp = cpMap.length;
1173:                for (int i = fillp; --i >= 1;) {
1174:                    Entry e = cpMap[i];
1175:                    if (e.isDoubleWord())
1176:                        cpMap[--revp] = null;
1177:                    cpMap[--revp] = e;
1178:                }
1179:                assert (revp == 1); // do not process the initial null
1180:
1181:                return cpMap;
1182:            }
1183:
1184:            void readMembers(Class[] classes) throws IOException {
1185:                //  class_bands:
1186:                //        ...
1187:                //        *class_field_count :DELTA5
1188:                //        *class_method_count :DELTA5
1189:                //
1190:                //        *field_descr :DELTA5  (cp_Descr)
1191:                //        field_attr_bands
1192:                //
1193:                //        *method_descr :MDELTA5  (cp_Descr)
1194:                //        method_attr_bands
1195:                //        ...
1196:                assert (classes.length == numClasses);
1197:                class_field_count.expectLength(numClasses);
1198:                class_method_count.expectLength(numClasses);
1199:                class_field_count.readFrom(in);
1200:                class_method_count.readFrom(in);
1201:
1202:                // Make a pre-pass over field and method counts to size the descrs:
1203:                int totalNF = class_field_count.getIntTotal();
1204:                int totalNM = class_method_count.getIntTotal();
1205:                field_descr.expectLength(totalNF);
1206:                method_descr.expectLength(totalNM);
1207:                if (verbose > 1)
1208:                    Utils.log.fine("expecting #fields=" + totalNF
1209:                            + " and #methods=" + totalNM + " in #classes="
1210:                            + numClasses);
1211:
1212:                ArrayList fields = new ArrayList(totalNF);
1213:                field_descr.readFrom(in);
1214:                for (int i = 0; i < classes.length; i++) {
1215:                    Class c = classes[i];
1216:                    int nf = class_field_count.getInt();
1217:                    for (int j = 0; j < nf; j++) {
1218:                        Class.Field f = c.new Field(NO_FLAGS_YET,
1219:                                (DescriptorEntry) field_descr.getRef());
1220:                        fields.add(f);
1221:                    }
1222:                }
1223:                class_field_count.doneDisbursing();
1224:                field_descr.doneDisbursing();
1225:                countAndReadAttrs(ATTR_CONTEXT_FIELD, fields);
1226:                fields = null; // release to GC
1227:
1228:                ArrayList methods = new ArrayList(totalNM);
1229:                method_descr.readFrom(in);
1230:                for (int i = 0; i < classes.length; i++) {
1231:                    Class c = classes[i];
1232:                    int nm = class_method_count.getInt();
1233:                    for (int j = 0; j < nm; j++) {
1234:                        Class.Method m = c.new Method(NO_FLAGS_YET,
1235:                                (DescriptorEntry) method_descr.getRef());
1236:                        methods.add(m);
1237:                    }
1238:                }
1239:                class_method_count.doneDisbursing();
1240:                method_descr.doneDisbursing();
1241:                countAndReadAttrs(ATTR_CONTEXT_METHOD, methods);
1242:
1243:                // Up to this point, Code attributes look like empty attributes.
1244:                // Now we start to special-case them.  The empty canonical Code
1245:                // attributes stay in the method attribute lists, however.
1246:                allCodes = buildCodeAttrs(methods);
1247:            }
1248:
1249:            Code[] allCodes;
1250:            List codesWithFlags;
1251:            HashMap ldcRefMap = new HashMap(); // HashMap<Class, HashSet<Entry>>
1252:
1253:            Code[] buildCodeAttrs(List methods) {
1254:                ArrayList codes = new ArrayList(methods.size());
1255:                for (Iterator i = methods.iterator(); i.hasNext();) {
1256:                    Class.Method m = (Class.Method) i.next();
1257:                    if (m.getAttribute(attrCodeEmpty) != null) {
1258:                        m.code = new Code(m);
1259:                        codes.add(m.code);
1260:                    }
1261:                }
1262:                Code[] a = new Code[codes.size()];
1263:                codes.toArray(a);
1264:                return a;
1265:            }
1266:
1267:            void readCodeHeaders() throws IOException {
1268:                //  code_bands:
1269:                //        *code_headers :BYTE1
1270:                //
1271:                //        *code_max_stack :UNSIGNED5
1272:                //        *code_max_na_locals :UNSIGNED5
1273:                //        *code_handler_count :UNSIGNED5
1274:                //        ...
1275:                //        code_attr_bands
1276:                boolean attrsOK = testBit(archiveOptions,
1277:                        AO_HAVE_ALL_CODE_FLAGS);
1278:                code_headers.expectLength(allCodes.length);
1279:                code_headers.readFrom(in);
1280:                ArrayList longCodes = new ArrayList(allCodes.length / 10);
1281:                for (int i = 0; i < allCodes.length; i++) {
1282:                    Code c = allCodes[i];
1283:                    int sc = code_headers.getByte();
1284:                    assert (sc == (sc & 0xFF));
1285:                    if (verbose > 2)
1286:                        Utils.log.fine("codeHeader " + c + " = " + sc);
1287:                    if (sc == LONG_CODE_HEADER) {
1288:                        // We will read ms/ml/nh/flags from bands shortly.
1289:                        longCodes.add(c);
1290:                        continue;
1291:                    }
1292:                    // Short code header is the usual case:
1293:                    c.setMaxStack(shortCodeHeader_max_stack(sc));
1294:                    c.setMaxNALocals(shortCodeHeader_max_na_locals(sc));
1295:                    c.setHandlerCount(shortCodeHeader_handler_count(sc));
1296:                    assert (shortCodeHeader(c) == sc);
1297:                }
1298:                code_headers.doneDisbursing();
1299:                code_max_stack.expectLength(longCodes.size());
1300:                code_max_na_locals.expectLength(longCodes.size());
1301:                code_handler_count.expectLength(longCodes.size());
1302:
1303:                // Do the long headers now.
1304:                code_max_stack.readFrom(in);
1305:                code_max_na_locals.readFrom(in);
1306:                code_handler_count.readFrom(in);
1307:                for (Iterator i = longCodes.iterator(); i.hasNext();) {
1308:                    Code c = (Code) i.next();
1309:                    c.setMaxStack(code_max_stack.getInt());
1310:                    c.setMaxNALocals(code_max_na_locals.getInt());
1311:                    c.setHandlerCount(code_handler_count.getInt());
1312:                }
1313:                code_max_stack.doneDisbursing();
1314:                code_max_na_locals.doneDisbursing();
1315:                code_handler_count.doneDisbursing();
1316:
1317:                readCodeHandlers();
1318:
1319:                if (attrsOK) {
1320:                    // Code attributes are common (debug info not stripped).
1321:                    codesWithFlags = Arrays.asList(allCodes);
1322:                } else {
1323:                    // Code attributes are very sparse (debug info is stripped).
1324:                    codesWithFlags = longCodes;
1325:                }
1326:                countAttrs(ATTR_CONTEXT_CODE, codesWithFlags);
1327:                // do readAttrs later, after BCs are scanned
1328:            }
1329:
1330:            void readCodeHandlers() throws IOException {
1331:                //  code_bands:
1332:                //        ...
1333:                //        *code_handler_start_P :BCI5
1334:                //        *code_handler_end_PO :BRANCH5
1335:                //        *code_handler_catch_PO :BRANCH5
1336:                //        *code_handler_class_RCN :UNSIGNED5  (null or cp_Class)
1337:                //        ...
1338:                int nh = 0;
1339:                for (int i = 0; i < allCodes.length; i++) {
1340:                    Code c = allCodes[i];
1341:                    nh += c.getHandlerCount();
1342:                }
1343:
1344:                ValueBand[] code_handler_bands = { code_handler_start_P,
1345:                        code_handler_end_PO, code_handler_catch_PO,
1346:                        code_handler_class_RCN };
1347:
1348:                for (int i = 0; i < code_handler_bands.length; i++) {
1349:                    code_handler_bands[i].expectLength(nh);
1350:                    code_handler_bands[i].readFrom(in);
1351:                }
1352:
1353:                for (int i = 0; i < allCodes.length; i++) {
1354:                    Code c = allCodes[i];
1355:                    for (int j = 0, jmax = c.getHandlerCount(); j < jmax; j++) {
1356:                        c.handler_class[j] = code_handler_class_RCN.getRef();
1357:                        // For now, just record the raw BCI codes.
1358:                        // We must wait until we have instruction boundaries.
1359:                        c.handler_start[j] = code_handler_start_P.getInt();
1360:                        c.handler_end[j] = code_handler_end_PO.getInt();
1361:                        c.handler_catch[j] = code_handler_catch_PO.getInt();
1362:                    }
1363:                }
1364:                for (int i = 0; i < code_handler_bands.length; i++) {
1365:                    code_handler_bands[i].doneDisbursing();
1366:                }
1367:            }
1368:
1369:            void fixupCodeHandlers() {
1370:                // Actually decode (renumber) the BCIs now.
1371:                for (int i = 0; i < allCodes.length; i++) {
1372:                    Code c = allCodes[i];
1373:                    for (int j = 0, jmax = c.getHandlerCount(); j < jmax; j++) {
1374:                        int sum = c.handler_start[j];
1375:                        c.handler_start[j] = c.decodeBCI(sum);
1376:                        sum += c.handler_end[j];
1377:                        c.handler_end[j] = c.decodeBCI(sum);
1378:                        sum += c.handler_catch[j];
1379:                        c.handler_catch[j] = c.decodeBCI(sum);
1380:                    }
1381:                }
1382:            }
1383:
1384:            // Generic routines for reading attributes of
1385:            // classes, fields, methods, and codes.
1386:            // The holders is a global list, already collected,
1387:            // of attribute "customers".
1388:            void countAndReadAttrs(int ctype, Collection holders)
1389:                    throws IOException {
1390:                //  class_attr_bands:
1391:                //        *class_flags :UNSIGNED5
1392:                //        *class_attr_count :UNSIGNED5
1393:                //        *class_attr_indexes :UNSIGNED5
1394:                //        *class_attr_calls :UNSIGNED5
1395:                //        *class_Signature_RS :UNSIGNED5 (cp_Signature)
1396:                //        class_metadata_bands
1397:                //        *class_SourceFile_RU :UNSIGNED5 (cp_Utf8)
1398:                //        *class_EnclosingMethod_RM :UNSIGNED5 (cp_Method)
1399:                //        ic_local_bands
1400:                //        *class_ClassFile_version_minor_H :UNSIGNED5
1401:                //        *class_ClassFile_version_major_H :UNSIGNED5
1402:                //
1403:                //  field_attr_bands:
1404:                //        *field_flags :UNSIGNED5
1405:                //        *field_attr_count :UNSIGNED5
1406:                //        *field_attr_indexes :UNSIGNED5
1407:                //        *field_attr_calls :UNSIGNED5
1408:                //        *field_Signature_RS :UNSIGNED5 (cp_Signature)
1409:                //        field_metadata_bands
1410:                //        *field_ConstantValue_KQ :UNSIGNED5 (cp_Int, etc.; see note)
1411:                //
1412:                //  method_attr_bands:
1413:                //        *method_flags :UNSIGNED5
1414:                //        *method_attr_count :UNSIGNED5
1415:                //        *method_attr_indexes :UNSIGNED5
1416:                //        *method_attr_calls :UNSIGNED5
1417:                //        *method_Signature_RS :UNSIGNED5 (cp_Signature)
1418:                //        method_metadata_bands
1419:                //        *method_Exceptions_N :UNSIGNED5
1420:                //        *method_Exceptions_RC :UNSIGNED5  (cp_Class)
1421:                //
1422:                //  code_attr_bands:
1423:                //        *code_flags :UNSIGNED5
1424:                //        *code_attr_count :UNSIGNED5
1425:                //        *code_attr_indexes :UNSIGNED5
1426:                //        *code_attr_calls :UNSIGNED5
1427:                //        *code_LineNumberTable_N :UNSIGNED5
1428:                //        *code_LineNumberTable_bci_P :BCI5
1429:                //        *code_LineNumberTable_line :UNSIGNED5
1430:                //        *code_LocalVariableTable_N :UNSIGNED5
1431:                //        *code_LocalVariableTable_bci_P :BCI5
1432:                //        *code_LocalVariableTable_span_O :BRANCH5
1433:                //        *code_LocalVariableTable_name_RU :UNSIGNED5 (cp_Utf8)
1434:                //        *code_LocalVariableTable_type_RS :UNSIGNED5 (cp_Signature)
1435:                //        *code_LocalVariableTable_slot :UNSIGNED5
1436:
1437:                countAttrs(ctype, holders);
1438:                readAttrs(ctype, holders);
1439:            }
1440:
1441:            // Read flags and count the attributes that are to be placed
1442:            // on the given holders.
1443:            void countAttrs(int ctype, Collection holders) throws IOException {
1444:                // Here, xxx stands for one of class, field, method, code.
1445:                MultiBand xxx_attr_bands = attrBands[ctype];
1446:                long flagMask = attrFlagMask[ctype];
1447:                if (verbose > 1) {
1448:                    Utils.log.fine("scanning flags and attrs for "
1449:                            + Attribute.contextName(ctype) + "["
1450:                            + holders.size() + "]");
1451:                }
1452:
1453:                // Fetch the attribute layout definitions which govern the bands
1454:                // we are about to read.
1455:                Attribute.Layout[] defs = new Attribute.Layout[attrDefs[ctype]
1456:                        .size()];
1457:                attrDefs[ctype].toArray(defs);
1458:                IntBand xxx_flags_hi = getAttrBand(xxx_attr_bands, AB_FLAGS_HI);
1459:                IntBand xxx_flags_lo = getAttrBand(xxx_attr_bands, AB_FLAGS_LO);
1460:                IntBand xxx_attr_count = getAttrBand(xxx_attr_bands,
1461:                        AB_ATTR_COUNT);
1462:                IntBand xxx_attr_indexes = getAttrBand(xxx_attr_bands,
1463:                        AB_ATTR_INDEXES);
1464:                IntBand xxx_attr_calls = getAttrBand(xxx_attr_bands,
1465:                        AB_ATTR_CALLS);
1466:
1467:                // Count up the number of holders which have overflow attrs.
1468:                int overflowMask = attrOverflowMask[ctype];
1469:                int overflowHolderCount = 0;
1470:                boolean haveLongFlags = haveFlagsHi(ctype);
1471:                xxx_flags_hi.expectLength(haveLongFlags ? holders.size() : 0);
1472:                xxx_flags_hi.readFrom(in);
1473:                xxx_flags_lo.expectLength(holders.size());
1474:                xxx_flags_lo.readFrom(in);
1475:                assert ((flagMask & overflowMask) == overflowMask);
1476:                for (Iterator i = holders.iterator(); i.hasNext();) {
1477:                    Attribute.Holder h = (Attribute.Holder) i.next();
1478:                    int flags = xxx_flags_lo.getInt();
1479:                    h.flags = flags;
1480:                    if ((flags & overflowMask) != 0)
1481:                        overflowHolderCount += 1;
1482:                }
1483:
1484:                // For each holder with overflow attrs, read a count.
1485:                xxx_attr_count.expectLength(overflowHolderCount);
1486:                xxx_attr_count.readFrom(in);
1487:                xxx_attr_indexes.expectLength(xxx_attr_count.getIntTotal());
1488:                xxx_attr_indexes.readFrom(in);
1489:
1490:                // Now it's time to check flag bits that indicate attributes.
1491:                // We accumulate (a) a list of attribute types for each holder
1492:                // (class/field/method/code), and also we accumulate (b) a total
1493:                // count for each attribute type.
1494:                int[] totalCounts = new int[defs.length];
1495:                for (Iterator i = holders.iterator(); i.hasNext();) {
1496:                    Attribute.Holder h = (Attribute.Holder) i.next();
1497:                    assert (h.attributes == null);
1498:                    // System.out.println("flags="+h.flags+" using fm="+flagMask);
1499:                    long attrBits = ((h.flags & flagMask) << 32) >>> 32;
1500:                    // Clean up the flags now.
1501:                    h.flags -= (int) attrBits; // strip attr bits
1502:                    assert (h.flags == (char) h.flags); // 16 bits only now
1503:                    assert ((ctype != ATTR_CONTEXT_CODE) || h.flags == 0);
1504:                    if (haveLongFlags)
1505:                        attrBits += (long) xxx_flags_hi.getInt() << 32;
1506:                    if (attrBits == 0)
1507:                        continue; // no attrs on this guy
1508:
1509:                    int noa = 0; // number of overflow attrs
1510:                    long overflowBit = (attrBits & overflowMask);
1511:                    assert (overflowBit >= 0);
1512:                    attrBits -= overflowBit;
1513:                    if (overflowBit != 0) {
1514:                        noa = xxx_attr_count.getInt();
1515:                    }
1516:
1517:                    int nfa = 0; // number of flag attrs
1518:                    long bits = attrBits;
1519:                    for (int ai = 0; bits != 0; ai++) {
1520:                        if ((bits & (1L << ai)) == 0)
1521:                            continue;
1522:                        bits -= (1L << ai);
1523:                        nfa += 1;
1524:                    }
1525:                    ArrayList ha = new ArrayList(nfa + noa);
1526:                    h.attributes = ha;
1527:                    bits = attrBits; // iterate again
1528:                    for (int ai = 0; bits != 0; ai++) {
1529:                        if ((bits & (1L << ai)) == 0)
1530:                            continue;
1531:                        bits -= (1L << ai);
1532:                        totalCounts[ai] += 1;
1533:                        // This definition index is live in this holder.
1534:                        if (defs[ai] == null)
1535:                            badAttrIndex(ai, ctype);
1536:                        Attribute canonical = defs[ai].canonicalInstance();
1537:                        ha.add(canonical);
1538:                        nfa -= 1;
1539:                    }
1540:                    assert (nfa == 0);
1541:                    for (; noa > 0; noa--) {
1542:                        int ai = xxx_attr_indexes.getInt();
1543:                        totalCounts[ai] += 1;
1544:                        // This definition index is live in this holder.
1545:                        if (defs[ai] == null)
1546:                            badAttrIndex(ai, ctype);
1547:                        Attribute canonical = defs[ai].canonicalInstance();
1548:                        ha.add(canonical);
1549:                    }
1550:                }
1551:
1552:                xxx_flags_hi.doneDisbursing();
1553:                xxx_flags_lo.doneDisbursing();
1554:                xxx_attr_count.doneDisbursing();
1555:                xxx_attr_indexes.doneDisbursing();
1556:
1557:                // Now each holder has a list of canonical attribute instances.
1558:                // For layouts with no elements, we are done.  However, for
1559:                // layouts with bands, we must replace each canonical (empty)
1560:                // instance with a value-bearing one, initialized from the
1561:                // appropriate bands.
1562:
1563:                // Make a small pass to detect and read backward call counts.
1564:                int callCounts = 0;
1565:                for (boolean predef = true;; predef = false) {
1566:                    for (int ai = 0; ai < defs.length; ai++) {
1567:                        Attribute.Layout def = defs[ai];
1568:                        if (def == null)
1569:                            continue; // unused index
1570:                        if (predef != isPredefinedAttr(ctype, ai))
1571:                            continue; // wrong pass
1572:                        int totalCount = totalCounts[ai];
1573:                        if (totalCount == 0)
1574:                            continue; // irrelevant
1575:                        Attribute.Layout.Element[] cbles = def.getCallables();
1576:                        for (int j = 0; j < cbles.length; j++) {
1577:                            assert (cbles[j].kind == Attribute.EK_CBLE);
1578:                            if (cbles[j].flagTest(Attribute.EF_BACK))
1579:                                callCounts += 1;
1580:                        }
1581:                    }
1582:                    if (!predef)
1583:                        break;
1584:                }
1585:                xxx_attr_calls.expectLength(callCounts);
1586:                xxx_attr_calls.readFrom(in);
1587:
1588:                // Finally, size all the attribute bands.
1589:                for (boolean predef = true;; predef = false) {
1590:                    for (int ai = 0; ai < defs.length; ai++) {
1591:                        Attribute.Layout def = defs[ai];
1592:                        if (def == null)
1593:                            continue; // unused index
1594:                        if (predef != isPredefinedAttr(ctype, ai))
1595:                            continue; // wrong pass
1596:                        int totalCount = totalCounts[ai];
1597:                        Band[] ab = (Band[]) attrBandTable.get(def);
1598:                        if (def == attrInnerClassesEmpty) {
1599:                            // Special case.
1600:                            // Size the bands as if using the following layout:
1601:                            //    [RCH TI[ (0)[] ()[RCNH RUNH] ]].
1602:                            class_InnerClasses_N.expectLength(totalCount);
1603:                            class_InnerClasses_N.readFrom(in);
1604:                            int tupleCount = class_InnerClasses_N.getIntTotal();
1605:                            class_InnerClasses_RC.expectLength(tupleCount);
1606:                            class_InnerClasses_RC.readFrom(in);
1607:                            class_InnerClasses_F.expectLength(tupleCount);
1608:                            class_InnerClasses_F.readFrom(in);
1609:                            // Drop remaining columns wherever flags are zero:
1610:                            tupleCount -= class_InnerClasses_F.getIntCount(0);
1611:                            class_InnerClasses_outer_RCN
1612:                                    .expectLength(tupleCount);
1613:                            class_InnerClasses_outer_RCN.readFrom(in);
1614:                            class_InnerClasses_name_RUN
1615:                                    .expectLength(tupleCount);
1616:                            class_InnerClasses_name_RUN.readFrom(in);
1617:                        } else if (totalCount == 0) {
1618:                            // Expect no elements at all.  Skip quickly.
1619:                            for (int j = 0; j < ab.length; j++) {
1620:                                ab[j].doneWithUnusedBand();
1621:                            }
1622:                        } else {
1623:                            // Read these bands in sequence.
1624:                            boolean hasCallables = def.hasCallables();
1625:                            if (!hasCallables) {
1626:                                readAttrBands(def.elems, totalCount,
1627:                                        new int[0], ab);
1628:                            } else {
1629:                                Attribute.Layout.Element[] cbles = def
1630:                                        .getCallables();
1631:                                // At first, record initial calls.
1632:                                // Later, forward calls may also accumulate here:
1633:                                int[] forwardCounts = new int[cbles.length];
1634:                                forwardCounts[0] = totalCount;
1635:                                for (int j = 0; j < cbles.length; j++) {
1636:                                    assert (cbles[j].kind == Attribute.EK_CBLE);
1637:                                    int entryCount = forwardCounts[j];
1638:                                    forwardCounts[j] = -1; // No more, please!
1639:                                    if (cbles[j].flagTest(Attribute.EF_BACK))
1640:                                        entryCount += xxx_attr_calls.getInt();
1641:                                    readAttrBands(cbles[j].body, entryCount,
1642:                                            forwardCounts, ab);
1643:                                }
1644:                            }
1645:                        }
1646:                    }
1647:                    if (!predef)
1648:                        break;
1649:                }
1650:                xxx_attr_calls.doneDisbursing();
1651:            }
1652:
1653:            void badAttrIndex(int ai, int ctype) throws IOException {
1654:                throw new IOException("Unknown attribute index " + ai + " for "
1655:                        + ATTR_CONTEXT_NAME[ctype] + " attribute");
1656:            }
1657:
1658:            void readAttrs(int ctype, Collection holders) throws IOException {
1659:                // Decode band values into attributes.
1660:                HashSet sawDefs = new HashSet();
1661:                ByteArrayOutputStream buf = new ByteArrayOutputStream();
1662:                for (Iterator i = holders.iterator(); i.hasNext();) {
1663:                    final Attribute.Holder h = (Attribute.Holder) i.next();
1664:                    if (h.attributes == null)
1665:                        continue;
1666:                    for (ListIterator j = h.attributes.listIterator(); j
1667:                            .hasNext();) {
1668:                        Attribute a = (Attribute) j.next();
1669:                        Attribute.Layout def = a.layout();
1670:                        if (def.bandCount == 0) {
1671:                            if (def == attrInnerClassesEmpty) {
1672:                                // Special logic to read this attr.
1673:                                readLocalInnerClasses((Class) h);
1674:                                continue;
1675:                            }
1676:                            // Canonical empty attr works fine (e.g., Synthetic).
1677:                            continue;
1678:                        }
1679:                        sawDefs.add(def);
1680:                        boolean isCV = (ctype == ATTR_CONTEXT_FIELD && def == attrConstantValue);
1681:                        if (isCV)
1682:                            setConstantValueIndex((Class.Field) h);
1683:                        if (verbose > 2)
1684:                            Utils.log.fine("read " + a + " in " + h);
1685:                        final Band[] ab = (Band[]) attrBandTable.get(def);
1686:                        // Read one attribute of type def from ab into a byte array.
1687:                        buf.reset();
1688:                        Object fixups = a.unparse(new Attribute.ValueStream() {
1689:                            public int getInt(int bandIndex) {
1690:                                return ((IntBand) ab[bandIndex]).getInt();
1691:                            }
1692:
1693:                            public Entry getRef(int bandIndex) {
1694:                                return ((CPRefBand) ab[bandIndex]).getRef();
1695:                            }
1696:
1697:                            public int decodeBCI(int bciCode) {
1698:                                Code code = (Code) h;
1699:                                return code.decodeBCI(bciCode);
1700:                            }
1701:                        }, buf);
1702:                        // Replace the canonical attr with the one just read.
1703:                        j.set(a.addContent(buf.toByteArray(), fixups));
1704:                        if (isCV)
1705:                            setConstantValueIndex(null); // clean up
1706:                    }
1707:                }
1708:
1709:                // Mark the bands we just used as done disbursing.
1710:                for (Iterator i = sawDefs.iterator(); i.hasNext();) {
1711:                    Attribute.Layout def = (Attribute.Layout) i.next();
1712:                    if (def == null)
1713:                        continue; // unused index
1714:                    Band[] ab = (Band[]) attrBandTable.get(def);
1715:                    for (int j = 0; j < ab.length; j++) {
1716:                        ab[j].doneDisbursing();
1717:                    }
1718:                }
1719:
1720:                if (ctype == ATTR_CONTEXT_CLASS) {
1721:                    class_InnerClasses_N.doneDisbursing();
1722:                    class_InnerClasses_RC.doneDisbursing();
1723:                    class_InnerClasses_F.doneDisbursing();
1724:                    class_InnerClasses_outer_RCN.doneDisbursing();
1725:                    class_InnerClasses_name_RUN.doneDisbursing();
1726:                }
1727:
1728:                MultiBand xxx_attr_bands = attrBands[ctype];
1729:                for (int i = 0; i < xxx_attr_bands.size(); i++) {
1730:                    Band b = xxx_attr_bands.get(i);
1731:                    if (b instanceof  MultiBand)
1732:                        b.doneDisbursing();
1733:                }
1734:                xxx_attr_bands.doneDisbursing();
1735:            }
1736:
1737:            private void readAttrBands(Attribute.Layout.Element[] elems,
1738:                    int count, int[] forwardCounts, Band[] ab)
1739:                    throws IOException {
1740:                for (int i = 0; i < elems.length; i++) {
1741:                    Attribute.Layout.Element e = elems[i];
1742:                    Band eBand = null;
1743:                    if (e.hasBand()) {
1744:                        eBand = ab[e.bandIndex];
1745:                        eBand.expectLength(count);
1746:                        eBand.readFrom(in);
1747:                    }
1748:                    switch (e.kind) {
1749:                    case Attribute.EK_REPL:
1750:                        // Recursive call.
1751:                        int repCount = ((IntBand) eBand).getIntTotal();
1752:                        // Note:  getIntTotal makes an extra pass over this band.
1753:                        readAttrBands(e.body, repCount, forwardCounts, ab);
1754:                        break;
1755:                    case Attribute.EK_UN:
1756:                        int remainingCount = count;
1757:                        for (int j = 0; j < e.body.length; j++) {
1758:                            int caseCount;
1759:                            if (j == e.body.length - 1) {
1760:                                caseCount = remainingCount;
1761:                            } else {
1762:                                caseCount = 0;
1763:                                for (int j0 = j; (j == j0)
1764:                                        || (j < e.body.length && e.body[j]
1765:                                                .flagTest(Attribute.EF_BACK)); j++) {
1766:                                    caseCount += ((IntBand) eBand)
1767:                                            .getIntCount(e.body[j].value);
1768:                                }
1769:                                --j; // back up to last occurrence of this body
1770:                            }
1771:                            remainingCount -= caseCount;
1772:                            readAttrBands(e.body[j].body, caseCount,
1773:                                    forwardCounts, ab);
1774:                        }
1775:                        assert (remainingCount == 0);
1776:                        break;
1777:                    case Attribute.EK_CALL:
1778:                        assert (e.body.length == 1);
1779:                        assert (e.body[0].kind == Attribute.EK_CBLE);
1780:                        if (!e.flagTest(Attribute.EF_BACK)) {
1781:                            // Backward calls are pre-counted, but forwards are not.
1782:                            // Push the present count forward.
1783:                            assert (forwardCounts[e.value] >= 0);
1784:                            forwardCounts[e.value] += count;
1785:                        }
1786:                        break;
1787:                    case Attribute.EK_CBLE:
1788:                        assert (false);
1789:                        break;
1790:                    }
1791:                }
1792:            }
1793:
1794:            void readByteCodes() throws IOException {
1795:                //  bc_bands:
1796:                //        *bc_codes :BYTE1
1797:                //        *bc_case_count :UNSIGNED5
1798:                //        *bc_case_value :DELTA5
1799:                //        *bc_byte :BYTE1
1800:                //        *bc_short :DELTA5
1801:                //        *bc_local :UNSIGNED5
1802:                //        *bc_label :BRANCH5
1803:                //        *bc_intref :DELTA5  (cp_Int)
1804:                //        *bc_floatref :DELTA5  (cp_Float)
1805:                //        *bc_longref :DELTA5  (cp_Long)
1806:                //        *bc_doubleref :DELTA5  (cp_Double)
1807:                //        *bc_stringref :DELTA5  (cp_String)
1808:                //        *bc_classref :UNSIGNED5  (current class or cp_Class)
1809:                //        *bc_fieldref :DELTA5  (cp_Field)
1810:                //        *bc_methodref :UNSIGNED5  (cp_Method)
1811:                //        *bc_imethodref :DELTA5  (cp_Imethod)
1812:                //        *bc_thisfield :UNSIGNED5 (cp_Field, only for current class)
1813:                //        *bc_superfield :UNSIGNED5 (cp_Field, only for current super)
1814:                //        *bc_thismethod :UNSIGNED5 (cp_Method, only for current class)
1815:                //        *bc_supermethod :UNSIGNED5 (cp_Method, only for current super)
1816:                //        *bc_initref :UNSIGNED5 (cp_Field, only for most recent new)
1817:                //        *bc_escref :UNSIGNED5 (cp_All)
1818:                //        *bc_escrefsize :UNSIGNED5
1819:                //        *bc_escsize :UNSIGNED5
1820:                //        *bc_escbyte :BYTE1
1821:                bc_codes.elementCountForDebug = allCodes.length;
1822:                bc_codes.setInputStreamFrom(in);
1823:                readByteCodeOps(); // reads from bc_codes and bc_case_count
1824:                bc_codes.doneDisbursing();
1825:
1826:                // All the operand bands have now been sized.  Read them all in turn.
1827:                Band[] operand_bands = { bc_case_value, bc_byte, bc_short,
1828:                        bc_local, bc_label, bc_intref, bc_floatref, bc_longref,
1829:                        bc_doubleref, bc_stringref, bc_classref, bc_fieldref,
1830:                        bc_methodref, bc_imethodref, bc_this field,
1831:                        bc_super field, bc_this method, bc_super method,
1832:                        bc_initref, bc_escref, bc_escrefsize, bc_escsize };
1833:                for (int i = 0; i < operand_bands.length; i++) {
1834:                    operand_bands[i].readFrom(in);
1835:                }
1836:                bc_escbyte.expectLength(bc_escsize.getIntTotal());
1837:                bc_escbyte.readFrom(in);
1838:
1839:                expandByteCodeOps();
1840:
1841:                // Done fetching values from operand bands:
1842:                bc_case_count.doneDisbursing();
1843:                for (int i = 0; i < operand_bands.length; i++) {
1844:                    operand_bands[i].doneDisbursing();
1845:                }
1846:                bc_escbyte.doneDisbursing();
1847:                bc_bands.doneDisbursing();
1848:
1849:                // We must delay the parsing of Code attributes until we
1850:                // have a complete model of bytecodes, for BCI encodings.
1851:                readAttrs(ATTR_CONTEXT_CODE, codesWithFlags);
1852:                // Ditto for exception handlers in codes.
1853:                fixupCodeHandlers();
1854:                // Now we can finish with class_bands; cf. readClasses().
1855:                code_bands.doneDisbursing();
1856:                class_bands.doneDisbursing();
1857:            }
1858:
1859:            private void readByteCodeOps() throws IOException {
1860:                // scratch buffer for collecting code::
1861:                byte[] buf = new byte[1 << 12];
1862:                // record of all switch opcodes (these are variable-length)
1863:                ArrayList allSwitchOps = new ArrayList();
1864:                for (int k = 0; k < allCodes.length; k++) {
1865:                    Code c = allCodes[k];
1866:                    scanOneMethod: for (int i = 0;; i++) {
1867:                        int bc = bc_codes.getByte();
1868:                        if (i + 10 > buf.length)
1869:                            buf = realloc(buf);
1870:                        buf[i] = (byte) bc;
1871:                        boolean isWide = false;
1872:                        if (bc == _wide) {
1873:                            bc = bc_codes.getByte();
1874:                            buf[++i] = (byte) bc;
1875:                            isWide = true;
1876:                        }
1877:                        assert (bc == (0xFF & bc));
1878:                        // Adjust expectations of various band sizes.
1879:                        switch (bc) {
1880:                        case _tableswitch:
1881:                        case _lookupswitch:
1882:                            bc_case_count.expectMoreLength(1);
1883:                            allSwitchOps.add(new Integer(bc));
1884:                            break;
1885:                        case _iinc:
1886:                            bc_local.expectMoreLength(1);
1887:                            if (isWide)
1888:                                bc_short.expectMoreLength(1);
1889:                            else
1890:                                bc_byte.expectMoreLength(1);
1891:                            break;
1892:                        case _sipush:
1893:                            bc_short.expectMoreLength(1);
1894:                            break;
1895:                        case _bipush:
1896:                            bc_byte.expectMoreLength(1);
1897:                            break;
1898:                        case _newarray:
1899:                            bc_byte.expectMoreLength(1);
1900:                            break;
1901:                        case _multianewarray:
1902:                            assert (getCPRefOpBand(bc) == bc_classref);
1903:                            bc_classref.expectMoreLength(1);
1904:                            bc_byte.expectMoreLength(1);
1905:                            break;
1906:                        case _ref_escape:
1907:                            bc_escrefsize.expectMoreLength(1);
1908:                            bc_escref.expectMoreLength(1);
1909:                            break;
1910:                        case _byte_escape:
1911:                            bc_escsize.expectMoreLength(1);
1912:                            // bc_escbyte will have to be counted too
1913:                            break;
1914:                        default:
1915:                            if (Instruction.isInvokeInitOp(bc)) {
1916:                                bc_initref.expectMoreLength(1);
1917:                                break;
1918:                            }
1919:                            if (Instruction.isSelfLinkerOp(bc)) {
1920:                                CPRefBand bc_which = selfOpRefBand(bc);
1921:                                bc_which.expectMoreLength(1);
1922:                                break;
1923:                            }
1924:                            if (Instruction.isBranchOp(bc)) {
1925:                                bc_label.expectMoreLength(1);
1926:                                break;
1927:                            }
1928:                            if (Instruction.isCPRefOp(bc)) {
1929:                                CPRefBand bc_which = getCPRefOpBand(bc);
1930:                                bc_which.expectMoreLength(1);
1931:                                assert (bc != _multianewarray); // handled elsewhere
1932:                                break;
1933:                            }
1934:                            if (Instruction.isLocalSlotOp(bc)) {
1935:                                bc_local.expectMoreLength(1);
1936:                                break;
1937:                            }
1938:                            break;
1939:                        case _end_marker: {
1940:                            // Transfer from buf to a more permanent place:
1941:                            c.bytes = realloc(buf, i);
1942:                            break scanOneMethod;
1943:                        }
1944:                        }
1945:                    }
1946:                }
1947:
1948:                // To size instruction bands correctly, we need info on switches:
1949:                bc_case_count.readFrom(in);
1950:                for (Iterator i = allSwitchOps.iterator(); i.hasNext();) {
1951:                    int bc = ((Integer) i.next()).intValue();
1952:                    int caseCount = bc_case_count.getInt();
1953:                    bc_label.expectMoreLength(1 + caseCount); // default label + cases
1954:                    bc_case_value.expectMoreLength(bc == _tableswitch ? 1
1955:                            : caseCount);
1956:                }
1957:                bc_case_count.resetForSecondPass();
1958:            }
1959:
1960:            private void expandByteCodeOps() throws IOException {
1961:                // scratch buffer for collecting code:
1962:                byte[] buf = new byte[1 << 12];
1963:                // scratch buffer for collecting instruction boundaries:
1964:                int[] insnMap = new int[1 << 12];
1965:                // list of label carriers, for label decoding post-pass:
1966:                int[] labels = new int[1 << 10];
1967:                // scratch buffer for registering CP refs:
1968:                Fixups fixupBuf = new Fixups();
1969:
1970:                for (int k = 0; k < allCodes.length; k++) {
1971:                    Code code = allCodes[k];
1972:                    byte[] codeOps = code.bytes;
1973:                    code.bytes = null; // just for now, while we accumulate bits
1974:
1975:                    Class curClass = code.this Class();
1976:
1977:                    HashSet ldcRefSet = (HashSet) ldcRefMap.get(curClass);
1978:                    if (ldcRefSet == null)
1979:                        ldcRefMap.put(curClass, ldcRefSet = new HashSet());
1980:
1981:                    ClassEntry this Class = curClass.this Class;
1982:                    ClassEntry super Class = curClass.super Class;
1983:                    ClassEntry newClass = null; // class of last _new opcode
1984:
1985:                    int pc = 0; // fill pointer in buf; actual bytecode PC
1986:                    int numInsns = 0;
1987:                    int numLabels = 0;
1988:                    boolean hasEscs = false;
1989:                    fixupBuf.clear();
1990:                    for (int i = 0; i < codeOps.length; i++) {
1991:                        int bc = Instruction.getByte(codeOps, i);
1992:                        int curPC = pc;
1993:                        insnMap[numInsns++] = curPC;
1994:                        if (pc + 10 > buf.length)
1995:                            buf = realloc(buf);
1996:                        if (numInsns + 10 > insnMap.length)
1997:                            insnMap = realloc(insnMap);
1998:                        if (numLabels + 10 > labels.length)
1999:                            labels = realloc(labels);
2000:                        boolean isWide = false;
2001:                        if (bc == _wide) {
2002:                            buf[pc++] = (byte) bc;
2003:                            bc = Instruction.getByte(codeOps, ++i);
2004:                            isWide = true;
2005:                        }
2006:                        switch (bc) {
2007:                        case _tableswitch: // apc:  (df, lo, hi, (hi-lo+1)*(label))
2008:                        case _lookupswitch: // apc:  (df, nc, nc*(case, label))
2009:                        {
2010:                            int caseCount = bc_case_count.getInt();
2011:                            while ((pc + 30 + caseCount * 8) > buf.length)
2012:                                buf = realloc(buf);
2013:                            buf[pc++] = (byte) bc;
2014:                            //initialize apc, df, lo, hi bytes to reasonable bits:
2015:                            Arrays.fill(buf, pc, pc + 30, (byte) 0);
2016:                            Instruction.Switch isw = (Instruction.Switch) Instruction
2017:                                    .at(buf, curPC);
2018:                            //isw.setDefaultLabel(getLabel(bc_label, code, curPC));
2019:                            isw.setCaseCount(caseCount);
2020:                            if (bc == _tableswitch) {
2021:                                isw.setCaseValue(0, bc_case_value.getInt());
2022:                            } else {
2023:                                for (int j = 0; j < caseCount; j++) {
2024:                                    isw.setCaseValue(j, bc_case_value.getInt());
2025:                                }
2026:                            }
2027:                            // Make our getLabel calls later.
2028:                            labels[numLabels++] = curPC;
2029:                            pc = isw.getNextPC();
2030:                            continue;
2031:                        }
2032:                        case _iinc: {
2033:                            buf[pc++] = (byte) bc;
2034:                            int local = bc_local.getInt();
2035:                            int delta;
2036:                            if (isWide) {
2037:                                delta = bc_short.getInt();
2038:                                Instruction.setShort(buf, pc, local);
2039:                                pc += 2;
2040:                                Instruction.setShort(buf, pc, delta);
2041:                                pc += 2;
2042:                            } else {
2043:                                delta = (byte) bc_byte.getByte();
2044:                                buf[pc++] = (byte) local;
2045:                                buf[pc++] = (byte) delta;
2046:                            }
2047:                            continue;
2048:                        }
2049:                        case _sipush: {
2050:                            int val = bc_short.getInt();
2051:                            buf[pc++] = (byte) bc;
2052:                            Instruction.setShort(buf, pc, val);
2053:                            pc += 2;
2054:                            continue;
2055:                        }
2056:                        case _bipush:
2057:                        case _newarray: {
2058:                            int val = bc_byte.getByte();
2059:                            buf[pc++] = (byte) bc;
2060:                            buf[pc++] = (byte) val;
2061:                            continue;
2062:                        }
2063:                        case _ref_escape: {
2064:                            // Note that insnMap has one entry for this.
2065:                            hasEscs = true;
2066:                            int size = bc_escrefsize.getInt();
2067:                            Entry ref = bc_escref.getRef();
2068:                            if (size == 1)
2069:                                ldcRefSet.add(ref);
2070:                            int fmt;
2071:                            switch (size) {
2072:                            case 1:
2073:                                fmt = Fixups.U1_FORMAT;
2074:                                break;
2075:                            case 2:
2076:                                fmt = Fixups.U2_FORMAT;
2077:                                break;
2078:                            default:
2079:                                assert (false);
2080:                                fmt = 0;
2081:                            }
2082:                            fixupBuf.add(pc, fmt, ref);
2083:                            buf[pc + 0] = buf[pc + 1] = 0;
2084:                            pc += size;
2085:                        }
2086:                            continue;
2087:                        case _byte_escape: {
2088:                            // Note that insnMap has one entry for all these bytes.
2089:                            hasEscs = true;
2090:                            int size = bc_escsize.getInt();
2091:                            while ((pc + size) > buf.length)
2092:                                buf = realloc(buf);
2093:                            while (size-- > 0) {
2094:                                buf[pc++] = (byte) bc_escbyte.getByte();
2095:                            }
2096:                        }
2097:                            continue;
2098:                        default:
2099:                            if (Instruction.isInvokeInitOp(bc)) {
2100:                                int idx = (bc - _invokeinit_op);
2101:                                int origBC = _invokespecial;
2102:                                ClassEntry classRef;
2103:                                switch (idx) {
2104:                                case _invokeinit_self_option:
2105:                                    classRef = this Class;
2106:                                    break;
2107:                                case _invokeinit_super _option:
2108:                                    classRef = super Class;
2109:                                    break;
2110:                                default:
2111:                                    assert (idx == _invokeinit_new_option);
2112:                                    classRef = newClass;
2113:                                    break;
2114:                                }
2115:                                buf[pc++] = (byte) origBC;
2116:                                int coding = bc_initref.getInt();
2117:                                // Find the nth overloading of <init> in classRef.
2118:                                MemberEntry ref = pkg.cp
2119:                                        .getOverloadingForIndex(
2120:                                                CONSTANT_Methodref, classRef,
2121:                                                "<init>", coding);
2122:                                fixupBuf.add(pc, Fixups.U2_FORMAT, ref);
2123:                                buf[pc + 0] = buf[pc + 1] = 0;
2124:                                pc += 2;
2125:                                assert (Instruction.opLength(origBC) == (pc - curPC));
2126:                                continue;
2127:                            }
2128:                            if (Instruction.isSelfLinkerOp(bc)) {
2129:                                int idx = (bc - _self_linker_op);
2130:                                boolean isSuper = (idx >= _self_linker_super _flag);
2131:                                if (isSuper)
2132:                                    idx -= _self_linker_super _flag;
2133:                                boolean isAload = (idx >= _self_linker_aload_flag);
2134:                                if (isAload)
2135:                                    idx -= _self_linker_aload_flag;
2136:                                int origBC = _first_linker_op + idx;
2137:                                boolean isField = Instruction.isFieldOp(origBC);
2138:                                CPRefBand bc_which;
2139:                                ClassEntry which_cls = isSuper ? super Class
2140:                                        : this Class;
2141:                                Index which_ix;
2142:                                if (isField) {
2143:                                    bc_which = isSuper ? bc_super field
2144:                                            : bc_this field;
2145:                                    which_ix = pkg.cp.getMemberIndex(
2146:                                            CONSTANT_Fieldref, which_cls);
2147:                                } else {
2148:                                    bc_which = isSuper ? bc_super method
2149:                                            : bc_this method;
2150:                                    which_ix = pkg.cp.getMemberIndex(
2151:                                            CONSTANT_Methodref, which_cls);
2152:                                }
2153:                                assert (bc_which == selfOpRefBand(bc));
2154:                                MemberEntry ref = (MemberEntry) bc_which
2155:                                        .getRef(which_ix);
2156:                                if (isAload) {
2157:                                    buf[pc++] = (byte) _aload_0;
2158:                                    curPC = pc;
2159:                                    // Note: insnMap keeps the _aload_0 separate.
2160:                                    insnMap[numInsns++] = curPC;
2161:                                }
2162:                                buf[pc++] = (byte) origBC;
2163:                                fixupBuf.add(pc, Fixups.U2_FORMAT, ref);
2164:                                buf[pc + 0] = buf[pc + 1] = 0;
2165:                                pc += 2;
2166:                                assert (Instruction.opLength(origBC) == (pc - curPC));
2167:                                continue;
2168:                            }
2169:                            if (Instruction.isBranchOp(bc)) {
2170:                                buf[pc++] = (byte) bc;
2171:                                assert (!isWide); // no wide prefix for branches
2172:                                int nextPC = curPC + Instruction.opLength(bc);
2173:                                // Make our getLabel calls later.
2174:                                labels[numLabels++] = curPC;
2175:                                //Instruction.at(buf, curPC).setBranchLabel(getLabel(bc_label, code, curPC));
2176:                                while (pc < nextPC)
2177:                                    buf[pc++] = 0;
2178:                                continue;
2179:                            }
2180:                            if (Instruction.isCPRefOp(bc)) {
2181:                                CPRefBand bc_which = getCPRefOpBand(bc);
2182:                                Entry ref = bc_which.getRef();
2183:                                if (ref == null) {
2184:                                    if (bc_which == bc_classref) {
2185:                                        // Shorthand for class self-references.
2186:                                        ref = this Class;
2187:                                    } else {
2188:                                        assert (false);
2189:                                    }
2190:                                }
2191:                                int origBC = bc;
2192:                                int size = 2;
2193:                                switch (bc) {
2194:                                case _ildc:
2195:                                case _cldc:
2196:                                case _fldc:
2197:                                case _aldc:
2198:                                    origBC = _ldc;
2199:                                    size = 1;
2200:                                    ldcRefSet.add(ref);
2201:                                    break;
2202:                                case _ildc_w:
2203:                                case _cldc_w:
2204:                                case _fldc_w:
2205:                                case _aldc_w:
2206:                                    origBC = _ldc_w;
2207:                                    break;
2208:                                case _lldc2_w:
2209:                                case _dldc2_w:
2210:                                    origBC = _ldc2_w;
2211:                                    break;
2212:                                case _new:
2213:                                    newClass = (ClassEntry) ref;
2214:                                    break;
2215:                                }
2216:                                buf[pc++] = (byte) origBC;
2217:                                int fmt;
2218:                                switch (size) {
2219:                                case 1:
2220:                                    fmt = Fixups.U1_FORMAT;
2221:                                    break;
2222:                                case 2:
2223:                                    fmt = Fixups.U2_FORMAT;
2224:                                    break;
2225:                                default:
2226:                                    assert (false);
2227:                                    fmt = 0;
2228:                                }
2229:                                fixupBuf.add(pc, fmt, ref);
2230:                                buf[pc + 0] = buf[pc + 1] = 0;
2231:                                pc += size;
2232:                                if (origBC == _multianewarray) {
2233:                                    // Copy the trailing byte also.
2234:                                    int val = bc_byte.getByte();
2235:                                    buf[pc++] = (byte) val;
2236:                                } else if (origBC == _invokeinterface) {
2237:                                    int argSize = ((MemberEntry) ref).descRef.typeRef
2238:                                            .computeSize(true);
2239:                                    buf[pc++] = (byte) (1 + argSize);
2240:                                    buf[pc++] = 0;
2241:                                }
2242:                                assert (Instruction.opLength(origBC) == (pc - curPC));
2243:                                continue;
2244:                            }
2245:                            if (Instruction.isLocalSlotOp(bc)) {
2246:                                buf[pc++] = (byte) bc;
2247:                                int local = bc_local.getInt();
2248:                                if (isWide) {
2249:                                    Instruction.setShort(buf, pc, local);
2250:                                    pc += 2;
2251:                                    if (bc == _iinc) {
2252:                                        int iVal = bc_short.getInt();
2253:                                        Instruction.setShort(buf, pc, iVal);
2254:                                        pc += 2;
2255:                                    }
2256:                                } else {
2257:                                    Instruction.setByte(buf, pc, local);
2258:                                    pc += 1;
2259:                                    if (bc == _iinc) {
2260:                                        int iVal = bc_byte.getByte();
2261:                                        Instruction.setByte(buf, pc, iVal);
2262:                                        pc += 1;
2263:                                    }
2264:                                }
2265:                                assert (Instruction.opLength(bc) == (pc - curPC));
2266:                                continue;
2267:                            }
2268:                            // Random bytecode.  Just copy it.
2269:                            if (bc >= _bytecode_limit)
2270:                                Utils.log.warning("unrecognized bytescode "
2271:                                        + bc + " " + Instruction.byteName(bc));
2272:                            assert (bc < _bytecode_limit);
2273:                            buf[pc++] = (byte) bc;
2274:                            assert (Instruction.opLength(bc) == (pc - curPC));
2275:                            continue;
2276:                        }
2277:                    }
2278:                    // now make a permanent copy of the bytecodes
2279:                    code.setBytes(realloc(buf, pc));
2280:                    code.setInstructionMap(insnMap, numInsns);
2281:                    // fix up labels, now that code has its insnMap
2282:                    Instruction ibr = null; // temporary branch instruction
2283:                    for (int i = 0; i < numLabels; i++) {
2284:                        int curPC = labels[i];
2285:                        // (Note:  Passing ibr in allows reuse, a speed hack.)
2286:                        ibr = Instruction.at(code.bytes, curPC, ibr);
2287:                        if (ibr instanceof  Instruction.Switch) {
2288:                            Instruction.Switch isw = (Instruction.Switch) ibr;
2289:                            isw
2290:                                    .setDefaultLabel(getLabel(bc_label, code,
2291:                                            curPC));
2292:                            int caseCount = isw.getCaseCount();
2293:                            for (int j = 0; j < caseCount; j++) {
2294:                                isw.setCaseLabel(j, getLabel(bc_label, code,
2295:                                        curPC));
2296:                            }
2297:                        } else {
2298:                            ibr.setBranchLabel(getLabel(bc_label, code, curPC));
2299:                        }
2300:                    }
2301:                    if (fixupBuf.size() > 0) {
2302:                        if (verbose > 2)
2303:                            Utils.log.fine("Fixups in code: " + fixupBuf);
2304:                        code.addFixups(fixupBuf);
2305:                    }
2306:                }
2307:            }
2308:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.