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