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