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