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: }
|