1 /* 2 * Copyright (c) 2001, 2013, 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 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<Entry>() { 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 /* 1197 * BootstrapMethod(BSMs) are added here before InnerClasses(ICs), 1198 * so as to ensure the order. Noting that the BSMs may be 1199 * removed if they are not found in the CP, after the ICs expansion. 1200 */ 1201 cls.addAttribute(Package.attrBootstrapMethodsEmpty.canonicalInstance()); 1202 1203 // flesh out the local constant pool 1204 ConstantPool.completeReferencesIn(cpRefs, true, bsms); 1205 1206 // Now that we know all our local class references, 1207 // compute the InnerClasses attribute. 1208 int changed = cls.expandLocalICs(); 1209 1210 if (changed != 0) { 1211 if (changed > 0) { 1212 // Just visit the expanded InnerClasses attr. 1213 cls.visitInnerClassRefs(VRM_CLASSIC, cpRefs); 1214 } else { 1215 // Have to recompute from scratch, because of deletions. 1216 cpRefs.clear(); 1217 cls.visitRefs(VRM_CLASSIC, cpRefs); 1218 } 1219 1220 // flesh out the local constant pool, again 1221 ConstantPool.completeReferencesIn(cpRefs, true, bsms); 1222 } 1223 1224 // remove the attr previously set, otherwise add the bsm and 1225 // references as required 1226 if (bsms.isEmpty()) { 1227 cls.attributes.remove(Package.attrBootstrapMethodsEmpty.canonicalInstance()); 1228 } else { 1229 cpRefs.add(Package.getRefString("BootstrapMethods")); 1230 Collections.sort(bsms); 1231 cls.setBootstrapMethods(bsms); 1232 } 1233 1234 // construct a local constant pool 1235 int numDoubles = 0; 1236 for (Entry e : cpRefs) { 1237 if (e.isDoubleWord()) numDoubles++; 1238 } 1239 Entry[] cpMap = new Entry[1+numDoubles+cpRefs.size()]; 1240 int fillp = 1; 1241 1242 // Add all ldc operands first. 1243 if (ldcRefs != null) { 1244 assert(cpRefs.containsAll(ldcRefs)); 1245 for (Entry e : ldcRefs) { 1246 cpMap[fillp++] = e; 1247 } 1248 assert(fillp == 1+ldcRefs.size()); 1249 cpRefs.removeAll(ldcRefs); 1250 ldcRefs = null; // done with it 1251 } 1252 1253 // Next add all the two-byte references. 1254 Set<Entry> wideRefs = cpRefs; 1255 cpRefs = null; // do not use! 1256 int narrowLimit = fillp; 1257 for (Entry e : wideRefs) { 1258 cpMap[fillp++] = e; 1259 } 1260 assert(fillp == narrowLimit+wideRefs.size()); 1261 Arrays.sort(cpMap, 1, narrowLimit, entryOutputOrder); 1262 Arrays.sort(cpMap, narrowLimit, fillp, entryOutputOrder); 1263 1264 if (verbose > 3) { 1265 Utils.log.fine("CP of "+this+" {"); 1266 for (int i = 0; i < fillp; i++) { 1267 Entry e = cpMap[i]; 1268 Utils.log.fine(" "+((e==null)?-1:getOutputIndex(e)) 1269 +" : "+e); 1270 } 1271 Utils.log.fine("}"); 1272 } 1273 1274 // Now repack backwards, introducing null elements. 1275 int revp = cpMap.length; 1276 for (int i = fillp; --i >= 1; ) { 1277 Entry e = cpMap[i]; 1278 if (e.isDoubleWord()) 1279 cpMap[--revp] = null; 1280 cpMap[--revp] = e; 1281 } 1282 assert(revp == 1); // do not process the initial null 1283 1284 return cpMap; 1285 } 1286 1287 void readMembers(Class[] classes) throws IOException { 1288 // class_bands: 1289 // ... 1290 // *class_field_count :DELTA5 1291 // *class_method_count :DELTA5 1292 // 1293 // *field_descr :DELTA5 (cp_Descr) 1294 // field_attr_bands 1295 // 1296 // *method_descr :MDELTA5 (cp_Descr) 1297 // method_attr_bands 1298 // ... 1299 assert(classes.length == numClasses); 1300 class_field_count.expectLength(numClasses); 1301 class_method_count.expectLength(numClasses); 1302 class_field_count.readFrom(in); 1303 class_method_count.readFrom(in); 1304 1305 // Make a pre-pass over field and method counts to size the descrs: 1306 int totalNF = class_field_count.getIntTotal(); 1307 int totalNM = class_method_count.getIntTotal(); 1308 field_descr.expectLength(totalNF); 1309 method_descr.expectLength(totalNM); 1310 if (verbose > 1) Utils.log.fine("expecting #fields="+totalNF+ 1311 " and #methods="+totalNM+" in #classes="+numClasses); 1312 1313 List<Class.Field> fields = new ArrayList<>(totalNF); 1314 field_descr.readFrom(in); 1315 for (int i = 0; i < classes.length; i++) { 1316 Class c = classes[i]; 1317 int nf = class_field_count.getInt(); 1318 for (int j = 0; j < nf; j++) { 1319 Class.Field f = c.new Field(NO_FLAGS_YET, (DescriptorEntry) 1320 field_descr.getRef()); 1321 fields.add(f); 1322 } 1323 } 1324 class_field_count.doneDisbursing(); 1325 field_descr.doneDisbursing(); 1326 countAndReadAttrs(ATTR_CONTEXT_FIELD, fields); 1327 fields = null; // release to GC 1328 1329 List<Class.Method> methods = new ArrayList<>(totalNM); 1330 method_descr.readFrom(in); 1331 for (int i = 0; i < classes.length; i++) { 1332 Class c = classes[i]; 1333 int nm = class_method_count.getInt(); 1334 for (int j = 0; j < nm; j++) { 1335 Class.Method m = c.new Method(NO_FLAGS_YET, (DescriptorEntry) 1336 method_descr.getRef()); 1337 methods.add(m); 1338 } 1339 } 1340 class_method_count.doneDisbursing(); 1341 method_descr.doneDisbursing(); 1342 countAndReadAttrs(ATTR_CONTEXT_METHOD, methods); 1343 1344 // Up to this point, Code attributes look like empty attributes. 1345 // Now we start to special-case them. The empty canonical Code 1346 // attributes stay in the method attribute lists, however. 1347 allCodes = buildCodeAttrs(methods); 1348 } 1349 1350 Code[] allCodes; 1351 List<Code> codesWithFlags; 1352 Map<Class, Set<Entry>> ldcRefMap = new HashMap<>(); 1353 1354 Code[] buildCodeAttrs(List<Class.Method> methods) { 1355 List<Code> codes = new ArrayList<>(methods.size()); 1356 for (Class.Method m : methods) { 1357 if (m.getAttribute(attrCodeEmpty) != null) { 1358 m.code = new Code(m); 1359 codes.add(m.code); 1360 } 1361 } 1362 Code[] a = new Code[codes.size()]; 1363 codes.toArray(a); 1364 return a; 1365 } 1366 1367 void readCodeHeaders() throws IOException { 1368 // code_bands: 1369 // *code_headers :BYTE1 1370 // 1371 // *code_max_stack :UNSIGNED5 1372 // *code_max_na_locals :UNSIGNED5 1373 // *code_handler_count :UNSIGNED5 1374 // ... 1375 // code_attr_bands 1376 boolean attrsOK = testBit(archiveOptions, AO_HAVE_ALL_CODE_FLAGS); 1377 code_headers.expectLength(allCodes.length); 1378 code_headers.readFrom(in); 1379 List<Code> longCodes = new ArrayList<>(allCodes.length / 10); 1380 for (int i = 0; i < allCodes.length; i++) { 1381 Code c = allCodes[i]; 1382 int sc = code_headers.getByte(); 1383 assert(sc == (sc & 0xFF)); 1384 if (verbose > 2) 1385 Utils.log.fine("codeHeader "+c+" = "+sc); 1386 if (sc == LONG_CODE_HEADER) { 1387 // We will read ms/ml/nh/flags from bands shortly. 1388 longCodes.add(c); 1389 continue; 1390 } 1391 // Short code header is the usual case: 1392 c.setMaxStack( shortCodeHeader_max_stack(sc) ); 1393 c.setMaxNALocals( shortCodeHeader_max_na_locals(sc) ); 1394 c.setHandlerCount( shortCodeHeader_handler_count(sc) ); 1395 assert(shortCodeHeader(c) == sc); 1396 } 1397 code_headers.doneDisbursing(); 1398 code_max_stack.expectLength(longCodes.size()); 1399 code_max_na_locals.expectLength(longCodes.size()); 1400 code_handler_count.expectLength(longCodes.size()); 1401 1402 // Do the long headers now. 1403 code_max_stack.readFrom(in); 1404 code_max_na_locals.readFrom(in); 1405 code_handler_count.readFrom(in); 1406 for (Code c : longCodes) { 1407 c.setMaxStack( code_max_stack.getInt() ); 1408 c.setMaxNALocals( code_max_na_locals.getInt() ); 1409 c.setHandlerCount( code_handler_count.getInt() ); 1410 } 1411 code_max_stack.doneDisbursing(); 1412 code_max_na_locals.doneDisbursing(); 1413 code_handler_count.doneDisbursing(); 1414 1415 readCodeHandlers(); 1416 1417 if (attrsOK) { 1418 // Code attributes are common (debug info not stripped). 1419 codesWithFlags = Arrays.asList(allCodes); 1420 } else { 1421 // Code attributes are very sparse (debug info is stripped). 1422 codesWithFlags = longCodes; 1423 } 1424 countAttrs(ATTR_CONTEXT_CODE, codesWithFlags); 1425 // do readAttrs later, after BCs are scanned 1426 } 1427 1428 void readCodeHandlers() throws IOException { 1429 // code_bands: 1430 // ... 1431 // *code_handler_start_P :BCI5 1432 // *code_handler_end_PO :BRANCH5 1433 // *code_handler_catch_PO :BRANCH5 1434 // *code_handler_class_RCN :UNSIGNED5 (null or cp_Class) 1435 // ... 1436 int nh = 0; 1437 for (int i = 0; i < allCodes.length; i++) { 1438 Code c = allCodes[i]; 1439 nh += c.getHandlerCount(); 1440 } 1441 1442 ValueBand[] code_handler_bands = { 1443 code_handler_start_P, 1444 code_handler_end_PO, 1445 code_handler_catch_PO, 1446 code_handler_class_RCN 1447 }; 1448 1449 for (int i = 0; i < code_handler_bands.length; i++) { 1450 code_handler_bands[i].expectLength(nh); 1451 code_handler_bands[i].readFrom(in); 1452 } 1453 1454 for (int i = 0; i < allCodes.length; i++) { 1455 Code c = allCodes[i]; 1456 for (int j = 0, jmax = c.getHandlerCount(); j < jmax; j++) { 1457 c.handler_class[j] = code_handler_class_RCN.getRef(); 1458 // For now, just record the raw BCI codes. 1459 // We must wait until we have instruction boundaries. 1460 c.handler_start[j] = code_handler_start_P.getInt(); 1461 c.handler_end[j] = code_handler_end_PO.getInt(); 1462 c.handler_catch[j] = code_handler_catch_PO.getInt(); 1463 } 1464 } 1465 for (int i = 0; i < code_handler_bands.length; i++) { 1466 code_handler_bands[i].doneDisbursing(); 1467 } 1468 } 1469 1470 void fixupCodeHandlers() { 1471 // Actually decode (renumber) the BCIs now. 1472 for (int i = 0; i < allCodes.length; i++) { 1473 Code c = allCodes[i]; 1474 for (int j = 0, jmax = c.getHandlerCount(); j < jmax; j++) { 1475 int sum = c.handler_start[j]; 1476 c.handler_start[j] = c.decodeBCI(sum); 1477 sum += c.handler_end[j]; 1478 c.handler_end[j] = c.decodeBCI(sum); 1479 sum += c.handler_catch[j]; 1480 c.handler_catch[j] = c.decodeBCI(sum); 1481 } 1482 } 1483 } 1484 1485 // Generic routines for reading attributes of 1486 // classes, fields, methods, and codes. 1487 // The holders is a global list, already collected, 1488 // of attribute "customers". 1489 void countAndReadAttrs(int ctype, Collection<? extends Attribute.Holder> holders) 1490 throws IOException { 1491 // class_attr_bands: 1492 // *class_flags :UNSIGNED5 1493 // *class_attr_count :UNSIGNED5 1494 // *class_attr_indexes :UNSIGNED5 1495 // *class_attr_calls :UNSIGNED5 1496 // *class_Signature_RS :UNSIGNED5 (cp_Signature) 1497 // class_metadata_bands 1498 // *class_SourceFile_RU :UNSIGNED5 (cp_Utf8) 1499 // *class_EnclosingMethod_RM :UNSIGNED5 (cp_Method) 1500 // ic_local_bands 1501 // *class_ClassFile_version_minor_H :UNSIGNED5 1502 // *class_ClassFile_version_major_H :UNSIGNED5 1503 // 1504 // field_attr_bands: 1505 // *field_flags :UNSIGNED5 1506 // *field_attr_count :UNSIGNED5 1507 // *field_attr_indexes :UNSIGNED5 1508 // *field_attr_calls :UNSIGNED5 1509 // *field_Signature_RS :UNSIGNED5 (cp_Signature) 1510 // field_metadata_bands 1511 // *field_ConstantValue_KQ :UNSIGNED5 (cp_Int, etc.; see note) 1512 // 1513 // method_attr_bands: 1514 // *method_flags :UNSIGNED5 1515 // *method_attr_count :UNSIGNED5 1516 // *method_attr_indexes :UNSIGNED5 1517 // *method_attr_calls :UNSIGNED5 1518 // *method_Signature_RS :UNSIGNED5 (cp_Signature) 1519 // method_metadata_bands 1520 // *method_Exceptions_N :UNSIGNED5 1521 // *method_Exceptions_RC :UNSIGNED5 (cp_Class) 1522 // *method_MethodParameters_NB: BYTE1 1523 // *method_MethodParameters_RUN: UNSIGNED5 (cp_Utf8) 1524 // *method_MethodParameters_FH: UNSIGNED5 (flag) 1525 // 1526 // code_attr_bands: 1527 // *code_flags :UNSIGNED5 1528 // *code_attr_count :UNSIGNED5 1529 // *code_attr_indexes :UNSIGNED5 1530 // *code_attr_calls :UNSIGNED5 1531 // *code_LineNumberTable_N :UNSIGNED5 1532 // *code_LineNumberTable_bci_P :BCI5 1533 // *code_LineNumberTable_line :UNSIGNED5 1534 // *code_LocalVariableTable_N :UNSIGNED5 1535 // *code_LocalVariableTable_bci_P :BCI5 1536 // *code_LocalVariableTable_span_O :BRANCH5 1537 // *code_LocalVariableTable_name_RU :UNSIGNED5 (cp_Utf8) 1538 // *code_LocalVariableTable_type_RS :UNSIGNED5 (cp_Signature) 1539 // *code_LocalVariableTable_slot :UNSIGNED5 1540 1541 countAttrs(ctype, holders); 1542 readAttrs(ctype, holders); 1543 } 1544 1545 // Read flags and count the attributes that are to be placed 1546 // on the given holders. 1547 void countAttrs(int ctype, Collection<? extends Attribute.Holder> holders) 1548 throws IOException { 1549 // Here, xxx stands for one of class, field, method, code. 1550 MultiBand xxx_attr_bands = attrBands[ctype]; 1551 long flagMask = attrFlagMask[ctype]; 1552 if (verbose > 1) { 1553 Utils.log.fine("scanning flags and attrs for "+ 1554 Attribute.contextName(ctype)+"["+holders.size()+"]"); 1555 } 1556 1557 // Fetch the attribute layout definitions which govern the bands 1558 // we are about to read. 1559 List<Attribute.Layout> defList = attrDefs.get(ctype); 1560 Attribute.Layout[] defs = new Attribute.Layout[defList.size()]; 1561 defList.toArray(defs); 1562 IntBand xxx_flags_hi = getAttrBand(xxx_attr_bands, AB_FLAGS_HI); 1563 IntBand xxx_flags_lo = getAttrBand(xxx_attr_bands, AB_FLAGS_LO); 1564 IntBand xxx_attr_count = getAttrBand(xxx_attr_bands, AB_ATTR_COUNT); 1565 IntBand xxx_attr_indexes = getAttrBand(xxx_attr_bands, AB_ATTR_INDEXES); 1566 IntBand xxx_attr_calls = getAttrBand(xxx_attr_bands, AB_ATTR_CALLS); 1567 1568 // Count up the number of holders which have overflow attrs. 1569 int overflowMask = attrOverflowMask[ctype]; 1570 int overflowHolderCount = 0; 1571 boolean haveLongFlags = haveFlagsHi(ctype); 1572 xxx_flags_hi.expectLength(haveLongFlags? holders.size(): 0); 1573 xxx_flags_hi.readFrom(in); 1574 xxx_flags_lo.expectLength(holders.size()); 1575 xxx_flags_lo.readFrom(in); 1576 assert((flagMask & overflowMask) == overflowMask); 1577 for (Attribute.Holder h : holders) { 1578 int flags = xxx_flags_lo.getInt(); 1579 h.flags = flags; 1580 if ((flags & overflowMask) != 0) 1581 overflowHolderCount += 1; 1582 } 1583 1584 // For each holder with overflow attrs, read a count. 1585 xxx_attr_count.expectLength(overflowHolderCount); 1586 xxx_attr_count.readFrom(in); 1587 xxx_attr_indexes.expectLength(xxx_attr_count.getIntTotal()); 1588 xxx_attr_indexes.readFrom(in); 1589 1590 // Now it's time to check flag bits that indicate attributes. 1591 // We accumulate (a) a list of attribute types for each holder 1592 // (class/field/method/code), and also we accumulate (b) a total 1593 // count for each attribute type. 1594 int[] totalCounts = new int[defs.length]; 1595 for (Attribute.Holder h : holders) { 1596 assert(h.attributes == null); 1597 // System.out.println("flags="+h.flags+" using fm="+flagMask); 1598 long attrBits = ((h.flags & flagMask) << 32) >>> 32; 1599 // Clean up the flags now. 1600 h.flags -= (int)attrBits; // strip attr bits 1601 assert(h.flags == (char)h.flags); // 16 bits only now 1602 assert((ctype != ATTR_CONTEXT_CODE) || h.flags == 0); 1603 if (haveLongFlags) 1604 attrBits += (long)xxx_flags_hi.getInt() << 32; 1605 if (attrBits == 0) continue; // no attrs on this guy 1606 1607 int noa = 0; // number of overflow attrs 1608 long overflowBit = (attrBits & overflowMask); 1609 assert(overflowBit >= 0); 1610 attrBits -= overflowBit; 1611 if (overflowBit != 0) { 1612 noa = xxx_attr_count.getInt(); 1613 } 1614 1615 int nfa = 0; // number of flag attrs 1616 long bits = attrBits; 1617 for (int ai = 0; bits != 0; ai++) { 1618 if ((bits & (1L<<ai)) == 0) continue; 1619 bits -= (1L<<ai); 1620 nfa += 1; 1621 } 1622 List<Attribute> ha = new ArrayList<>(nfa + noa); 1623 h.attributes = ha; 1624 bits = attrBits; // iterate again 1625 for (int ai = 0; bits != 0; ai++) { 1626 if ((bits & (1L<<ai)) == 0) continue; 1627 bits -= (1L<<ai); 1628 totalCounts[ai] += 1; 1629 // This definition index is live in this holder. 1630 if (defs[ai] == null) badAttrIndex(ai, ctype); 1631 Attribute canonical = defs[ai].canonicalInstance(); 1632 ha.add(canonical); 1633 nfa -= 1; 1634 } 1635 assert(nfa == 0); 1636 for (; noa > 0; noa--) { 1637 int ai = xxx_attr_indexes.getInt(); 1638 totalCounts[ai] += 1; 1639 // This definition index is live in this holder. 1640 if (defs[ai] == null) badAttrIndex(ai, ctype); 1641 Attribute canonical = defs[ai].canonicalInstance(); 1642 ha.add(canonical); 1643 } 1644 } 1645 1646 xxx_flags_hi.doneDisbursing(); 1647 xxx_flags_lo.doneDisbursing(); 1648 xxx_attr_count.doneDisbursing(); 1649 xxx_attr_indexes.doneDisbursing(); 1650 1651 // Now each holder has a list of canonical attribute instances. 1652 // For layouts with no elements, we are done. However, for 1653 // layouts with bands, we must replace each canonical (empty) 1654 // instance with a value-bearing one, initialized from the 1655 // appropriate bands. 1656 1657 // Make a small pass to detect and read backward call counts. 1658 int callCounts = 0; 1659 for (boolean predef = true; ; predef = false) { 1660 for (int ai = 0; ai < defs.length; ai++) { 1661 Attribute.Layout def = defs[ai]; 1662 if (def == null) continue; // unused index 1663 if (predef != isPredefinedAttr(ctype, ai)) 1664 continue; // wrong pass 1665 int totalCount = totalCounts[ai]; 1666 if (totalCount == 0) 1667 continue; // irrelevant 1668 Attribute.Layout.Element[] cbles = def.getCallables(); 1669 for (int j = 0; j < cbles.length; j++) { 1670 assert(cbles[j].kind == Attribute.EK_CBLE); 1671 if (cbles[j].flagTest(Attribute.EF_BACK)) 1672 callCounts += 1; 1673 } 1674 } 1675 if (!predef) break; 1676 } 1677 xxx_attr_calls.expectLength(callCounts); 1678 xxx_attr_calls.readFrom(in); 1679 1680 // Finally, size all the attribute bands. 1681 for (boolean predef = true; ; predef = false) { 1682 for (int ai = 0; ai < defs.length; ai++) { 1683 Attribute.Layout def = defs[ai]; 1684 if (def == null) continue; // unused index 1685 if (predef != isPredefinedAttr(ctype, ai)) 1686 continue; // wrong pass 1687 int totalCount = totalCounts[ai]; 1688 Band[] ab = attrBandTable.get(def); 1689 if (def == attrInnerClassesEmpty) { 1690 // Special case. 1691 // Size the bands as if using the following layout: 1692 // [RCH TI[ (0)[] ()[RCNH RUNH] ]]. 1693 class_InnerClasses_N.expectLength(totalCount); 1694 class_InnerClasses_N.readFrom(in); 1695 int tupleCount = class_InnerClasses_N.getIntTotal(); 1696 class_InnerClasses_RC.expectLength(tupleCount); 1697 class_InnerClasses_RC.readFrom(in); 1698 class_InnerClasses_F.expectLength(tupleCount); 1699 class_InnerClasses_F.readFrom(in); 1700 // Drop remaining columns wherever flags are zero: 1701 tupleCount -= class_InnerClasses_F.getIntCount(0); 1702 class_InnerClasses_outer_RCN.expectLength(tupleCount); 1703 class_InnerClasses_outer_RCN.readFrom(in); 1704 class_InnerClasses_name_RUN.expectLength(tupleCount); 1705 class_InnerClasses_name_RUN.readFrom(in); 1706 } else if (totalCount == 0) { 1707 // Expect no elements at all. Skip quickly. 1708 for (int j = 0; j < ab.length; j++) { 1709 ab[j].doneWithUnusedBand(); 1710 } 1711 } else { 1712 // Read these bands in sequence. 1713 boolean hasCallables = def.hasCallables(); 1714 if (!hasCallables) { 1715 readAttrBands(def.elems, totalCount, new int[0], ab); 1716 } else { 1717 Attribute.Layout.Element[] cbles = def.getCallables(); 1718 // At first, record initial calls. 1719 // Later, forward calls may also accumulate here: 1720 int[] forwardCounts = new int[cbles.length]; 1721 forwardCounts[0] = totalCount; 1722 for (int j = 0; j < cbles.length; j++) { 1723 assert(cbles[j].kind == Attribute.EK_CBLE); 1724 int entryCount = forwardCounts[j]; 1725 forwardCounts[j] = -1; // No more, please! 1726 if (cbles[j].flagTest(Attribute.EF_BACK)) 1727 entryCount += xxx_attr_calls.getInt(); 1728 readAttrBands(cbles[j].body, entryCount, forwardCounts, ab); 1729 } 1730 } 1731 } 1732 } 1733 if (!predef) break; 1734 } 1735 xxx_attr_calls.doneDisbursing(); 1736 } 1737 1738 void badAttrIndex(int ai, int ctype) throws IOException { 1739 throw new IOException("Unknown attribute index "+ai+" for "+ 1740 ATTR_CONTEXT_NAME[ctype]+" attribute"); 1741 } 1742 1743 void readAttrs(int ctype, Collection<? extends Attribute.Holder> holders) 1744 throws IOException { 1745 // Decode band values into attributes. 1746 Set<Attribute.Layout> sawDefs = new HashSet<>(); 1747 ByteArrayOutputStream buf = new ByteArrayOutputStream(); 1748 for (final Attribute.Holder h : holders) { 1749 if (h.attributes == null) continue; 1750 for (ListIterator<Attribute> j = h.attributes.listIterator(); j.hasNext(); ) { 1751 Attribute a = j.next(); 1752 Attribute.Layout def = a.layout(); 1753 if (def.bandCount == 0) { 1754 if (def == attrInnerClassesEmpty) { 1755 // Special logic to read this attr. 1756 readLocalInnerClasses((Class) h); 1757 continue; 1758 } 1759 // Canonical empty attr works fine (e.g., Synthetic). 1760 continue; 1761 } 1762 sawDefs.add(def); 1763 boolean isCV = (ctype == ATTR_CONTEXT_FIELD && def == attrConstantValue); 1764 if (isCV) setConstantValueIndex((Class.Field)h); 1765 if (verbose > 2) 1766 Utils.log.fine("read "+a+" in "+h); 1767 final Band[] ab = attrBandTable.get(def); 1768 // Read one attribute of type def from ab into a byte array. 1769 buf.reset(); 1770 Object fixups = a.unparse(new Attribute.ValueStream() { 1771 public int getInt(int bandIndex) { 1772 return ((IntBand) ab[bandIndex]).getInt(); 1773 } 1774 public Entry getRef(int bandIndex) { 1775 return ((CPRefBand) ab[bandIndex]).getRef(); 1776 } 1777 public int decodeBCI(int bciCode) { 1778 Code code = (Code) h; 1779 return code.decodeBCI(bciCode); 1780 } 1781 }, buf); 1782 // Replace the canonical attr with the one just read. 1783 j.set(a.addContent(buf.toByteArray(), fixups)); 1784 if (isCV) setConstantValueIndex(null); // clean up 1785 } 1786 } 1787 1788 // Mark the bands we just used as done disbursing. 1789 for (Attribute.Layout def : sawDefs) { 1790 if (def == null) continue; // unused index 1791 Band[] ab = attrBandTable.get(def); 1792 for (int j = 0; j < ab.length; j++) { 1793 ab[j].doneDisbursing(); 1794 } 1795 } 1796 1797 if (ctype == ATTR_CONTEXT_CLASS) { 1798 class_InnerClasses_N.doneDisbursing(); 1799 class_InnerClasses_RC.doneDisbursing(); 1800 class_InnerClasses_F.doneDisbursing(); 1801 class_InnerClasses_outer_RCN.doneDisbursing(); 1802 class_InnerClasses_name_RUN.doneDisbursing(); 1803 } 1804 1805 MultiBand xxx_attr_bands = attrBands[ctype]; 1806 for (int i = 0; i < xxx_attr_bands.size(); i++) { 1807 Band b = xxx_attr_bands.get(i); 1808 if (b instanceof MultiBand) 1809 b.doneDisbursing(); 1810 } 1811 xxx_attr_bands.doneDisbursing(); 1812 } 1813 1814 private 1815 void readAttrBands(Attribute.Layout.Element[] elems, 1816 int count, int[] forwardCounts, 1817 Band[] ab) 1818 throws IOException { 1819 for (int i = 0; i < elems.length; i++) { 1820 Attribute.Layout.Element e = elems[i]; 1821 Band eBand = null; 1822 if (e.hasBand()) { 1823 eBand = ab[e.bandIndex]; 1824 eBand.expectLength(count); 1825 eBand.readFrom(in); 1826 } 1827 switch (e.kind) { 1828 case Attribute.EK_REPL: 1829 // Recursive call. 1830 int repCount = ((IntBand)eBand).getIntTotal(); 1831 // Note: getIntTotal makes an extra pass over this band. 1832 readAttrBands(e.body, repCount, forwardCounts, ab); 1833 break; 1834 case Attribute.EK_UN: 1835 int remainingCount = count; 1836 for (int j = 0; j < e.body.length; j++) { 1837 int caseCount; 1838 if (j == e.body.length-1) { 1839 caseCount = remainingCount; 1840 } else { 1841 caseCount = 0; 1842 for (int j0 = j; 1843 (j == j0) 1844 || (j < e.body.length 1845 && e.body[j].flagTest(Attribute.EF_BACK)); 1846 j++) { 1847 caseCount += ((IntBand)eBand).getIntCount(e.body[j].value); 1848 } 1849 --j; // back up to last occurrence of this body 1850 } 1851 remainingCount -= caseCount; 1852 readAttrBands(e.body[j].body, caseCount, forwardCounts, ab); 1853 } 1854 assert(remainingCount == 0); 1855 break; 1856 case Attribute.EK_CALL: 1857 assert(e.body.length == 1); 1858 assert(e.body[0].kind == Attribute.EK_CBLE); 1859 if (!e.flagTest(Attribute.EF_BACK)) { 1860 // Backward calls are pre-counted, but forwards are not. 1861 // Push the present count forward. 1862 assert(forwardCounts[e.value] >= 0); 1863 forwardCounts[e.value] += count; 1864 } 1865 break; 1866 case Attribute.EK_CBLE: 1867 assert(false); 1868 break; 1869 } 1870 } 1871 } 1872 1873 void readByteCodes() throws IOException { 1874 // bc_bands: 1875 // *bc_codes :BYTE1 1876 // *bc_case_count :UNSIGNED5 1877 // *bc_case_value :DELTA5 1878 // *bc_byte :BYTE1 1879 // *bc_short :DELTA5 1880 // *bc_local :UNSIGNED5 1881 // *bc_label :BRANCH5 1882 // *bc_intref :DELTA5 (cp_Int) 1883 // *bc_floatref :DELTA5 (cp_Float) 1884 // *bc_longref :DELTA5 (cp_Long) 1885 // *bc_doubleref :DELTA5 (cp_Double) 1886 // *bc_stringref :DELTA5 (cp_String) 1887 // *bc_classref :UNSIGNED5 (current class or cp_Class) 1888 // *bc_fieldref :DELTA5 (cp_Field) 1889 // *bc_methodref :UNSIGNED5 (cp_Method) 1890 // *bc_imethodref :DELTA5 (cp_Imethod) 1891 // *bc_thisfield :UNSIGNED5 (cp_Field, only for current class) 1892 // *bc_superfield :UNSIGNED5 (cp_Field, only for current super) 1893 // *bc_thismethod :UNSIGNED5 (cp_Method, only for current class) 1894 // *bc_supermethod :UNSIGNED5 (cp_Method, only for current super) 1895 // *bc_initref :UNSIGNED5 (cp_Field, only for most recent new) 1896 // *bc_escref :UNSIGNED5 (cp_All) 1897 // *bc_escrefsize :UNSIGNED5 1898 // *bc_escsize :UNSIGNED5 1899 // *bc_escbyte :BYTE1 1900 bc_codes.elementCountForDebug = allCodes.length; 1901 bc_codes.setInputStreamFrom(in); 1902 readByteCodeOps(); // reads from bc_codes and bc_case_count 1903 bc_codes.doneDisbursing(); 1904 1905 // All the operand bands have now been sized. Read them all in turn. 1906 Band[] operand_bands = { 1907 bc_case_value, 1908 bc_byte, bc_short, 1909 bc_local, bc_label, 1910 bc_intref, bc_floatref, 1911 bc_longref, bc_doubleref, bc_stringref, 1912 bc_loadablevalueref, 1913 bc_classref, bc_fieldref, 1914 bc_methodref, bc_imethodref, 1915 bc_indyref, 1916 bc_thisfield, bc_superfield, 1917 bc_thismethod, bc_supermethod, 1918 bc_initref, 1919 bc_escref, bc_escrefsize, bc_escsize 1920 }; 1921 for (int i = 0; i < operand_bands.length; i++) { 1922 operand_bands[i].readFrom(in); 1923 } 1924 bc_escbyte.expectLength(bc_escsize.getIntTotal()); 1925 bc_escbyte.readFrom(in); 1926 1927 expandByteCodeOps(); 1928 1929 // Done fetching values from operand bands: 1930 bc_case_count.doneDisbursing(); 1931 for (int i = 0; i < operand_bands.length; i++) { 1932 operand_bands[i].doneDisbursing(); 1933 } 1934 bc_escbyte.doneDisbursing(); 1935 bc_bands.doneDisbursing(); 1936 1937 // We must delay the parsing of Code attributes until we 1938 // have a complete model of bytecodes, for BCI encodings. 1939 readAttrs(ATTR_CONTEXT_CODE, codesWithFlags); 1940 // Ditto for exception handlers in codes. 1941 fixupCodeHandlers(); 1942 // Now we can finish with class_bands; cf. readClasses(). 1943 code_bands.doneDisbursing(); 1944 class_bands.doneDisbursing(); 1945 } 1946 1947 private void readByteCodeOps() throws IOException { 1948 // scratch buffer for collecting code:: 1949 byte[] buf = new byte[1<<12]; 1950 // record of all switch opcodes (these are variable-length) 1951 List<Integer> allSwitchOps = new ArrayList<>(); 1952 for (int k = 0; k < allCodes.length; k++) { 1953 Code c = allCodes[k]; 1954 scanOneMethod: 1955 for (int i = 0; ; i++) { 1956 int bc = bc_codes.getByte(); 1957 if (i + 10 > buf.length) buf = realloc(buf); 1958 buf[i] = (byte)bc; 1959 boolean isWide = false; 1960 if (bc == _wide) { 1961 bc = bc_codes.getByte(); 1962 buf[++i] = (byte)bc; 1963 isWide = true; 1964 } 1965 assert(bc == (0xFF & bc)); 1966 // Adjust expectations of various band sizes. 1967 switch (bc) { 1968 case _tableswitch: 1969 case _lookupswitch: 1970 bc_case_count.expectMoreLength(1); 1971 allSwitchOps.add(bc); 1972 break; 1973 case _iinc: 1974 bc_local.expectMoreLength(1); 1975 if (isWide) 1976 bc_short.expectMoreLength(1); 1977 else 1978 bc_byte.expectMoreLength(1); 1979 break; 1980 case _sipush: 1981 bc_short.expectMoreLength(1); 1982 break; 1983 case _bipush: 1984 bc_byte.expectMoreLength(1); 1985 break; 1986 case _newarray: 1987 bc_byte.expectMoreLength(1); 1988 break; 1989 case _multianewarray: 1990 assert(getCPRefOpBand(bc) == bc_classref); 1991 bc_classref.expectMoreLength(1); 1992 bc_byte.expectMoreLength(1); 1993 break; 1994 case _ref_escape: 1995 bc_escrefsize.expectMoreLength(1); 1996 bc_escref.expectMoreLength(1); 1997 break; 1998 case _byte_escape: 1999 bc_escsize.expectMoreLength(1); 2000 // bc_escbyte will have to be counted too 2001 break; 2002 default: 2003 if (Instruction.isInvokeInitOp(bc)) { 2004 bc_initref.expectMoreLength(1); 2005 break; 2006 } 2007 if (Instruction.isSelfLinkerOp(bc)) { 2008 CPRefBand bc_which = selfOpRefBand(bc); 2009 bc_which.expectMoreLength(1); 2010 break; 2011 } 2012 if (Instruction.isBranchOp(bc)) { 2013 bc_label.expectMoreLength(1); 2014 break; 2015 } 2016 if (Instruction.isCPRefOp(bc)) { 2017 CPRefBand bc_which = getCPRefOpBand(bc); 2018 bc_which.expectMoreLength(1); 2019 assert(bc != _multianewarray); // handled elsewhere 2020 break; 2021 } 2022 if (Instruction.isLocalSlotOp(bc)) { 2023 bc_local.expectMoreLength(1); 2024 break; 2025 } 2026 break; 2027 case _end_marker: 2028 { 2029 // Transfer from buf to a more permanent place: 2030 c.bytes = realloc(buf, i); 2031 break scanOneMethod; 2032 } 2033 } 2034 } 2035 } 2036 2037 // To size instruction bands correctly, we need info on switches: 2038 bc_case_count.readFrom(in); 2039 for (Integer i : allSwitchOps) { 2040 int bc = i.intValue(); 2041 int caseCount = bc_case_count.getInt(); 2042 bc_label.expectMoreLength(1+caseCount); // default label + cases 2043 bc_case_value.expectMoreLength(bc == _tableswitch ? 1 : caseCount); 2044 } 2045 bc_case_count.resetForSecondPass(); 2046 } 2047 2048 private void expandByteCodeOps() throws IOException { 2049 // scratch buffer for collecting code: 2050 byte[] buf = new byte[1<<12]; 2051 // scratch buffer for collecting instruction boundaries: 2052 int[] insnMap = new int[1<<12]; 2053 // list of label carriers, for label decoding post-pass: 2054 int[] labels = new int[1<<10]; 2055 // scratch buffer for registering CP refs: 2056 Fixups fixupBuf = new Fixups(); 2057 2058 for (int k = 0; k < allCodes.length; k++) { 2059 Code code = allCodes[k]; 2060 byte[] codeOps = code.bytes; 2061 code.bytes = null; // just for now, while we accumulate bits 2062 2063 Class curClass = code.thisClass(); 2064 2065 Set<Entry> ldcRefSet = ldcRefMap.get(curClass); 2066 if (ldcRefSet == null) 2067 ldcRefMap.put(curClass, ldcRefSet = new HashSet<>()); 2068 2069 ClassEntry thisClass = curClass.thisClass; 2070 ClassEntry superClass = curClass.superClass; 2071 ClassEntry newClass = null; // class of last _new opcode 2072 2073 int pc = 0; // fill pointer in buf; actual bytecode PC 2074 int numInsns = 0; 2075 int numLabels = 0; 2076 boolean hasEscs = false; 2077 fixupBuf.clear(); 2078 for (int i = 0; i < codeOps.length; i++) { 2079 int bc = Instruction.getByte(codeOps, i); 2080 int curPC = pc; 2081 insnMap[numInsns++] = curPC; 2082 if (pc + 10 > buf.length) buf = realloc(buf); 2083 if (numInsns+10 > insnMap.length) insnMap = realloc(insnMap); 2084 if (numLabels+10 > labels.length) labels = realloc(labels); 2085 boolean isWide = false; 2086 if (bc == _wide) { 2087 buf[pc++] = (byte) bc; 2088 bc = Instruction.getByte(codeOps, ++i); 2089 isWide = true; 2090 } 2091 switch (bc) { 2092 case _tableswitch: // apc: (df, lo, hi, (hi-lo+1)*(label)) 2093 case _lookupswitch: // apc: (df, nc, nc*(case, label)) 2094 { 2095 int caseCount = bc_case_count.getInt(); 2096 while ((pc + 30 + caseCount*8) > buf.length) 2097 buf = realloc(buf); 2098 buf[pc++] = (byte) bc; 2099 //initialize apc, df, lo, hi bytes to reasonable bits: 2100 Arrays.fill(buf, pc, pc+30, (byte)0); 2101 Instruction.Switch isw = (Instruction.Switch) 2102 Instruction.at(buf, curPC); 2103 //isw.setDefaultLabel(getLabel(bc_label, code, curPC)); 2104 isw.setCaseCount(caseCount); 2105 if (bc == _tableswitch) { 2106 isw.setCaseValue(0, bc_case_value.getInt()); 2107 } else { 2108 for (int j = 0; j < caseCount; j++) { 2109 isw.setCaseValue(j, bc_case_value.getInt()); 2110 } 2111 } 2112 // Make our getLabel calls later. 2113 labels[numLabels++] = curPC; 2114 pc = isw.getNextPC(); 2115 continue; 2116 } 2117 case _iinc: 2118 { 2119 buf[pc++] = (byte) bc; 2120 int local = bc_local.getInt(); 2121 int delta; 2122 if (isWide) { 2123 delta = bc_short.getInt(); 2124 Instruction.setShort(buf, pc, local); pc += 2; 2125 Instruction.setShort(buf, pc, delta); pc += 2; 2126 } else { 2127 delta = (byte) bc_byte.getByte(); 2128 buf[pc++] = (byte)local; 2129 buf[pc++] = (byte)delta; 2130 } 2131 continue; 2132 } 2133 case _sipush: 2134 { 2135 int val = bc_short.getInt(); 2136 buf[pc++] = (byte) bc; 2137 Instruction.setShort(buf, pc, val); pc += 2; 2138 continue; 2139 } 2140 case _bipush: 2141 case _newarray: 2142 { 2143 int val = bc_byte.getByte(); 2144 buf[pc++] = (byte) bc; 2145 buf[pc++] = (byte) val; 2146 continue; 2147 } 2148 case _ref_escape: 2149 { 2150 // Note that insnMap has one entry for this. 2151 hasEscs = true; 2152 int size = bc_escrefsize.getInt(); 2153 Entry ref = bc_escref.getRef(); 2154 if (size == 1) ldcRefSet.add(ref); 2155 int fmt; 2156 switch (size) { 2157 case 1: fmt = Fixups.U1_FORMAT; break; 2158 case 2: fmt = Fixups.U2_FORMAT; break; 2159 default: assert(false); fmt = 0; 2160 } 2161 fixupBuf.add(pc, fmt, ref); 2162 buf[pc+0] = buf[pc+1] = 0; 2163 pc += size; 2164 } 2165 continue; 2166 case _byte_escape: 2167 { 2168 // Note that insnMap has one entry for all these bytes. 2169 hasEscs = true; 2170 int size = bc_escsize.getInt(); 2171 while ((pc + size) > buf.length) 2172 buf = realloc(buf); 2173 while (size-- > 0) { 2174 buf[pc++] = (byte) bc_escbyte.getByte(); 2175 } 2176 } 2177 continue; 2178 default: 2179 if (Instruction.isInvokeInitOp(bc)) { 2180 int idx = (bc - _invokeinit_op); 2181 int origBC = _invokespecial; 2182 ClassEntry classRef; 2183 switch (idx) { 2184 case _invokeinit_self_option: 2185 classRef = thisClass; break; 2186 case _invokeinit_super_option: 2187 classRef = superClass; break; 2188 default: 2189 assert(idx == _invokeinit_new_option); 2190 classRef = newClass; break; 2191 } 2192 buf[pc++] = (byte) origBC; 2193 int coding = bc_initref.getInt(); 2194 // Find the nth overloading of <init> in classRef. 2195 MemberEntry ref = pkg.cp.getOverloadingForIndex(CONSTANT_Methodref, classRef, "<init>", coding); 2196 fixupBuf.add(pc, Fixups.U2_FORMAT, ref); 2197 buf[pc+0] = buf[pc+1] = 0; 2198 pc += 2; 2199 assert(Instruction.opLength(origBC) == (pc - curPC)); 2200 continue; 2201 } 2202 if (Instruction.isSelfLinkerOp(bc)) { 2203 int idx = (bc - _self_linker_op); 2204 boolean isSuper = (idx >= _self_linker_super_flag); 2205 if (isSuper) idx -= _self_linker_super_flag; 2206 boolean isAload = (idx >= _self_linker_aload_flag); 2207 if (isAload) idx -= _self_linker_aload_flag; 2208 int origBC = _first_linker_op + idx; 2209 boolean isField = Instruction.isFieldOp(origBC); 2210 CPRefBand bc_which; 2211 ClassEntry which_cls = isSuper ? superClass : thisClass; 2212 Index which_ix; 2213 if (isField) { 2214 bc_which = isSuper ? bc_superfield : bc_thisfield; 2215 which_ix = pkg.cp.getMemberIndex(CONSTANT_Fieldref, which_cls); 2216 } else { 2217 bc_which = isSuper ? bc_supermethod : bc_thismethod; 2218 which_ix = pkg.cp.getMemberIndex(CONSTANT_Methodref, which_cls); 2219 } 2220 assert(bc_which == selfOpRefBand(bc)); 2221 MemberEntry ref = (MemberEntry) bc_which.getRef(which_ix); 2222 if (isAload) { 2223 buf[pc++] = (byte) _aload_0; 2224 curPC = pc; 2225 // Note: insnMap keeps the _aload_0 separate. 2226 insnMap[numInsns++] = curPC; 2227 } 2228 buf[pc++] = (byte) origBC; 2229 fixupBuf.add(pc, Fixups.U2_FORMAT, ref); 2230 buf[pc+0] = buf[pc+1] = 0; 2231 pc += 2; 2232 assert(Instruction.opLength(origBC) == (pc - curPC)); 2233 continue; 2234 } 2235 if (Instruction.isBranchOp(bc)) { 2236 buf[pc++] = (byte) bc; 2237 assert(!isWide); // no wide prefix for branches 2238 int nextPC = curPC + Instruction.opLength(bc); 2239 // Make our getLabel calls later. 2240 labels[numLabels++] = curPC; 2241 //Instruction.at(buf, curPC).setBranchLabel(getLabel(bc_label, code, curPC)); 2242 while (pc < nextPC) buf[pc++] = 0; 2243 continue; 2244 } 2245 if (Instruction.isCPRefOp(bc)) { 2246 CPRefBand bc_which = getCPRefOpBand(bc); 2247 Entry ref = bc_which.getRef(); 2248 if (ref == null) { 2249 if (bc_which == bc_classref) { 2250 // Shorthand for class self-references. 2251 ref = thisClass; 2252 } else { 2253 assert(false); 2254 } 2255 } 2256 int origBC = bc; 2257 int size = 2; 2258 switch (bc) { 2259 case _invokestatic_int: 2260 origBC = _invokestatic; 2261 break; 2262 case _invokespecial_int: 2263 origBC = _invokespecial; 2264 break; 2265 case _ildc: 2266 case _cldc: 2267 case _fldc: 2268 case _sldc: 2269 case _qldc: 2270 origBC = _ldc; 2271 size = 1; 2272 ldcRefSet.add(ref); 2273 break; 2274 case _ildc_w: 2275 case _cldc_w: 2276 case _fldc_w: 2277 case _sldc_w: 2278 case _qldc_w: 2279 origBC = _ldc_w; 2280 break; 2281 case _lldc2_w: 2282 case _dldc2_w: 2283 origBC = _ldc2_w; 2284 break; 2285 case _new: 2286 newClass = (ClassEntry) ref; 2287 break; 2288 } 2289 buf[pc++] = (byte) origBC; 2290 int fmt; 2291 switch (size) { 2292 case 1: fmt = Fixups.U1_FORMAT; break; 2293 case 2: fmt = Fixups.U2_FORMAT; break; 2294 default: assert(false); fmt = 0; 2295 } 2296 fixupBuf.add(pc, fmt, ref); 2297 buf[pc+0] = buf[pc+1] = 0; 2298 pc += size; 2299 if (origBC == _multianewarray) { 2300 // Copy the trailing byte also. 2301 int val = bc_byte.getByte(); 2302 buf[pc++] = (byte) val; 2303 } else if (origBC == _invokeinterface) { 2304 int argSize = ((MemberEntry)ref).descRef.typeRef.computeSize(true); 2305 buf[pc++] = (byte)( 1 + argSize ); 2306 buf[pc++] = 0; 2307 } else if (origBC == _invokedynamic) { 2308 buf[pc++] = 0; 2309 buf[pc++] = 0; 2310 } 2311 assert(Instruction.opLength(origBC) == (pc - curPC)); 2312 continue; 2313 } 2314 if (Instruction.isLocalSlotOp(bc)) { 2315 buf[pc++] = (byte) bc; 2316 int local = bc_local.getInt(); 2317 if (isWide) { 2318 Instruction.setShort(buf, pc, local); 2319 pc += 2; 2320 if (bc == _iinc) { 2321 int iVal = bc_short.getInt(); 2322 Instruction.setShort(buf, pc, iVal); 2323 pc += 2; 2324 } 2325 } else { 2326 Instruction.setByte(buf, pc, local); 2327 pc += 1; 2328 if (bc == _iinc) { 2329 int iVal = bc_byte.getByte(); 2330 Instruction.setByte(buf, pc, iVal); 2331 pc += 1; 2332 } 2333 } 2334 assert(Instruction.opLength(bc) == (pc - curPC)); 2335 continue; 2336 } 2337 // Random bytecode. Just copy it. 2338 if (bc >= _bytecode_limit) 2339 Utils.log.warning("unrecognized bytescode "+bc 2340 +" "+Instruction.byteName(bc)); 2341 assert(bc < _bytecode_limit); 2342 buf[pc++] = (byte) bc; 2343 assert(Instruction.opLength(bc) == (pc - curPC)); 2344 continue; 2345 } 2346 } 2347 // now make a permanent copy of the bytecodes 2348 code.setBytes(realloc(buf, pc)); 2349 code.setInstructionMap(insnMap, numInsns); 2350 // fix up labels, now that code has its insnMap 2351 Instruction ibr = null; // temporary branch instruction 2352 for (int i = 0; i < numLabels; i++) { 2353 int curPC = labels[i]; 2354 // (Note: Passing ibr in allows reuse, a speed hack.) 2355 ibr = Instruction.at(code.bytes, curPC, ibr); 2356 if (ibr instanceof Instruction.Switch) { 2357 Instruction.Switch isw = (Instruction.Switch) ibr; 2358 isw.setDefaultLabel(getLabel(bc_label, code, curPC)); 2359 int caseCount = isw.getCaseCount(); 2360 for (int j = 0; j < caseCount; j++) { 2361 isw.setCaseLabel(j, getLabel(bc_label, code, curPC)); 2362 } 2363 } else { 2364 ibr.setBranchLabel(getLabel(bc_label, code, curPC)); 2365 } 2366 } 2367 if (fixupBuf.size() > 0) { 2368 if (verbose > 2) 2369 Utils.log.fine("Fixups in code: "+fixupBuf); 2370 code.addFixups(fixupBuf); 2371 } 2372 } 2373 } 2374 }