1 /* 2 * Copyright (c) 2001, 2010, 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.Entry; 29 import com.sun.java.util.jar.pack.ConstantPool.Index; 30 import com.sun.java.util.jar.pack.Package.Class.Field; 31 import java.io.BufferedOutputStream; 32 import java.io.ByteArrayInputStream; 33 import java.io.ByteArrayOutputStream; 34 import java.io.EOFException; 35 import java.io.File; 36 import java.io.FileOutputStream; 37 import java.io.FilterInputStream; 38 import java.io.FilterOutputStream; 39 import java.io.IOException; 40 import java.io.InputStream; 41 import java.io.OutputStream; 42 import java.io.PrintStream; 43 import java.util.ArrayList; 44 import java.util.Arrays; 45 import java.util.Collections; 46 import java.util.HashMap; 47 import java.util.List; 48 import java.util.Map; 49 import java.util.jar.Pack200; 50 import static com.sun.java.util.jar.pack.Constants.*; 51 52 /** 53 * Define the structure and ordering of "bands" in a packed file. 54 * @author John Rose 55 */ 56 abstract 57 class BandStructure { 58 static final int MAX_EFFORT = 9; 59 static final int MIN_EFFORT = 1; 60 static final int DEFAULT_EFFORT = 5; 61 62 // Inherit options from Pack200: 63 PropMap p200 = Utils.currentPropMap(); 64 65 int verbose = p200.getInteger(Utils.DEBUG_VERBOSE); 66 int effort = p200.getInteger(Pack200.Packer.EFFORT); 67 { if (effort == 0) effort = DEFAULT_EFFORT; } 68 boolean optDumpBands = p200.getBoolean(Utils.COM_PREFIX+"dump.bands"); 69 boolean optDebugBands = p200.getBoolean(Utils.COM_PREFIX+"debug.bands"); 70 71 // Various heuristic options. 72 boolean optVaryCodings = !p200.getBoolean(Utils.COM_PREFIX+"no.vary.codings"); 73 boolean optBigStrings = !p200.getBoolean(Utils.COM_PREFIX+"no.big.strings"); 74 75 abstract protected Index getCPIndex(byte tag); 76 77 // Local copy of package version. 78 private int packageMajver = -1; 79 80 /** Call this exactly once, early, to specify the archive major version. */ 81 public void initPackageMajver(int packageMajver) throws IOException { 82 assert(packageMajver > 0 && packageMajver < 0x10000); 83 if (this.packageMajver > 0) { 84 throw new IOException( 85 "Package majver is already initialized to " + this.packageMajver+ 86 "; new setting is " + packageMajver); 87 } 88 this.packageMajver = packageMajver; 89 adjustToMajver(); 90 } 91 public int getPackageMajver() { 92 if (packageMajver < 0) { 93 throw new RuntimeException("Package majver not yet initialized"); 94 } 95 return packageMajver; 96 } 97 98 private final boolean isReader = this instanceof PackageReader; 99 protected BandStructure() { 100 } 101 102 final static Coding BYTE1 = Coding.of(1,256); 103 104 final static Coding CHAR3 = Coding.of(3,128); 105 // Note: Tried sharper (3,16) with no post-zip benefit. 106 107 // This is best used with BCI values: 108 final static Coding BCI5 = Coding.of(5,4); // mostly 1-byte offsets 109 final static Coding BRANCH5 = Coding.of(5,4,2); // mostly forward branches 110 111 final static Coding UNSIGNED5 = Coding.of(5,64); 112 final static Coding UDELTA5 = UNSIGNED5.getDeltaCoding(); 113 // "sharp" (5,64) zips 0.4% better than "medium" (5,128) 114 // It zips 1.1% better than "flat" (5,192) 115 116 final static Coding SIGNED5 = Coding.of(5,64,1); //sharp 117 final static Coding DELTA5 = SIGNED5.getDeltaCoding(); 118 // Note: Tried (5,128,2) and (5,192,2) with no benefit. 119 120 final static Coding MDELTA5 = Coding.of(5,64,2).getDeltaCoding(); 121 122 final private static Coding[] basicCodings = { 123 // Table of "Canonical BHSD Codings" from Pack200 spec. 124 null, // _meta_default 125 126 // Fixed-length codings: 127 Coding.of(1,256,0), 128 Coding.of(1,256,1), 129 Coding.of(1,256,0).getDeltaCoding(), 130 Coding.of(1,256,1).getDeltaCoding(), 131 Coding.of(2,256,0), 132 Coding.of(2,256,1), 133 Coding.of(2,256,0).getDeltaCoding(), 134 Coding.of(2,256,1).getDeltaCoding(), 135 Coding.of(3,256,0), 136 Coding.of(3,256,1), 137 Coding.of(3,256,0).getDeltaCoding(), 138 Coding.of(3,256,1).getDeltaCoding(), 139 Coding.of(4,256,0), 140 Coding.of(4,256,1), 141 Coding.of(4,256,0).getDeltaCoding(), 142 Coding.of(4,256,1).getDeltaCoding(), 143 144 // Full-range variable-length codings: 145 Coding.of(5, 4,0), 146 Coding.of(5, 4,1), 147 Coding.of(5, 4,2), 148 Coding.of(5, 16,0), 149 Coding.of(5, 16,1), 150 Coding.of(5, 16,2), 151 Coding.of(5, 32,0), 152 Coding.of(5, 32,1), 153 Coding.of(5, 32,2), 154 Coding.of(5, 64,0), 155 Coding.of(5, 64,1), 156 Coding.of(5, 64,2), 157 Coding.of(5,128,0), 158 Coding.of(5,128,1), 159 Coding.of(5,128,2), 160 161 Coding.of(5, 4,0).getDeltaCoding(), 162 Coding.of(5, 4,1).getDeltaCoding(), 163 Coding.of(5, 4,2).getDeltaCoding(), 164 Coding.of(5, 16,0).getDeltaCoding(), 165 Coding.of(5, 16,1).getDeltaCoding(), 166 Coding.of(5, 16,2).getDeltaCoding(), 167 Coding.of(5, 32,0).getDeltaCoding(), 168 Coding.of(5, 32,1).getDeltaCoding(), 169 Coding.of(5, 32,2).getDeltaCoding(), 170 Coding.of(5, 64,0).getDeltaCoding(), 171 Coding.of(5, 64,1).getDeltaCoding(), 172 Coding.of(5, 64,2).getDeltaCoding(), 173 Coding.of(5,128,0).getDeltaCoding(), 174 Coding.of(5,128,1).getDeltaCoding(), 175 Coding.of(5,128,2).getDeltaCoding(), 176 177 // Variable length subrange codings: 178 Coding.of(2,192,0), 179 Coding.of(2,224,0), 180 Coding.of(2,240,0), 181 Coding.of(2,248,0), 182 Coding.of(2,252,0), 183 184 Coding.of(2, 8,0).getDeltaCoding(), 185 Coding.of(2, 8,1).getDeltaCoding(), 186 Coding.of(2, 16,0).getDeltaCoding(), 187 Coding.of(2, 16,1).getDeltaCoding(), 188 Coding.of(2, 32,0).getDeltaCoding(), 189 Coding.of(2, 32,1).getDeltaCoding(), 190 Coding.of(2, 64,0).getDeltaCoding(), 191 Coding.of(2, 64,1).getDeltaCoding(), 192 Coding.of(2,128,0).getDeltaCoding(), 193 Coding.of(2,128,1).getDeltaCoding(), 194 Coding.of(2,192,0).getDeltaCoding(), 195 Coding.of(2,192,1).getDeltaCoding(), 196 Coding.of(2,224,0).getDeltaCoding(), 197 Coding.of(2,224,1).getDeltaCoding(), 198 Coding.of(2,240,0).getDeltaCoding(), 199 Coding.of(2,240,1).getDeltaCoding(), 200 Coding.of(2,248,0).getDeltaCoding(), 201 Coding.of(2,248,1).getDeltaCoding(), 202 203 Coding.of(3,192,0), 204 Coding.of(3,224,0), 205 Coding.of(3,240,0), 206 Coding.of(3,248,0), 207 Coding.of(3,252,0), 208 209 Coding.of(3, 8,0).getDeltaCoding(), 210 Coding.of(3, 8,1).getDeltaCoding(), 211 Coding.of(3, 16,0).getDeltaCoding(), 212 Coding.of(3, 16,1).getDeltaCoding(), 213 Coding.of(3, 32,0).getDeltaCoding(), 214 Coding.of(3, 32,1).getDeltaCoding(), 215 Coding.of(3, 64,0).getDeltaCoding(), 216 Coding.of(3, 64,1).getDeltaCoding(), 217 Coding.of(3,128,0).getDeltaCoding(), 218 Coding.of(3,128,1).getDeltaCoding(), 219 Coding.of(3,192,0).getDeltaCoding(), 220 Coding.of(3,192,1).getDeltaCoding(), 221 Coding.of(3,224,0).getDeltaCoding(), 222 Coding.of(3,224,1).getDeltaCoding(), 223 Coding.of(3,240,0).getDeltaCoding(), 224 Coding.of(3,240,1).getDeltaCoding(), 225 Coding.of(3,248,0).getDeltaCoding(), 226 Coding.of(3,248,1).getDeltaCoding(), 227 228 Coding.of(4,192,0), 229 Coding.of(4,224,0), 230 Coding.of(4,240,0), 231 Coding.of(4,248,0), 232 Coding.of(4,252,0), 233 234 Coding.of(4, 8,0).getDeltaCoding(), 235 Coding.of(4, 8,1).getDeltaCoding(), 236 Coding.of(4, 16,0).getDeltaCoding(), 237 Coding.of(4, 16,1).getDeltaCoding(), 238 Coding.of(4, 32,0).getDeltaCoding(), 239 Coding.of(4, 32,1).getDeltaCoding(), 240 Coding.of(4, 64,0).getDeltaCoding(), 241 Coding.of(4, 64,1).getDeltaCoding(), 242 Coding.of(4,128,0).getDeltaCoding(), 243 Coding.of(4,128,1).getDeltaCoding(), 244 Coding.of(4,192,0).getDeltaCoding(), 245 Coding.of(4,192,1).getDeltaCoding(), 246 Coding.of(4,224,0).getDeltaCoding(), 247 Coding.of(4,224,1).getDeltaCoding(), 248 Coding.of(4,240,0).getDeltaCoding(), 249 Coding.of(4,240,1).getDeltaCoding(), 250 Coding.of(4,248,0).getDeltaCoding(), 251 Coding.of(4,248,1).getDeltaCoding(), 252 253 null 254 }; 255 final private static Map<Coding, Integer> basicCodingIndexes; 256 static { 257 assert(basicCodings[_meta_default] == null); 258 assert(basicCodings[_meta_canon_min] != null); 259 assert(basicCodings[_meta_canon_max] != null); 260 Map<Coding, Integer> map = new HashMap<>(); 261 for (int i = 0; i < basicCodings.length; i++) { 262 Coding c = basicCodings[i]; 263 if (c == null) continue; 264 assert(i >= _meta_canon_min); 265 assert(i <= _meta_canon_max); 266 map.put(c, i); 267 } 268 basicCodingIndexes = map; 269 } 270 public static Coding codingForIndex(int i) { 271 return i < basicCodings.length ? basicCodings[i] : null; 272 } 273 public static int indexOf(Coding c) { 274 Integer i = basicCodingIndexes.get(c); 275 if (i == null) return 0; 276 return i.intValue(); 277 } 278 public static Coding[] getBasicCodings() { 279 return basicCodings.clone(); 280 } 281 282 protected byte[] bandHeaderBytes; // used for input only 283 protected int bandHeaderBytePos; // BHB read pointer, for input only 284 protected int bandHeaderBytePos0; // for debug 285 286 protected CodingMethod getBandHeader(int XB, Coding regularCoding) { 287 CodingMethod[] res = {null}; 288 // push back XB onto the band header bytes 289 bandHeaderBytes[--bandHeaderBytePos] = (byte) XB; 290 bandHeaderBytePos0 = bandHeaderBytePos; 291 // scan forward through XB and any additional band header bytes 292 bandHeaderBytePos = parseMetaCoding(bandHeaderBytes, 293 bandHeaderBytePos, 294 regularCoding, 295 res); 296 return res[0]; 297 } 298 299 public static int parseMetaCoding(byte[] bytes, int pos, Coding dflt, CodingMethod[] res) { 300 if ((bytes[pos] & 0xFF) == _meta_default) { 301 res[0] = dflt; 302 return pos+1; 303 } 304 int pos2; 305 pos2 = Coding.parseMetaCoding(bytes, pos, dflt, res); 306 if (pos2 > pos) return pos2; 307 pos2 = PopulationCoding.parseMetaCoding(bytes, pos, dflt, res); 308 if (pos2 > pos) return pos2; 309 pos2 = AdaptiveCoding.parseMetaCoding(bytes, pos, dflt, res); 310 if (pos2 > pos) return pos2; 311 throw new RuntimeException("Bad meta-coding op "+(bytes[pos]&0xFF)); 312 } 313 314 static final int SHORT_BAND_HEURISTIC = 100; 315 316 public static final int NO_PHASE = 0; 317 318 // package writing phases: 319 public static final int COLLECT_PHASE = 1; // collect data before write 320 public static final int FROZEN_PHASE = 3; // no longer collecting 321 public static final int WRITE_PHASE = 5; // ready to write bytes 322 323 // package reading phases: 324 public static final int EXPECT_PHASE = 2; // gather expected counts 325 public static final int READ_PHASE = 4; // ready to read bytes 326 public static final int DISBURSE_PHASE = 6; // pass out data after read 327 328 public static final int DONE_PHASE = 8; // done writing or reading 329 330 static boolean phaseIsRead(int p) { 331 return (p % 2) == 0; 332 } 333 static int phaseCmp(int p0, int p1) { 334 assert((p0 % 2) == (p1 % 2) || (p0 % 8) == 0 || (p1 % 8) == 0); 335 return p0 - p1; 336 } 337 338 /** The packed file is divided up into a number of segments. 339 * Most segments are typed as ValueBand, strongly-typed sequences 340 * of integer values, all interpreted in a single way. 341 * A few segments are ByteBands, which hetergeneous sequences 342 * of bytes. 343 * 344 * The two phases for writing a packed file are COLLECT and WRITE. 345 * 1. When writing a packed file, each band collects 346 * data in an ad-hoc order. 347 * 2. At the end, each band is assigned a coding scheme, 348 * and then all the bands are written in their global order. 349 * 350 * The three phases for reading a packed file are EXPECT, READ, 351 * and DISBURSE. 352 * 1. For each band, the expected number of integers is determined. 353 * 2. The data is actually read from the file into the band. 354 * 3. The band pays out its values as requested, in an ad hoc order. 355 * 356 * When the last phase of a band is done, it is marked so (DONE). 357 * Clearly, these phases must be properly ordered WRT each other. 358 */ 359 abstract class Band { 360 private int phase = NO_PHASE; 361 private final String name; 362 363 private int valuesExpected; 364 365 protected long outputSize = -1; // cache 366 367 final public Coding regularCoding; 368 369 final public int seqForDebug; 370 public int elementCountForDebug; 371 372 373 protected Band(String name, Coding regularCoding) { 374 this.name = name; 375 this.regularCoding = regularCoding; 376 this.seqForDebug = ++nextSeqForDebug; 377 if (verbose > 2) 378 Utils.log.fine("Band "+seqForDebug+" is "+name); 379 // caller must call init 380 } 381 382 public Band init() { 383 // Cannot due this from the constructor, because constructor 384 // may wish to initialize some subclass variables. 385 // Set initial phase for reading or writing: 386 if (isReader) 387 readyToExpect(); 388 else 389 readyToCollect(); 390 return this; 391 } 392 393 // common operations 394 boolean isReader() { return isReader; } 395 int phase() { return phase; } 396 String name() { return name; } 397 398 /** Return -1 if data buffer not allocated, else max length. */ 399 public abstract int capacity(); 400 401 /** Allocate data buffer to specified length. */ 402 protected abstract void setCapacity(int cap); 403 404 /** Return current number of values in buffer, which must exist. */ 405 public abstract int length(); 406 407 protected abstract int valuesRemainingForDebug(); 408 409 public final int valuesExpected() { 410 return valuesExpected; 411 } 412 413 /** Write out bytes, encoding the values. */ 414 public final void writeTo(OutputStream out) throws IOException { 415 assert(assertReadyToWriteTo(this, out)); 416 setPhase(WRITE_PHASE); 417 // subclasses continue by writing their contents to output 418 writeDataTo(out); 419 doneWriting(); 420 } 421 422 abstract void chooseBandCodings() throws IOException; 423 424 public final long outputSize() { 425 if (outputSize >= 0) { 426 long size = outputSize; 427 assert(size == computeOutputSize()); 428 return size; 429 } 430 return computeOutputSize(); 431 } 432 433 protected abstract long computeOutputSize(); 434 435 abstract protected void writeDataTo(OutputStream out) throws IOException; 436 437 /** Expect a certain number of values. */ 438 void expectLength(int l) { 439 assert(assertPhase(this, EXPECT_PHASE)); 440 assert(valuesExpected == 0); // all at once 441 assert(l >= 0); 442 valuesExpected = l; 443 } 444 /** Expect more values. (Multiple calls accumulate.) */ 445 void expectMoreLength(int l) { 446 assert(assertPhase(this, EXPECT_PHASE)); 447 valuesExpected += l; 448 } 449 450 451 /// Phase change markers. 452 453 private void readyToCollect() { // called implicitly by constructor 454 setCapacity(1); 455 setPhase(COLLECT_PHASE); 456 } 457 protected void doneWriting() { 458 assert(assertPhase(this, WRITE_PHASE)); 459 setPhase(DONE_PHASE); 460 } 461 private void readyToExpect() { // called implicitly by constructor 462 setPhase(EXPECT_PHASE); 463 } 464 /** Read in bytes, decoding the values. */ 465 public final void readFrom(InputStream in) throws IOException { 466 assert(assertReadyToReadFrom(this, in)); 467 setCapacity(valuesExpected()); 468 setPhase(READ_PHASE); 469 // subclasses continue by reading their contents from input: 470 readDataFrom(in); 471 readyToDisburse(); 472 } 473 abstract protected void readDataFrom(InputStream in) throws IOException; 474 protected void readyToDisburse() { 475 if (verbose > 1) Utils.log.fine("readyToDisburse "+this); 476 setPhase(DISBURSE_PHASE); 477 } 478 public void doneDisbursing() { 479 assert(assertPhase(this, DISBURSE_PHASE)); 480 setPhase(DONE_PHASE); 481 } 482 public final void doneWithUnusedBand() { 483 if (isReader) { 484 assert(assertPhase(this, EXPECT_PHASE)); 485 assert(valuesExpected() == 0); 486 // Fast forward: 487 setPhase(READ_PHASE); 488 setPhase(DISBURSE_PHASE); 489 setPhase(DONE_PHASE); 490 } else { 491 setPhase(FROZEN_PHASE); 492 } 493 } 494 495 protected void setPhase(int newPhase) { 496 assert(assertPhaseChangeOK(this, phase, newPhase)); 497 this.phase = newPhase; 498 } 499 500 protected int lengthForDebug = -1; // DEBUG ONLY 501 public String toString() { // DEBUG ONLY 502 int length = (lengthForDebug != -1 ? lengthForDebug : length()); 503 String str = name; 504 if (length != 0) 505 str += "[" + length + "]"; 506 if (elementCountForDebug != 0) 507 str += "(" + elementCountForDebug + ")"; 508 return str; 509 } 510 } 511 512 class ValueBand extends Band { 513 private int[] values; // must be null in EXPECT phase 514 private int length; 515 private int valuesDisbursed; 516 517 private CodingMethod bandCoding; 518 private byte[] metaCoding; 519 520 protected ValueBand(String name, Coding regularCoding) { 521 super(name, regularCoding); 522 } 523 524 public int capacity() { 525 return values == null ? -1 : values.length; 526 } 527 528 /** Declare predicted or needed capacity. */ 529 protected void setCapacity(int cap) { 530 assert(length <= cap); 531 if (cap == -1) { values = null; return; } 532 values = realloc(values, cap); 533 } 534 535 public int length() { 536 return length; 537 } 538 protected int valuesRemainingForDebug() { 539 return length - valuesDisbursed; 540 } 541 protected int valueAtForDebug(int i) { 542 return values[i]; 543 } 544 545 void patchValue(int i, int value) { 546 // Only one use for this. 547 assert(this == archive_header_S); 548 assert(i == AH_ARCHIVE_SIZE_HI || i == AH_ARCHIVE_SIZE_LO); 549 assert(i < length); // must have already output a dummy 550 values[i] = value; 551 outputSize = -1; // decache 552 } 553 554 protected void initializeValues(int[] values) { 555 assert(assertCanChangeLength(this)); 556 assert(length == 0); 557 this.values = values; 558 this.length = values.length; 559 } 560 561 /** Collect one value, or store one decoded value. */ 562 protected void addValue(int x) { 563 assert(assertCanChangeLength(this)); 564 if (length == values.length) 565 setCapacity(length < 1000 ? length * 10 : length * 2); 566 values[length++] = x; 567 } 568 569 private boolean canVaryCoding() { 570 if (!optVaryCodings) return false; 571 if (length == 0) return false; 572 // Can't read band_headers w/o the archive header: 573 if (this == archive_header_0) return false; 574 if (this == archive_header_S) return false; 575 if (this == archive_header_1) return false; 576 // BYTE1 bands can't vary codings, but the others can. 577 // All that's needed for the initial escape is at least 578 // 256 negative values or more than 256 non-negative values 579 return (regularCoding.min() <= -256 || regularCoding.max() >= 256); 580 } 581 582 private boolean shouldVaryCoding() { 583 assert(canVaryCoding()); 584 if (effort < MAX_EFFORT && length < SHORT_BAND_HEURISTIC) 585 return false; 586 return true; 587 } 588 589 protected void chooseBandCodings() throws IOException { 590 boolean canVary = canVaryCoding(); 591 if (!canVary || !shouldVaryCoding()) { 592 if (regularCoding.canRepresent(values, 0, length)) { 593 bandCoding = regularCoding; 594 } else { 595 assert(canVary); 596 if (verbose > 1) 597 Utils.log.fine("regular coding fails in band "+name()); 598 bandCoding = UNSIGNED5; 599 } 600 outputSize = -1; 601 } else { 602 int[] sizes = {0,0}; 603 bandCoding = chooseCoding(values, 0, length, 604 regularCoding, name(), 605 sizes); 606 outputSize = sizes[CodingChooser.BYTE_SIZE]; 607 if (outputSize == 0) // CodingChooser failed to size it. 608 outputSize = -1; 609 } 610 611 // Compute and save the meta-coding bytes also. 612 if (bandCoding != regularCoding) { 613 metaCoding = bandCoding.getMetaCoding(regularCoding); 614 if (verbose > 1) { 615 Utils.log.fine("alternate coding "+this+" "+bandCoding); 616 } 617 } else if (canVary && 618 decodeEscapeValue(values[0], regularCoding) >= 0) { 619 // Need an explicit default. 620 metaCoding = defaultMetaCoding; 621 } else { 622 // Common case: Zero bytes of meta coding. 623 metaCoding = noMetaCoding; 624 } 625 if (metaCoding.length > 0 626 && (verbose > 2 || verbose > 1 && metaCoding.length > 1)) { 627 StringBuffer sb = new StringBuffer(); 628 for (int i = 0; i < metaCoding.length; i++) { 629 if (i == 1) sb.append(" /"); 630 sb.append(" ").append(metaCoding[i] & 0xFF); 631 } 632 Utils.log.fine(" meta-coding "+sb); 633 } 634 635 assert((outputSize < 0) || 636 !(bandCoding instanceof Coding) || 637 (outputSize == ((Coding)bandCoding) 638 .getLength(values, 0, length))) 639 : (bandCoding+" : "+ 640 outputSize+" != "+ 641 ((Coding)bandCoding).getLength(values, 0, length) 642 +" ?= "+getCodingChooser().computeByteSize(bandCoding,values,0,length) 643 ); 644 645 // Compute outputSize of the escape value X, if any. 646 if (metaCoding.length > 0) { 647 // First byte XB of meta-coding is treated specially, 648 // but any other bytes go into the band headers band. 649 // This must be done before any other output happens. 650 if (outputSize >= 0) 651 outputSize += computeEscapeSize(); // good cache 652 // Other bytes go into band_headers. 653 for (int i = 1; i < metaCoding.length; i++) { 654 band_headers.putByte(metaCoding[i] & 0xFF); 655 } 656 } 657 } 658 659 protected long computeOutputSize() { 660 outputSize = getCodingChooser().computeByteSize(bandCoding, 661 values, 0, length); 662 assert(outputSize < Integer.MAX_VALUE); 663 outputSize += computeEscapeSize(); 664 return outputSize; 665 } 666 667 protected int computeEscapeSize() { 668 if (metaCoding.length == 0) return 0; 669 int XB = metaCoding[0] & 0xFF; 670 int X = encodeEscapeValue(XB, regularCoding); 671 return regularCoding.setD(0).getLength(X); 672 } 673 674 protected void writeDataTo(OutputStream out) throws IOException { 675 if (length == 0) return; // nothing to write 676 long len0 = 0; 677 if (out == outputCounter) { 678 len0 = outputCounter.getCount(); 679 } 680 if (metaCoding.length > 0) { 681 int XB = metaCoding[0] & 0xFF; 682 // We need an explicit band header, either because 683 // there is a non-default coding method, or because 684 // the first value would be parsed as an escape value. 685 int X = encodeEscapeValue(XB, regularCoding); 686 //System.out.println("X="+X+" XB="+XB+" in "+this); 687 regularCoding.setD(0).writeTo(out, X); 688 } 689 bandCoding.writeArrayTo(out, values, 0, length); 690 if (out == outputCounter) { 691 assert(outputSize == outputCounter.getCount() - len0) 692 : (outputSize+" != "+outputCounter.getCount()+"-"+len0); 693 } 694 if (optDumpBands) dumpBand(); 695 } 696 697 protected void readDataFrom(InputStream in) throws IOException { 698 length = valuesExpected(); 699 if (length == 0) return; // nothing to read 700 if (verbose > 1) 701 Utils.log.fine("Reading band "+this); 702 if (!canVaryCoding()) { 703 bandCoding = regularCoding; 704 metaCoding = noMetaCoding; 705 } else { 706 assert(in.markSupported()); // input must be buffered 707 in.mark(Coding.B_MAX); 708 int X = regularCoding.setD(0).readFrom(in); 709 int XB = decodeEscapeValue(X, regularCoding); 710 if (XB < 0) { 711 // Do not consume this value. No alternate coding. 712 in.reset(); 713 XB = _meta_default; 714 bandCoding = regularCoding; 715 metaCoding = noMetaCoding; 716 } else if (XB == _meta_default) { 717 bandCoding = regularCoding; 718 metaCoding = defaultMetaCoding; 719 } else { 720 if (verbose > 2) 721 Utils.log.fine("found X="+X+" => XB="+XB); 722 bandCoding = getBandHeader(XB, regularCoding); 723 // This is really used only by dumpBands. 724 int p0 = bandHeaderBytePos0; 725 int p1 = bandHeaderBytePos; 726 metaCoding = new byte[p1-p0]; 727 System.arraycopy(bandHeaderBytes, p0, 728 metaCoding, 0, metaCoding.length); 729 } 730 } 731 if (bandCoding != regularCoding) { 732 if (verbose > 1) 733 Utils.log.fine(name()+": irregular coding "+bandCoding); 734 } 735 bandCoding.readArrayFrom(in, values, 0, length); 736 if (optDumpBands) dumpBand(); 737 } 738 739 public void doneDisbursing() { 740 super.doneDisbursing(); 741 values = null; // for GC 742 } 743 744 private void dumpBand() throws IOException { 745 assert(optDumpBands); 746 try (PrintStream ps = new PrintStream(getDumpStream(this, ".txt"))) { 747 String irr = (bandCoding == regularCoding) ? "" : " irregular"; 748 ps.print("# length="+length+ 749 " size="+outputSize()+ 750 irr+" coding="+bandCoding); 751 if (metaCoding != noMetaCoding) { 752 StringBuffer sb = new StringBuffer(); 753 for (int i = 0; i < metaCoding.length; i++) { 754 if (i == 1) sb.append(" /"); 755 sb.append(" ").append(metaCoding[i] & 0xFF); 756 } 757 ps.print(" //header: "+sb); 758 } 759 printArrayTo(ps, values, 0, length); 760 } 761 try (OutputStream ds = getDumpStream(this, ".bnd")) { 762 bandCoding.writeArrayTo(ds, values, 0, length); 763 } 764 } 765 766 /** Disburse one value. */ 767 protected int getValue() { 768 assert(phase() == DISBURSE_PHASE); 769 assert(valuesDisbursed < length); 770 return values[valuesDisbursed++]; 771 } 772 773 /** Reset for another pass over the same value set. */ 774 public void resetForSecondPass() { 775 assert(phase() == DISBURSE_PHASE); 776 assert(valuesDisbursed == length()); // 1st pass is complete 777 valuesDisbursed = 0; 778 } 779 } 780 781 class ByteBand extends Band { 782 private ByteArrayOutputStream bytes; // input buffer 783 private ByteArrayOutputStream bytesForDump; 784 private InputStream in; 785 786 public ByteBand(String name) { 787 super(name, BYTE1); 788 } 789 790 public int capacity() { 791 return bytes == null ? -1 : Integer.MAX_VALUE; 792 } 793 protected void setCapacity(int cap) { 794 assert(bytes == null); // do this just once 795 bytes = new ByteArrayOutputStream(cap); 796 } 797 public void destroy() { 798 lengthForDebug = length(); 799 bytes = null; 800 } 801 802 public int length() { 803 return bytes == null ? -1 : bytes.size(); 804 } 805 public void reset() { 806 bytes.reset(); 807 } 808 protected int valuesRemainingForDebug() { 809 return (bytes == null) ? -1 : ((ByteArrayInputStream)in).available(); 810 } 811 812 protected void chooseBandCodings() throws IOException { 813 // No-op. 814 assert(decodeEscapeValue(regularCoding.min(), regularCoding) < 0); 815 assert(decodeEscapeValue(regularCoding.max(), regularCoding) < 0); 816 } 817 818 protected long computeOutputSize() { 819 // do not cache 820 return bytes.size(); 821 } 822 823 public void writeDataTo(OutputStream out) throws IOException { 824 if (length() == 0) return; 825 bytes.writeTo(out); 826 if (optDumpBands) dumpBand(); 827 destroy(); // done with the bits! 828 } 829 830 private void dumpBand() throws IOException { 831 assert(optDumpBands); 832 try (OutputStream ds = getDumpStream(this, ".bnd")) { 833 if (bytesForDump != null) 834 bytesForDump.writeTo(ds); 835 else 836 bytes.writeTo(ds); 837 } 838 } 839 840 public void readDataFrom(InputStream in) throws IOException { 841 int vex = valuesExpected(); 842 if (vex == 0) return; 843 if (verbose > 1) { 844 lengthForDebug = vex; 845 Utils.log.fine("Reading band "+this); 846 lengthForDebug = -1; 847 } 848 byte[] buf = new byte[Math.min(vex, 1<<14)]; 849 while (vex > 0) { 850 int nr = in.read(buf, 0, Math.min(vex, buf.length)); 851 if (nr < 0) throw new EOFException(); 852 bytes.write(buf, 0, nr); 853 vex -= nr; 854 } 855 if (optDumpBands) dumpBand(); 856 } 857 858 public void readyToDisburse() { 859 in = new ByteArrayInputStream(bytes.toByteArray()); 860 super.readyToDisburse(); 861 } 862 863 public void doneDisbursing() { 864 super.doneDisbursing(); 865 if (optDumpBands 866 && bytesForDump != null && bytesForDump.size() > 0) { 867 try { 868 dumpBand(); 869 } catch (IOException ee) { 870 throw new RuntimeException(ee); 871 } 872 } 873 in = null; // GC 874 bytes = null; // GC 875 bytesForDump = null; // GC 876 } 877 878 // alternative to readFrom: 879 public void setInputStreamFrom(InputStream in) throws IOException { 880 assert(bytes == null); 881 assert(assertReadyToReadFrom(this, in)); 882 setPhase(READ_PHASE); 883 this.in = in; 884 if (optDumpBands) { 885 // Tap the stream. 886 bytesForDump = new ByteArrayOutputStream(); 887 this.in = new FilterInputStream(in) { 888 public int read() throws IOException { 889 int ch = in.read(); 890 if (ch >= 0) bytesForDump.write(ch); 891 return ch; 892 } 893 public int read(byte b[], int off, int len) throws IOException { 894 int nr = in.read(b, off, len); 895 if (nr >= 0) bytesForDump.write(b, off, nr); 896 return nr; 897 } 898 }; 899 } 900 super.readyToDisburse(); 901 } 902 903 public OutputStream collectorStream() { 904 assert(phase() == COLLECT_PHASE); 905 assert(bytes != null); 906 return bytes; 907 } 908 909 public InputStream getInputStream() { 910 assert(phase() == DISBURSE_PHASE); 911 assert(in != null); 912 return in; 913 } 914 public int getByte() throws IOException { 915 int b = getInputStream().read(); 916 if (b < 0) throw new EOFException(); 917 return b; 918 } 919 public void putByte(int b) throws IOException { 920 assert(b == (b & 0xFF)); 921 collectorStream().write(b); 922 } 923 public String toString() { 924 return "byte "+super.toString(); 925 } 926 } 927 928 class IntBand extends ValueBand { 929 // The usual coding for bands is 7bit/5byte/delta. 930 public IntBand(String name, Coding regularCoding) { 931 super(name, regularCoding); 932 } 933 934 public void putInt(int x) { 935 assert(phase() == COLLECT_PHASE); 936 addValue(x); 937 } 938 939 public int getInt() { 940 return getValue(); 941 } 942 /** Return the sum of all values in this band. */ 943 public int getIntTotal() { 944 assert(phase() == DISBURSE_PHASE); 945 // assert that this is the whole pass; no other reads allowed 946 assert(valuesRemainingForDebug() == length()); 947 int total = 0; 948 for (int k = length(); k > 0; k--) { 949 total += getInt(); 950 } 951 resetForSecondPass(); 952 return total; 953 } 954 /** Return the occurrence count of a specific value in this band. */ 955 public int getIntCount(int value) { 956 assert(phase() == DISBURSE_PHASE); 957 // assert that this is the whole pass; no other reads allowed 958 assert(valuesRemainingForDebug() == length()); 959 int total = 0; 960 for (int k = length(); k > 0; k--) { 961 if (getInt() == value) { 962 total += 1; 963 } 964 } 965 resetForSecondPass(); 966 return total; 967 } 968 } 969 970 static int getIntTotal(int[] values) { 971 int total = 0; 972 for (int i = 0; i < values.length; i++) { 973 total += values[i]; 974 } 975 return total; 976 } 977 978 class CPRefBand extends ValueBand { 979 Index index; 980 boolean nullOK; 981 982 public CPRefBand(String name, Coding regularCoding, byte cpTag, boolean nullOK) { 983 super(name, regularCoding); 984 this.nullOK = nullOK; 985 if (cpTag != CONSTANT_None) 986 setBandIndex(this, cpTag); 987 } 988 public CPRefBand(String name, Coding regularCoding, byte cpTag) { 989 this(name, regularCoding, cpTag, false); 990 } 991 public CPRefBand(String name, Coding regularCoding, Object undef) { 992 this(name, regularCoding, CONSTANT_None, false); 993 } 994 995 public void setIndex(Index index) { 996 this.index = index; 997 } 998 999 protected void readDataFrom(InputStream in) throws IOException { 1000 super.readDataFrom(in); 1001 assert(assertValidCPRefs(this)); 1002 } 1003 1004 /** Write a constant pool reference. */ 1005 public void putRef(Entry e) { 1006 assert(index != null); 1007 addValue(encodeRefOrNull(e, index)); 1008 } 1009 public void putRef(Entry e, Index index) { 1010 assert(this.index == null); 1011 addValue(encodeRefOrNull(e, index)); 1012 } 1013 public void putRef(Entry e, byte cptag) { 1014 putRef(e, getCPIndex(cptag)); 1015 } 1016 1017 public Entry getRef() { 1018 if (index == null) Utils.log.warning("No index for "+this); 1019 assert(index != null); 1020 return decodeRefOrNull(getValue(), index); 1021 } 1022 public Entry getRef(Index index) { 1023 assert(this.index == null); 1024 return decodeRefOrNull(getValue(), index); 1025 } 1026 public Entry getRef(byte cptag) { 1027 return getRef(getCPIndex(cptag)); 1028 } 1029 1030 private int encodeRefOrNull(Entry e, Index index) { 1031 int nonNullCode; // NNC is the coding which assumes nulls are rare 1032 if (e == null) { 1033 nonNullCode = -1; // negative values are rare 1034 } else { 1035 nonNullCode = encodeRef(e, index); 1036 } 1037 // If nulls are expected, increment, to make -1 code turn to 0. 1038 return (nullOK ? 1 : 0) + nonNullCode; 1039 } 1040 private Entry decodeRefOrNull(int code, Index index) { 1041 // Inverse to encodeRefOrNull... 1042 int nonNullCode = code - (nullOK ? 1 : 0); 1043 if (nonNullCode == -1) { 1044 return null; 1045 } else { 1046 return decodeRef(nonNullCode, index); 1047 } 1048 } 1049 } 1050 1051 // Bootstrap support for CPRefBands. These are needed to record 1052 // intended CP indexes, before the CP has been created. 1053 private final List<CPRefBand> allKQBands = new ArrayList<>(); 1054 private List<Object[]> needPredefIndex = new ArrayList<>(); 1055 1056 1057 int encodeRef(Entry e, Index ix) { 1058 int coding = ix.indexOf(e); 1059 if (verbose > 2) 1060 Utils.log.fine("putRef "+coding+" => "+e); 1061 return coding; 1062 } 1063 1064 Entry decodeRef(int n, Index ix) { 1065 if (n < 0 || n >= ix.size()) 1066 Utils.log.warning("decoding bad ref "+n+" in "+ix); 1067 Entry e = ix.getEntry(n); 1068 if (verbose > 2) 1069 Utils.log.fine("getRef "+n+" => "+e); 1070 return e; 1071 } 1072 1073 private CodingChooser codingChooser; 1074 protected CodingChooser getCodingChooser() { 1075 if (codingChooser == null) { 1076 codingChooser = new CodingChooser(effort, basicCodings); 1077 if (codingChooser.stress != null 1078 && this instanceof PackageWriter) { 1079 // Twist the random state based on my first file. 1080 // This sends each segment off in a different direction. 1081 List<Package.Class> classes = ((PackageWriter)this).pkg.classes; 1082 if (!classes.isEmpty()) { 1083 Package.Class cls = classes.get(0); 1084 codingChooser.addStressSeed(cls.getName().hashCode()); 1085 } 1086 } 1087 } 1088 return codingChooser; 1089 } 1090 1091 public CodingMethod chooseCoding(int[] values, int start, int end, 1092 Coding regular, String bandName, 1093 int[] sizes) { 1094 assert(optVaryCodings); 1095 if (effort <= MIN_EFFORT) { 1096 return regular; 1097 } 1098 CodingChooser cc = getCodingChooser(); 1099 if (verbose > 1 || cc.verbose > 1) { 1100 Utils.log.fine("--- chooseCoding "+bandName); 1101 } 1102 return cc.choose(values, start, end, regular, sizes); 1103 } 1104 1105 static final byte[] defaultMetaCoding = { _meta_default }; 1106 static final byte[] noMetaCoding = {}; 1107 1108 // The first value in a band is always coded with the default coding D. 1109 // If this first value X is an escape value, it actually represents the 1110 // first (and perhaps only) byte of a meta-coding. 1111 // 1112 // If D.S != 0 and D includes the range [-256..-1], 1113 // the escape values are in that range, 1114 // and the first byte XB is -1-X. 1115 // 1116 // If D.S == 0 and D includes the range [(D.L)..(D.L)+255], 1117 // the escape values are in that range, 1118 // and XB is X-(D.L). 1119 // 1120 // This representation is designed so that a band header is unlikely 1121 // to be confused with the initial value of a headerless band, 1122 // and yet so that a band header is likely to occupy only a byte or two. 1123 // 1124 // Result is in [0..255] if XB was successfully extracted, else -1. 1125 // See section "Coding Specifier Meta-Encoding" in the JSR 200 spec. 1126 protected static int decodeEscapeValue(int X, Coding regularCoding) { 1127 // The first value in a band is always coded with the default coding D. 1128 // If this first value X is an escape value, it actually represents the 1129 // first (and perhaps only) byte of a meta-coding. 1130 // Result is in [0..255] if XB was successfully extracted, else -1. 1131 if (regularCoding.B() == 1 || regularCoding.L() == 0) 1132 return -1; // degenerate regular coding (BYTE1) 1133 if (regularCoding.S() != 0) { 1134 if (-256 <= X && X <= -1 && regularCoding.min() <= -256) { 1135 int XB = -1-X; 1136 assert(XB >= 0 && XB < 256); 1137 return XB; 1138 } 1139 } else { 1140 int L = regularCoding.L(); 1141 if (L <= X && X <= L+255 && regularCoding.max() >= L+255) { 1142 int XB = X-L; 1143 assert(XB >= 0 && XB < 256); 1144 return XB; 1145 } 1146 } 1147 return -1; // negative value for failure 1148 } 1149 // Inverse to decodeEscapeValue(). 1150 protected static int encodeEscapeValue(int XB, Coding regularCoding) { 1151 assert(XB >= 0 && XB < 256); 1152 assert(regularCoding.B() > 1 && regularCoding.L() > 0); 1153 int X; 1154 if (regularCoding.S() != 0) { 1155 assert(regularCoding.min() <= -256); 1156 X = -1-XB; 1157 } else { 1158 int L = regularCoding.L(); 1159 assert(regularCoding.max() >= L+255); 1160 X = XB+L; 1161 } 1162 assert(decodeEscapeValue(X, regularCoding) == XB) 1163 : (regularCoding+" XB="+XB+" X="+X); 1164 return X; 1165 } 1166 1167 static { 1168 boolean checkXB = false; 1169 assert(checkXB = true); 1170 if (checkXB) { 1171 for (int i = 0; i < basicCodings.length; i++) { 1172 Coding D = basicCodings[i]; 1173 if (D == null) continue; 1174 if (D.B() == 1) continue; 1175 if (D.L() == 0) continue; 1176 for (int XB = 0; XB <= 255; XB++) { 1177 // The following exercises decodeEscapeValue also: 1178 encodeEscapeValue(XB, D); 1179 } 1180 } 1181 } 1182 } 1183 1184 class MultiBand extends Band { 1185 MultiBand(String name, Coding regularCoding) { 1186 super(name, regularCoding); 1187 } 1188 1189 public Band init() { 1190 super.init(); 1191 // This is all just to keep the asserts happy: 1192 setCapacity(0); 1193 if (phase() == EXPECT_PHASE) { 1194 // Fast forward: 1195 setPhase(READ_PHASE); 1196 setPhase(DISBURSE_PHASE); 1197 } 1198 return this; 1199 } 1200 1201 Band[] bands = new Band[10]; 1202 int bandCount = 0; 1203 1204 int size() { 1205 return bandCount; 1206 } 1207 Band get(int i) { 1208 assert(i < bandCount); 1209 return bands[i]; 1210 } 1211 Band[] toArray() { 1212 return (Band[]) realloc(bands, bandCount); 1213 } 1214 1215 void add(Band b) { 1216 assert(bandCount == 0 || notePrevForAssert(b, bands[bandCount-1])); 1217 if (bandCount == bands.length) { 1218 bands = (Band[]) realloc(bands); 1219 } 1220 bands[bandCount++] = b; 1221 } 1222 1223 ByteBand newByteBand(String name) { 1224 ByteBand b = new ByteBand(name); 1225 b.init(); add(b); 1226 return b; 1227 } 1228 IntBand newIntBand(String name) { 1229 IntBand b = new IntBand(name, regularCoding); 1230 b.init(); add(b); 1231 return b; 1232 } 1233 IntBand newIntBand(String name, Coding regularCoding) { 1234 IntBand b = new IntBand(name, regularCoding); 1235 b.init(); add(b); 1236 return b; 1237 } 1238 MultiBand newMultiBand(String name, Coding regularCoding) { 1239 MultiBand b = new MultiBand(name, regularCoding); 1240 b.init(); add(b); 1241 return b; 1242 } 1243 CPRefBand newCPRefBand(String name, byte cpTag) { 1244 CPRefBand b = new CPRefBand(name, regularCoding, cpTag); 1245 b.init(); add(b); 1246 return b; 1247 } 1248 CPRefBand newCPRefBand(String name, Coding regularCoding, 1249 byte cpTag) { 1250 CPRefBand b = new CPRefBand(name, regularCoding, cpTag); 1251 b.init(); add(b); 1252 return b; 1253 } 1254 CPRefBand newCPRefBand(String name, Coding regularCoding, 1255 byte cpTag, boolean nullOK) { 1256 CPRefBand b = new CPRefBand(name, regularCoding, cpTag, nullOK); 1257 b.init(); add(b); 1258 return b; 1259 } 1260 1261 int bandCount() { return bandCount; } 1262 1263 private int cap = -1; 1264 public int capacity() { return cap; } 1265 public void setCapacity(int cap) { this.cap = cap; } 1266 1267 public int length() { return 0; } 1268 public int valuesRemainingForDebug() { return 0; } 1269 1270 protected void chooseBandCodings() throws IOException { 1271 // coding decision pass 1272 for (int i = 0; i < bandCount; i++) { 1273 Band b = bands[i]; 1274 b.chooseBandCodings(); 1275 } 1276 } 1277 1278 protected long computeOutputSize() { 1279 // coding decision pass 1280 long sum = 0; 1281 for (int i = 0; i < bandCount; i++) { 1282 Band b = bands[i]; 1283 long bsize = b.outputSize(); 1284 assert(bsize >= 0) : b; 1285 sum += bsize; 1286 } 1287 // do not cache 1288 return sum; 1289 } 1290 1291 protected void writeDataTo(OutputStream out) throws IOException { 1292 long preCount = 0; 1293 if (outputCounter != null) preCount = outputCounter.getCount(); 1294 for (int i = 0; i < bandCount; i++) { 1295 Band b = bands[i]; 1296 b.writeTo(out); 1297 if (outputCounter != null) { 1298 long postCount = outputCounter.getCount(); 1299 long len = postCount - preCount; 1300 preCount = postCount; 1301 if ((verbose > 0 && len > 0) || verbose > 1) { 1302 Utils.log.info(" ...wrote "+len+" bytes from "+b); 1303 } 1304 } 1305 } 1306 } 1307 1308 protected void readDataFrom(InputStream in) throws IOException { 1309 assert(false); // not called? 1310 for (int i = 0; i < bandCount; i++) { 1311 Band b = bands[i]; 1312 b.readFrom(in); 1313 if ((verbose > 0 && b.length() > 0) || verbose > 1) { 1314 Utils.log.info(" ...read "+b); 1315 } 1316 } 1317 } 1318 1319 public String toString() { 1320 return "{"+bandCount()+" bands: "+super.toString()+"}"; 1321 } 1322 } 1323 1324 /** 1325 * An output stream which counts the number of bytes written. 1326 */ 1327 private static 1328 class ByteCounter extends FilterOutputStream { 1329 // (should go public under the name CountingOutputStream?) 1330 1331 private long count; 1332 1333 public ByteCounter(OutputStream out) { 1334 super(out); 1335 } 1336 1337 public long getCount() { return count; } 1338 public void setCount(long c) { count = c; } 1339 1340 public void write(int b) throws IOException { 1341 count++; 1342 if (out != null) out.write(b); 1343 } 1344 public void write(byte b[], int off, int len) throws IOException { 1345 count += len; 1346 if (out != null) out.write(b, off, len); 1347 } 1348 public String toString() { 1349 return String.valueOf(getCount()); 1350 } 1351 } 1352 ByteCounter outputCounter; 1353 1354 void writeAllBandsTo(OutputStream out) throws IOException { 1355 // Wrap a byte-counter around the output stream. 1356 outputCounter = new ByteCounter(out); 1357 out = outputCounter; 1358 all_bands.writeTo(out); 1359 if (verbose > 0) { 1360 long nbytes = outputCounter.getCount(); 1361 Utils.log.info("Wrote total of "+nbytes+" bytes."); 1362 assert(nbytes == archiveSize0+archiveSize1); 1363 } 1364 outputCounter = null; 1365 } 1366 1367 // random AO_XXX bits, decoded from the archive header 1368 protected int archiveOptions; 1369 1370 // archiveSize1 sizes most of the archive [archive_options..file_bits). 1371 protected long archiveSize0; // size through archive_size_lo 1372 protected long archiveSize1; // size reported in archive_header 1373 protected int archiveNextCount; // reported in archive_header 1374 1375 static final int AH_LENGTH_0 = 3; //minver, majver, options 1376 static final int AH_ARCHIVE_SIZE_HI = 0; 1377 static final int AH_ARCHIVE_SIZE_LO = 1; 1378 static final int AH_LENGTH_S = 2; //optional size hi/lo 1379 static final int AH_LENGTH = 26; // mentioned in spec 1380 // Length contributions from optional header fields: 1381 static final int AH_FILE_HEADER_LEN = 5; // sizehi/lo/next/modtime/files 1382 static final int AH_SPECIAL_FORMAT_LEN = 2; // layouts/band-headers 1383 static final int AH_CP_NUMBER_LEN = 4; // int/float/long/double 1384 static final int AH_LENGTH_MIN = AH_LENGTH 1385 -(AH_SPECIAL_FORMAT_LEN+AH_FILE_HEADER_LEN+AH_CP_NUMBER_LEN); 1386 1387 // Common structure of attribute band groups: 1388 static final int AB_FLAGS_HI = 0; 1389 static final int AB_FLAGS_LO = 1; 1390 static final int AB_ATTR_COUNT = 2; 1391 static final int AB_ATTR_INDEXES = 3; 1392 static final int AB_ATTR_CALLS = 4; 1393 1394 static IntBand getAttrBand(MultiBand xxx_attr_bands, int which) { 1395 IntBand b = (IntBand) xxx_attr_bands.get(which); 1396 switch (which) { 1397 case AB_FLAGS_HI: 1398 assert(b.name().endsWith("_flags_hi")); break; 1399 case AB_FLAGS_LO: 1400 assert(b.name().endsWith("_flags_lo")); break; 1401 case AB_ATTR_COUNT: 1402 assert(b.name().endsWith("_attr_count")); break; 1403 case AB_ATTR_INDEXES: 1404 assert(b.name().endsWith("_attr_indexes")); break; 1405 case AB_ATTR_CALLS: 1406 assert(b.name().endsWith("_attr_calls")); break; 1407 default: 1408 assert(false); break; 1409 } 1410 return b; 1411 } 1412 1413 static private final boolean NULL_IS_OK = true; 1414 1415 MultiBand all_bands = (MultiBand) new MultiBand("(package)", UNSIGNED5).init(); 1416 1417 // file header (various random bytes) 1418 ByteBand archive_magic = all_bands.newByteBand("archive_magic"); 1419 IntBand archive_header_0 = all_bands.newIntBand("archive_header_0", UNSIGNED5); 1420 IntBand archive_header_S = all_bands.newIntBand("archive_header_S", UNSIGNED5); 1421 IntBand archive_header_1 = all_bands.newIntBand("archive_header_1", UNSIGNED5); 1422 ByteBand band_headers = all_bands.newByteBand("band_headers"); 1423 1424 // constant pool contents 1425 MultiBand cp_bands = all_bands.newMultiBand("(constant_pool)", DELTA5); 1426 IntBand cp_Utf8_prefix = cp_bands.newIntBand("cp_Utf8_prefix"); 1427 IntBand cp_Utf8_suffix = cp_bands.newIntBand("cp_Utf8_suffix", UNSIGNED5); 1428 IntBand cp_Utf8_chars = cp_bands.newIntBand("cp_Utf8_chars", CHAR3); 1429 IntBand cp_Utf8_big_suffix = cp_bands.newIntBand("cp_Utf8_big_suffix"); 1430 MultiBand cp_Utf8_big_chars = cp_bands.newMultiBand("(cp_Utf8_big_chars)", DELTA5); 1431 IntBand cp_Int = cp_bands.newIntBand("cp_Int", UDELTA5); 1432 IntBand cp_Float = cp_bands.newIntBand("cp_Float", UDELTA5); 1433 IntBand cp_Long_hi = cp_bands.newIntBand("cp_Long_hi", UDELTA5); 1434 IntBand cp_Long_lo = cp_bands.newIntBand("cp_Long_lo"); 1435 IntBand cp_Double_hi = cp_bands.newIntBand("cp_Double_hi", UDELTA5); 1436 IntBand cp_Double_lo = cp_bands.newIntBand("cp_Double_lo"); 1437 CPRefBand cp_String = cp_bands.newCPRefBand("cp_String", UDELTA5, CONSTANT_Utf8); 1438 CPRefBand cp_Class = cp_bands.newCPRefBand("cp_Class", UDELTA5, CONSTANT_Utf8); 1439 CPRefBand cp_Signature_form = cp_bands.newCPRefBand("cp_Signature_form", CONSTANT_Utf8); 1440 CPRefBand cp_Signature_classes = cp_bands.newCPRefBand("cp_Signature_classes", UDELTA5, CONSTANT_Class); 1441 CPRefBand cp_Descr_name = cp_bands.newCPRefBand("cp_Descr_name", CONSTANT_Utf8); 1442 CPRefBand cp_Descr_type = cp_bands.newCPRefBand("cp_Descr_type", UDELTA5, CONSTANT_Signature); 1443 CPRefBand cp_Field_class = cp_bands.newCPRefBand("cp_Field_class", CONSTANT_Class); 1444 CPRefBand cp_Field_desc = cp_bands.newCPRefBand("cp_Field_desc", UDELTA5, CONSTANT_NameandType); 1445 CPRefBand cp_Method_class = cp_bands.newCPRefBand("cp_Method_class", CONSTANT_Class); 1446 CPRefBand cp_Method_desc = cp_bands.newCPRefBand("cp_Method_desc", UDELTA5, CONSTANT_NameandType); 1447 CPRefBand cp_Imethod_class = cp_bands.newCPRefBand("cp_Imethod_class", CONSTANT_Class); 1448 CPRefBand cp_Imethod_desc = cp_bands.newCPRefBand("cp_Imethod_desc", UDELTA5, CONSTANT_NameandType); 1449 1450 // bands for carrying attribute definitions: 1451 MultiBand attr_definition_bands = all_bands.newMultiBand("(attr_definition_bands)", UNSIGNED5); 1452 ByteBand attr_definition_headers = attr_definition_bands.newByteBand("attr_definition_headers"); 1453 CPRefBand attr_definition_name = attr_definition_bands.newCPRefBand("attr_definition_name", CONSTANT_Utf8); 1454 CPRefBand attr_definition_layout = attr_definition_bands.newCPRefBand("attr_definition_layout", CONSTANT_Utf8); 1455 1456 // bands for hardwired InnerClasses attribute (shared across the package) 1457 MultiBand ic_bands = all_bands.newMultiBand("(ic_bands)", DELTA5); 1458 CPRefBand ic_this_class = ic_bands.newCPRefBand("ic_this_class", UDELTA5, CONSTANT_Class); 1459 IntBand ic_flags = ic_bands.newIntBand("ic_flags", UNSIGNED5); 1460 // These bands contain data only where flags sets ACC_IC_LONG_FORM: 1461 CPRefBand ic_outer_class = ic_bands.newCPRefBand("ic_outer_class", DELTA5, CONSTANT_Class, NULL_IS_OK); 1462 CPRefBand ic_name = ic_bands.newCPRefBand("ic_name", DELTA5, CONSTANT_Utf8, NULL_IS_OK); 1463 1464 // bands for carrying class schema information: 1465 MultiBand class_bands = all_bands.newMultiBand("(class_bands)", DELTA5); 1466 CPRefBand class_this = class_bands.newCPRefBand("class_this", CONSTANT_Class); 1467 CPRefBand class_super = class_bands.newCPRefBand("class_super", CONSTANT_Class); 1468 IntBand class_interface_count = class_bands.newIntBand("class_interface_count"); 1469 CPRefBand class_interface = class_bands.newCPRefBand("class_interface", CONSTANT_Class); 1470 1471 // bands for class members 1472 IntBand class_field_count = class_bands.newIntBand("class_field_count"); 1473 IntBand class_method_count = class_bands.newIntBand("class_method_count"); 1474 1475 CPRefBand field_descr = class_bands.newCPRefBand("field_descr", CONSTANT_NameandType); 1476 MultiBand field_attr_bands = class_bands.newMultiBand("(field_attr_bands)", UNSIGNED5); 1477 IntBand field_flags_hi = field_attr_bands.newIntBand("field_flags_hi"); 1478 IntBand field_flags_lo = field_attr_bands.newIntBand("field_flags_lo"); 1479 IntBand field_attr_count = field_attr_bands.newIntBand("field_attr_count"); 1480 IntBand field_attr_indexes = field_attr_bands.newIntBand("field_attr_indexes"); 1481 IntBand field_attr_calls = field_attr_bands.newIntBand("field_attr_calls"); 1482 1483 // bands for predefined field attributes 1484 CPRefBand field_ConstantValue_KQ = field_attr_bands.newCPRefBand("field_ConstantValue_KQ", CONSTANT_Literal); 1485 CPRefBand field_Signature_RS = field_attr_bands.newCPRefBand("field_Signature_RS", CONSTANT_Signature); 1486 MultiBand field_metadata_bands = field_attr_bands.newMultiBand("(field_metadata_bands)", UNSIGNED5); 1487 1488 CPRefBand method_descr = class_bands.newCPRefBand("method_descr", MDELTA5, CONSTANT_NameandType); 1489 MultiBand method_attr_bands = class_bands.newMultiBand("(method_attr_bands)", UNSIGNED5); 1490 IntBand method_flags_hi = method_attr_bands.newIntBand("method_flags_hi"); 1491 IntBand method_flags_lo = method_attr_bands.newIntBand("method_flags_lo"); 1492 IntBand method_attr_count = method_attr_bands.newIntBand("method_attr_count"); 1493 IntBand method_attr_indexes = method_attr_bands.newIntBand("method_attr_indexes"); 1494 IntBand method_attr_calls = method_attr_bands.newIntBand("method_attr_calls"); 1495 // band for predefined method attributes 1496 IntBand method_Exceptions_N = method_attr_bands.newIntBand("method_Exceptions_N"); 1497 CPRefBand method_Exceptions_RC = method_attr_bands.newCPRefBand("method_Exceptions_RC", CONSTANT_Class); 1498 CPRefBand method_Signature_RS = method_attr_bands.newCPRefBand("method_Signature_RS", CONSTANT_Signature); 1499 MultiBand method_metadata_bands = method_attr_bands.newMultiBand("(method_metadata_bands)", UNSIGNED5); 1500 1501 MultiBand class_attr_bands = class_bands.newMultiBand("(class_attr_bands)", UNSIGNED5); 1502 IntBand class_flags_hi = class_attr_bands.newIntBand("class_flags_hi"); 1503 IntBand class_flags_lo = class_attr_bands.newIntBand("class_flags_lo"); 1504 IntBand class_attr_count = class_attr_bands.newIntBand("class_attr_count"); 1505 IntBand class_attr_indexes = class_attr_bands.newIntBand("class_attr_indexes"); 1506 IntBand class_attr_calls = class_attr_bands.newIntBand("class_attr_calls"); 1507 // band for predefined SourceFile and other class attributes 1508 CPRefBand class_SourceFile_RUN = class_attr_bands.newCPRefBand("class_SourceFile_RUN", UNSIGNED5, CONSTANT_Utf8, NULL_IS_OK); 1509 CPRefBand class_EnclosingMethod_RC = class_attr_bands.newCPRefBand("class_EnclosingMethod_RC", CONSTANT_Class); 1510 CPRefBand class_EnclosingMethod_RDN = class_attr_bands.newCPRefBand("class_EnclosingMethod_RDN", UNSIGNED5, CONSTANT_NameandType, NULL_IS_OK); 1511 CPRefBand class_Signature_RS = class_attr_bands.newCPRefBand("class_Signature_RS", CONSTANT_Signature); 1512 MultiBand class_metadata_bands = class_attr_bands.newMultiBand("(class_metadata_bands)", UNSIGNED5); 1513 IntBand class_InnerClasses_N = class_attr_bands.newIntBand("class_InnerClasses_N"); 1514 CPRefBand class_InnerClasses_RC = class_attr_bands.newCPRefBand("class_InnerClasses_RC", CONSTANT_Class); 1515 IntBand class_InnerClasses_F = class_attr_bands.newIntBand("class_InnerClasses_F"); 1516 CPRefBand class_InnerClasses_outer_RCN = class_attr_bands.newCPRefBand("class_InnerClasses_outer_RCN", UNSIGNED5, CONSTANT_Class, NULL_IS_OK); 1517 CPRefBand class_InnerClasses_name_RUN = class_attr_bands.newCPRefBand("class_InnerClasses_name_RUN", UNSIGNED5, CONSTANT_Utf8, NULL_IS_OK); 1518 IntBand class_ClassFile_version_minor_H = class_attr_bands.newIntBand("class_ClassFile_version_minor_H"); 1519 IntBand class_ClassFile_version_major_H = class_attr_bands.newIntBand("class_ClassFile_version_major_H"); 1520 1521 MultiBand code_bands = class_bands.newMultiBand("(code_bands)", UNSIGNED5); 1522 ByteBand code_headers = code_bands.newByteBand("code_headers"); //BYTE1 1523 IntBand code_max_stack = code_bands.newIntBand("code_max_stack", UNSIGNED5); 1524 IntBand code_max_na_locals = code_bands.newIntBand("code_max_na_locals", UNSIGNED5); 1525 IntBand code_handler_count = code_bands.newIntBand("code_handler_count", UNSIGNED5); 1526 IntBand code_handler_start_P = code_bands.newIntBand("code_handler_start_P", BCI5); 1527 IntBand code_handler_end_PO = code_bands.newIntBand("code_handler_end_PO", BRANCH5); 1528 IntBand code_handler_catch_PO = code_bands.newIntBand("code_handler_catch_PO", BRANCH5); 1529 CPRefBand code_handler_class_RCN = code_bands.newCPRefBand("code_handler_class_RCN", UNSIGNED5, CONSTANT_Class, NULL_IS_OK); 1530 1531 MultiBand code_attr_bands = class_bands.newMultiBand("(code_attr_bands)", UNSIGNED5); 1532 IntBand code_flags_hi = code_attr_bands.newIntBand("code_flags_hi"); 1533 IntBand code_flags_lo = code_attr_bands.newIntBand("code_flags_lo"); 1534 IntBand code_attr_count = code_attr_bands.newIntBand("code_attr_count"); 1535 IntBand code_attr_indexes = code_attr_bands.newIntBand("code_attr_indexes"); 1536 IntBand code_attr_calls = code_attr_bands.newIntBand("code_attr_calls"); 1537 1538 MultiBand stackmap_bands = code_attr_bands.newMultiBand("StackMapTable_bands", UNSIGNED5); 1539 IntBand code_StackMapTable_N = stackmap_bands.newIntBand("code_StackMapTable_N"); 1540 IntBand code_StackMapTable_frame_T = stackmap_bands.newIntBand("code_StackMapTable_frame_T",BYTE1); 1541 IntBand code_StackMapTable_local_N = stackmap_bands.newIntBand("code_StackMapTable_local_N"); 1542 IntBand code_StackMapTable_stack_N = stackmap_bands.newIntBand("code_StackMapTable_stack_N"); 1543 IntBand code_StackMapTable_offset = stackmap_bands.newIntBand("code_StackMapTable_offset", UNSIGNED5); 1544 IntBand code_StackMapTable_T = stackmap_bands.newIntBand("code_StackMapTable_T", BYTE1); 1545 CPRefBand code_StackMapTable_RC = stackmap_bands.newCPRefBand("code_StackMapTable_RC", CONSTANT_Class); 1546 IntBand code_StackMapTable_P = stackmap_bands.newIntBand("code_StackMapTable_P", BCI5); 1547 1548 // bands for predefined LineNumberTable attribute 1549 IntBand code_LineNumberTable_N = code_attr_bands.newIntBand("code_LineNumberTable_N"); 1550 IntBand code_LineNumberTable_bci_P = code_attr_bands.newIntBand("code_LineNumberTable_bci_P", BCI5); 1551 IntBand code_LineNumberTable_line = code_attr_bands.newIntBand("code_LineNumberTable_line"); 1552 1553 // bands for predefined LocalVariable{Type}Table attributes 1554 IntBand code_LocalVariableTable_N = code_attr_bands.newIntBand("code_LocalVariableTable_N"); 1555 IntBand code_LocalVariableTable_bci_P = code_attr_bands.newIntBand("code_LocalVariableTable_bci_P", BCI5); 1556 IntBand code_LocalVariableTable_span_O = code_attr_bands.newIntBand("code_LocalVariableTable_span_O", BRANCH5); 1557 CPRefBand code_LocalVariableTable_name_RU = code_attr_bands.newCPRefBand("code_LocalVariableTable_name_RU", CONSTANT_Utf8); 1558 CPRefBand code_LocalVariableTable_type_RS = code_attr_bands.newCPRefBand("code_LocalVariableTable_type_RS", CONSTANT_Signature); 1559 IntBand code_LocalVariableTable_slot = code_attr_bands.newIntBand("code_LocalVariableTable_slot"); 1560 IntBand code_LocalVariableTypeTable_N = code_attr_bands.newIntBand("code_LocalVariableTypeTable_N"); 1561 IntBand code_LocalVariableTypeTable_bci_P = code_attr_bands.newIntBand("code_LocalVariableTypeTable_bci_P", BCI5); 1562 IntBand code_LocalVariableTypeTable_span_O = code_attr_bands.newIntBand("code_LocalVariableTypeTable_span_O", BRANCH5); 1563 CPRefBand code_LocalVariableTypeTable_name_RU = code_attr_bands.newCPRefBand("code_LocalVariableTypeTable_name_RU", CONSTANT_Utf8); 1564 CPRefBand code_LocalVariableTypeTable_type_RS = code_attr_bands.newCPRefBand("code_LocalVariableTypeTable_type_RS", CONSTANT_Signature); 1565 IntBand code_LocalVariableTypeTable_slot = code_attr_bands.newIntBand("code_LocalVariableTypeTable_slot"); 1566 1567 // bands for bytecodes 1568 MultiBand bc_bands = all_bands.newMultiBand("(byte_codes)", UNSIGNED5); 1569 ByteBand bc_codes = bc_bands.newByteBand("bc_codes"); //BYTE1 1570 // remaining bands provide typed opcode fields required by the bc_codes 1571 1572 IntBand bc_case_count = bc_bands.newIntBand("bc_case_count"); // *switch 1573 IntBand bc_case_value = bc_bands.newIntBand("bc_case_value", DELTA5); // *switch 1574 ByteBand bc_byte = bc_bands.newByteBand("bc_byte"); //BYTE1 // bipush, iinc, *newarray 1575 IntBand bc_short = bc_bands.newIntBand("bc_short", DELTA5); // sipush, wide iinc 1576 IntBand bc_local = bc_bands.newIntBand("bc_local"); // *load, *store, iinc, ret 1577 IntBand bc_label = bc_bands.newIntBand("bc_label", BRANCH5); // if*, goto*, jsr*, *switch 1578 1579 // Most CP refs exhibit some correlation, and benefit from delta coding. 1580 // The notable exceptions are class and method references. 1581 1582 // ldc* operands: 1583 CPRefBand bc_intref = bc_bands.newCPRefBand("bc_intref", DELTA5, CONSTANT_Integer); 1584 CPRefBand bc_floatref = bc_bands.newCPRefBand("bc_floatref", DELTA5, CONSTANT_Float); 1585 CPRefBand bc_longref = bc_bands.newCPRefBand("bc_longref", DELTA5, CONSTANT_Long); 1586 CPRefBand bc_doubleref = bc_bands.newCPRefBand("bc_doubleref", DELTA5, CONSTANT_Double); 1587 CPRefBand bc_stringref = bc_bands.newCPRefBand("bc_stringref", DELTA5, CONSTANT_String); 1588 1589 // nulls produced by bc_classref are taken to mean the current class 1590 CPRefBand bc_classref = bc_bands.newCPRefBand("bc_classref", UNSIGNED5, CONSTANT_Class, NULL_IS_OK); // new, *anew*, c*cast, i*of, ldc 1591 CPRefBand bc_fieldref = bc_bands.newCPRefBand("bc_fieldref", DELTA5, CONSTANT_Fieldref); // get*, put* 1592 CPRefBand bc_methodref = bc_bands.newCPRefBand("bc_methodref", CONSTANT_Methodref); // invoke[vs]* 1593 CPRefBand bc_imethodref = bc_bands.newCPRefBand("bc_imethodref", DELTA5, CONSTANT_InterfaceMethodref); // invokeinterface 1594 1595 // _self_linker_op family 1596 CPRefBand bc_thisfield = bc_bands.newCPRefBand("bc_thisfield", CONSTANT_None); // any field within cur. class 1597 CPRefBand bc_superfield = bc_bands.newCPRefBand("bc_superfield", CONSTANT_None); // any field within superclass 1598 CPRefBand bc_thismethod = bc_bands.newCPRefBand("bc_thismethod", CONSTANT_None); // any method within cur. class 1599 CPRefBand bc_supermethod = bc_bands.newCPRefBand("bc_supermethod", CONSTANT_None); // any method within superclass 1600 // bc_invokeinit family: 1601 IntBand bc_initref = bc_bands.newIntBand("bc_initref"); 1602 // escapes 1603 CPRefBand bc_escref = bc_bands.newCPRefBand("bc_escref", CONSTANT_All); 1604 IntBand bc_escrefsize = bc_bands.newIntBand("bc_escrefsize"); 1605 IntBand bc_escsize = bc_bands.newIntBand("bc_escsize"); 1606 ByteBand bc_escbyte = bc_bands.newByteBand("bc_escbyte"); 1607 1608 // bands for carrying resource files and file attributes: 1609 MultiBand file_bands = all_bands.newMultiBand("(file_bands)", UNSIGNED5); 1610 CPRefBand file_name = file_bands.newCPRefBand("file_name", CONSTANT_Utf8); 1611 IntBand file_size_hi = file_bands.newIntBand("file_size_hi"); 1612 IntBand file_size_lo = file_bands.newIntBand("file_size_lo"); 1613 IntBand file_modtime = file_bands.newIntBand("file_modtime", DELTA5); 1614 IntBand file_options = file_bands.newIntBand("file_options"); 1615 ByteBand file_bits = file_bands.newByteBand("file_bits"); 1616 1617 // End of band definitions! 1618 1619 /** Given CP indexes, distribute tag-specific indexes to bands. */ 1620 protected void setBandIndexes() { 1621 // Handle prior calls to setBandIndex: 1622 for (Object[] need : needPredefIndex) { 1623 CPRefBand b = (CPRefBand) need[0]; 1624 Byte which = (Byte) need[1]; 1625 b.setIndex(getCPIndex(which.byteValue())); 1626 } 1627 needPredefIndex = null; // no more predefs 1628 1629 if (verbose > 3) { 1630 printCDecl(all_bands); 1631 } 1632 } 1633 1634 protected void setBandIndex(CPRefBand b, byte which) { 1635 Object[] need = { b, Byte.valueOf(which) }; 1636 if (which == CONSTANT_Literal) { 1637 // I.e., attribute layouts KQ (no null) or KQN (null ok). 1638 allKQBands.add(b); 1639 } else if (needPredefIndex != null) { 1640 needPredefIndex.add(need); 1641 } else { 1642 // Not in predefinition mode; getCPIndex now works. 1643 b.setIndex(getCPIndex(which)); 1644 } 1645 } 1646 1647 protected void setConstantValueIndex(Field f) { 1648 Index ix = null; 1649 if (f != null) { 1650 byte tag = f.getLiteralTag(); 1651 ix = getCPIndex(tag); 1652 if (verbose > 2) 1653 Utils.log.fine("setConstantValueIndex "+f+" "+ConstantPool.tagName(tag)+" => "+ix); 1654 assert(ix != null); 1655 } 1656 // Typically, allKQBands is the singleton of field_ConstantValue_KQ. 1657 for (CPRefBand xxx_KQ : allKQBands) { 1658 xxx_KQ.setIndex(ix); 1659 } 1660 } 1661 1662 // Table of bands which contain metadata. 1663 protected MultiBand[] metadataBands = new MultiBand[ATTR_CONTEXT_LIMIT]; 1664 { 1665 metadataBands[ATTR_CONTEXT_CLASS] = class_metadata_bands; 1666 metadataBands[ATTR_CONTEXT_FIELD] = field_metadata_bands; 1667 metadataBands[ATTR_CONTEXT_METHOD] = method_metadata_bands; 1668 } 1669 1670 // Attribute layouts. 1671 public static final int ADH_CONTEXT_MASK = 0x3; // (ad_hdr & ADH_CONTEXT_MASK) 1672 public static final int ADH_BIT_SHIFT = 0x2; // (ad_hdr >> ADH_BIT_SHIFT) 1673 public static final int ADH_BIT_IS_LSB = 1; 1674 public static final int ATTR_INDEX_OVERFLOW = -1; 1675 1676 public int[] attrIndexLimit = new int[ATTR_CONTEXT_LIMIT]; 1677 // Each index limit is either 32 or 63, depending on AO_HAVE_XXX_FLAGS_HI. 1678 1679 // Which flag bits are taken over by attributes? 1680 protected long[] attrFlagMask = new long[ATTR_CONTEXT_LIMIT]; 1681 // Which flag bits have been taken over explicitly? 1682 protected long[] attrDefSeen = new long[ATTR_CONTEXT_LIMIT]; 1683 1684 // What pseudo-attribute bits are there to watch for? 1685 protected int[] attrOverflowMask = new int[ATTR_CONTEXT_LIMIT]; 1686 protected int attrClassFileVersionMask; 1687 1688 // Mapping from Attribute.Layout to Band[] (layout element bands). 1689 protected Map<Attribute.Layout, Band[]> attrBandTable = new HashMap<>(); 1690 1691 // Well-known attributes: 1692 protected final Attribute.Layout attrCodeEmpty; 1693 protected final Attribute.Layout attrInnerClassesEmpty; 1694 protected final Attribute.Layout attrClassFileVersion; 1695 protected final Attribute.Layout attrConstantValue; 1696 1697 // Mapping from Attribute.Layout to Integer (inverse of attrDefs) 1698 Map<Attribute.Layout, Integer> attrIndexTable = new HashMap<>(); 1699 1700 // Mapping from attribute index (<32 are flag bits) to attributes. 1701 protected List<List<Attribute.Layout>> attrDefs = 1702 new FixedList<>(ATTR_CONTEXT_LIMIT); 1703 { 1704 for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { 1705 assert(attrIndexLimit[i] == 0); 1706 attrIndexLimit[i] = 32; // just for the sake of predefs. 1707 attrDefs.set(i, new ArrayList<Attribute.Layout>(Collections.nCopies( 1708 attrIndexLimit[i], (Attribute.Layout)null))); 1709 1710 } 1711 1712 // Add predefined attribute definitions: 1713 attrInnerClassesEmpty = 1714 predefineAttribute(CLASS_ATTR_InnerClasses, ATTR_CONTEXT_CLASS, null, 1715 "InnerClasses", ""); 1716 assert(attrInnerClassesEmpty == Package.attrInnerClassesEmpty); 1717 predefineAttribute(CLASS_ATTR_SourceFile, ATTR_CONTEXT_CLASS, 1718 new Band[] { class_SourceFile_RUN }, 1719 "SourceFile", "RUNH"); 1720 predefineAttribute(CLASS_ATTR_EnclosingMethod, ATTR_CONTEXT_CLASS, 1721 new Band[] { 1722 class_EnclosingMethod_RC, 1723 class_EnclosingMethod_RDN 1724 }, 1725 "EnclosingMethod", "RCHRDNH"); 1726 attrClassFileVersion = 1727 predefineAttribute(CLASS_ATTR_ClassFile_version, ATTR_CONTEXT_CLASS, 1728 new Band[] { 1729 class_ClassFile_version_minor_H, 1730 class_ClassFile_version_major_H 1731 }, 1732 ".ClassFile.version", "HH"); 1733 predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_CLASS, 1734 new Band[] { class_Signature_RS }, 1735 "Signature", "RSH"); 1736 predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_CLASS, null, 1737 "Deprecated", ""); 1738 //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_CLASS, null, 1739 // "Synthetic", ""); 1740 predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_CLASS, null, 1741 ".Overflow", ""); 1742 attrConstantValue = 1743 predefineAttribute(FIELD_ATTR_ConstantValue, ATTR_CONTEXT_FIELD, 1744 new Band[] { field_ConstantValue_KQ }, 1745 "ConstantValue", "KQH"); 1746 predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_FIELD, 1747 new Band[] { field_Signature_RS }, 1748 "Signature", "RSH"); 1749 predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_FIELD, null, 1750 "Deprecated", ""); 1751 //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_FIELD, null, 1752 // "Synthetic", ""); 1753 predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_FIELD, null, 1754 ".Overflow", ""); 1755 attrCodeEmpty = 1756 predefineAttribute(METHOD_ATTR_Code, ATTR_CONTEXT_METHOD, null, 1757 "Code", ""); 1758 predefineAttribute(METHOD_ATTR_Exceptions, ATTR_CONTEXT_METHOD, 1759 new Band[] { 1760 method_Exceptions_N, 1761 method_Exceptions_RC 1762 }, 1763 "Exceptions", "NH[RCH]"); 1764 assert(attrCodeEmpty == Package.attrCodeEmpty); 1765 predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_METHOD, 1766 new Band[] { method_Signature_RS }, 1767 "Signature", "RSH"); 1768 predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_METHOD, null, 1769 "Deprecated", ""); 1770 //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_METHOD, null, 1771 // "Synthetic", ""); 1772 predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_METHOD, null, 1773 ".Overflow", ""); 1774 1775 for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) { 1776 MultiBand xxx_metadata_bands = metadataBands[ctype]; 1777 if (xxx_metadata_bands == null) 1778 continue; // no code attrs 1779 1780 // These arguments cause the bands to be built 1781 // automatically for this complicated layout: 1782 predefineAttribute(X_ATTR_RuntimeVisibleAnnotations, 1783 ATTR_CONTEXT_NAME[ctype]+"_RVA_", 1784 xxx_metadata_bands, 1785 Attribute.lookup(null, ctype, 1786 "RuntimeVisibleAnnotations")); 1787 predefineAttribute(X_ATTR_RuntimeInvisibleAnnotations, 1788 ATTR_CONTEXT_NAME[ctype]+"_RIA_", 1789 xxx_metadata_bands, 1790 Attribute.lookup(null, ctype, 1791 "RuntimeInvisibleAnnotations")); 1792 if (ctype != ATTR_CONTEXT_METHOD) 1793 continue; 1794 1795 predefineAttribute(METHOD_ATTR_RuntimeVisibleParameterAnnotations, 1796 "method_RVPA_", xxx_metadata_bands, 1797 Attribute.lookup(null, ctype, 1798 "RuntimeVisibleParameterAnnotations")); 1799 predefineAttribute(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, 1800 "method_RIPA_", xxx_metadata_bands, 1801 Attribute.lookup(null, ctype, 1802 "RuntimeInvisibleParameterAnnotations")); 1803 predefineAttribute(METHOD_ATTR_AnnotationDefault, 1804 "method_AD_", xxx_metadata_bands, 1805 Attribute.lookup(null, ctype, 1806 "AnnotationDefault")); 1807 } 1808 1809 1810 Attribute.Layout stackMapDef = Attribute.lookup(null, ATTR_CONTEXT_CODE, "StackMapTable").layout(); 1811 predefineAttribute(CODE_ATTR_StackMapTable, ATTR_CONTEXT_CODE, 1812 stackmap_bands.toArray(), 1813 stackMapDef.name(), stackMapDef.layout()); 1814 1815 predefineAttribute(CODE_ATTR_LineNumberTable, ATTR_CONTEXT_CODE, 1816 new Band[] { 1817 code_LineNumberTable_N, 1818 code_LineNumberTable_bci_P, 1819 code_LineNumberTable_line 1820 }, 1821 "LineNumberTable", "NH[PHH]"); 1822 predefineAttribute(CODE_ATTR_LocalVariableTable, ATTR_CONTEXT_CODE, 1823 new Band[] { 1824 code_LocalVariableTable_N, 1825 code_LocalVariableTable_bci_P, 1826 code_LocalVariableTable_span_O, 1827 code_LocalVariableTable_name_RU, 1828 code_LocalVariableTable_type_RS, 1829 code_LocalVariableTable_slot 1830 }, 1831 "LocalVariableTable", "NH[PHOHRUHRSHH]"); 1832 predefineAttribute(CODE_ATTR_LocalVariableTypeTable, ATTR_CONTEXT_CODE, 1833 new Band[] { 1834 code_LocalVariableTypeTable_N, 1835 code_LocalVariableTypeTable_bci_P, 1836 code_LocalVariableTypeTable_span_O, 1837 code_LocalVariableTypeTable_name_RU, 1838 code_LocalVariableTypeTable_type_RS, 1839 code_LocalVariableTypeTable_slot 1840 }, 1841 "LocalVariableTypeTable", "NH[PHOHRUHRSHH]"); 1842 predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_CODE, null, 1843 ".Overflow", ""); 1844 1845 // Clear the record of having seen these definitions, 1846 // so they may be redefined without error. 1847 for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { 1848 attrDefSeen[i] = 0; 1849 } 1850 1851 // Set up the special masks: 1852 for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { 1853 attrOverflowMask[i] = (1<<X_ATTR_OVERFLOW); 1854 attrIndexLimit[i] = 0; // will make a final decision later 1855 } 1856 attrClassFileVersionMask = (1<<CLASS_ATTR_ClassFile_version); 1857 } 1858 1859 private void adjustToMajver() { 1860 if (getPackageMajver() < JAVA6_PACKAGE_MAJOR_VERSION) { 1861 if (verbose > 0) Utils.log.fine("Legacy package version"); 1862 // Revoke definition of pre-1.6 attribute type. 1863 undefineAttribute(CODE_ATTR_StackMapTable, ATTR_CONTEXT_CODE); 1864 } 1865 } 1866 1867 protected void initAttrIndexLimit() { 1868 for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { 1869 assert(attrIndexLimit[i] == 0); // decide on it now! 1870 attrIndexLimit[i] = (haveFlagsHi(i)? 63: 32); 1871 List<Attribute.Layout> defList = attrDefs.get(i); 1872 assert(defList.size() == 32); // all predef indexes are <32 1873 int addMore = attrIndexLimit[i] - defList.size(); 1874 defList.addAll(Collections.nCopies(addMore, (Attribute.Layout) null)); 1875 } 1876 } 1877 1878 protected boolean haveFlagsHi(int ctype) { 1879 int mask = 1<<(LG_AO_HAVE_XXX_FLAGS_HI+ctype); 1880 switch (ctype) { 1881 case ATTR_CONTEXT_CLASS: 1882 assert(mask == AO_HAVE_CLASS_FLAGS_HI); break; 1883 case ATTR_CONTEXT_FIELD: 1884 assert(mask == AO_HAVE_FIELD_FLAGS_HI); break; 1885 case ATTR_CONTEXT_METHOD: 1886 assert(mask == AO_HAVE_METHOD_FLAGS_HI); break; 1887 case ATTR_CONTEXT_CODE: 1888 assert(mask == AO_HAVE_CODE_FLAGS_HI); break; 1889 default: 1890 assert(false); 1891 } 1892 return testBit(archiveOptions, mask); 1893 } 1894 1895 protected List getPredefinedAttrs(int ctype) { 1896 assert(attrIndexLimit[ctype] != 0); 1897 List<Attribute.Layout> res = new ArrayList<>(attrIndexLimit[ctype]); 1898 // Remove nulls and non-predefs. 1899 for (int ai = 0; ai < attrIndexLimit[ctype]; ai++) { 1900 if (testBit(attrDefSeen[ctype], 1L<<ai)) continue; 1901 Attribute.Layout def = attrDefs.get(ctype).get(ai); 1902 if (def == null) continue; // unused flag bit 1903 assert(isPredefinedAttr(ctype, ai)); 1904 res.add(def); 1905 } 1906 return res; 1907 } 1908 1909 protected boolean isPredefinedAttr(int ctype, int ai) { 1910 assert(attrIndexLimit[ctype] != 0); 1911 // Overflow attrs are never predefined. 1912 if (ai >= attrIndexLimit[ctype]) return false; 1913 // If the bit is set, it was explicitly def'd. 1914 if (testBit(attrDefSeen[ctype], 1L<<ai)) return false; 1915 return (attrDefs.get(ctype).get(ai) != null); 1916 } 1917 1918 protected void adjustSpecialAttrMasks() { 1919 // Clear special masks if new definitions have been seen for them. 1920 attrClassFileVersionMask &= ~ attrDefSeen[ATTR_CONTEXT_CLASS]; 1921 // It is possible to clear the overflow mask (bit 16). 1922 for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { 1923 attrOverflowMask[i] &= ~ attrDefSeen[i]; 1924 } 1925 } 1926 1927 protected Attribute makeClassFileVersionAttr(int minver, int majver) { 1928 byte[] bytes = { 1929 (byte)(minver >> 8), (byte)minver, 1930 (byte)(majver >> 8), (byte)majver 1931 }; 1932 return attrClassFileVersion.addContent(bytes); 1933 } 1934 1935 protected short[] parseClassFileVersionAttr(Attribute attr) { 1936 assert(attr.layout() == attrClassFileVersion); 1937 assert(attr.size() == 4); 1938 byte[] bytes = attr.bytes(); 1939 int minver = ((bytes[0] & 0xFF) << 8) | (bytes[1] & 0xFF); 1940 int majver = ((bytes[2] & 0xFF) << 8) | (bytes[3] & 0xFF); 1941 return new short[]{ (short) minver, (short) majver }; 1942 } 1943 1944 private boolean assertBandOKForElems(Band[] ab, Attribute.Layout.Element[] elems) { 1945 for (int i = 0; i < elems.length; i++) { 1946 assert(assertBandOKForElem(ab, elems[i])); 1947 } 1948 return true; 1949 } 1950 private boolean assertBandOKForElem(Band[] ab, Attribute.Layout.Element e) { 1951 Band b = null; 1952 if (e.bandIndex != Attribute.NO_BAND_INDEX) 1953 b = ab[e.bandIndex]; 1954 Coding rc = UNSIGNED5; 1955 boolean wantIntBand = true; 1956 switch (e.kind) { 1957 case Attribute.EK_INT: 1958 if (e.flagTest(Attribute.EF_SIGN)) { 1959 rc = SIGNED5; 1960 } else if (e.len == 1) { 1961 rc = BYTE1; 1962 } 1963 break; 1964 case Attribute.EK_BCI: 1965 if (!e.flagTest(Attribute.EF_DELTA)) { 1966 rc = BCI5; 1967 } else { 1968 rc = BRANCH5; 1969 } 1970 break; 1971 case Attribute.EK_BCO: 1972 rc = BRANCH5; 1973 break; 1974 case Attribute.EK_FLAG: 1975 if (e.len == 1) rc = BYTE1; 1976 break; 1977 case Attribute.EK_REPL: 1978 if (e.len == 1) rc = BYTE1; 1979 assertBandOKForElems(ab, e.body); 1980 break; 1981 case Attribute.EK_UN: 1982 if (e.flagTest(Attribute.EF_SIGN)) { 1983 rc = SIGNED5; 1984 } else if (e.len == 1) { 1985 rc = BYTE1; 1986 } 1987 assertBandOKForElems(ab, e.body); 1988 break; 1989 case Attribute.EK_CASE: 1990 assert(b == null); 1991 assertBandOKForElems(ab, e.body); 1992 return true; // no direct band 1993 case Attribute.EK_CALL: 1994 assert(b == null); 1995 return true; // no direct band 1996 case Attribute.EK_CBLE: 1997 assert(b == null); 1998 assertBandOKForElems(ab, e.body); 1999 return true; // no direct band 2000 case Attribute.EK_REF: 2001 wantIntBand = false; 2002 assert(b instanceof CPRefBand); 2003 assert(((CPRefBand)b).nullOK == e.flagTest(Attribute.EF_NULL)); 2004 break; 2005 default: assert(false); 2006 } 2007 assert(b.regularCoding == rc) 2008 : (e+" // "+b); 2009 if (wantIntBand) 2010 assert(b instanceof IntBand); 2011 return true; 2012 } 2013 2014 private 2015 Attribute.Layout predefineAttribute(int index, int ctype, Band[] ab, 2016 String name, String layout) { 2017 // Use Attribute.find to get uniquification of layouts. 2018 Attribute.Layout def = Attribute.find(ctype, name, layout).layout(); 2019 //def.predef = true; 2020 if (index >= 0) { 2021 setAttributeLayoutIndex(def, index); 2022 } 2023 if (ab == null) { 2024 ab = new Band[0]; 2025 } 2026 assert(attrBandTable.get(def) == null); // no redef 2027 attrBandTable.put(def, ab); 2028 assert(def.bandCount == ab.length) 2029 : (def+" // "+Arrays.asList(ab)); 2030 // Let's make sure the band types match: 2031 assert(assertBandOKForElems(ab, def.elems)); 2032 return def; 2033 } 2034 2035 // This version takes bandPrefix/addHere instead of prebuilt Band[] ab. 2036 private 2037 Attribute.Layout predefineAttribute(int index, 2038 String bandPrefix, MultiBand addHere, 2039 Attribute attr) { 2040 //Attribute.Layout def = Attribute.find(ctype, name, layout).layout(); 2041 Attribute.Layout def = attr.layout(); 2042 int ctype = def.ctype(); 2043 return predefineAttribute(index, ctype, 2044 makeNewAttributeBands(bandPrefix, def, 2045 addHere), 2046 def.name(), def.layout()); 2047 } 2048 2049 private 2050 void undefineAttribute(int index, int ctype) { 2051 if (verbose > 1) { 2052 System.out.println("Removing predefined "+ATTR_CONTEXT_NAME[ctype]+ 2053 " attribute on bit "+index); 2054 } 2055 List<Attribute.Layout> defList = attrDefs.get(ctype); 2056 Attribute.Layout def = defList.get(index); 2057 assert(def != null); 2058 defList.set(index, null); 2059 attrIndexTable.put(def, null); 2060 // Clear the def bit. (For predefs, it's already clear.) 2061 assert(index < 64); 2062 attrDefSeen[ctype] &= ~(1L<<index); 2063 attrFlagMask[ctype] &= ~(1L<<index); 2064 Band[] ab = attrBandTable.get(def); 2065 for (int j = 0; j < ab.length; j++) { 2066 ab[j].doneWithUnusedBand(); 2067 } 2068 } 2069 2070 // Bands which contain non-predefined attrs. 2071 protected MultiBand[] attrBands = new MultiBand[ATTR_CONTEXT_LIMIT]; 2072 { 2073 attrBands[ATTR_CONTEXT_CLASS] = class_attr_bands; 2074 attrBands[ATTR_CONTEXT_FIELD] = field_attr_bands; 2075 attrBands[ATTR_CONTEXT_METHOD] = method_attr_bands; 2076 attrBands[ATTR_CONTEXT_CODE] = code_attr_bands; 2077 } 2078 2079 // Create bands for all non-predefined attrs. 2080 void makeNewAttributeBands() { 2081 // Retract special flag bit bindings, if they were taken over. 2082 adjustSpecialAttrMasks(); 2083 2084 for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) { 2085 String cname = ATTR_CONTEXT_NAME[ctype]; 2086 MultiBand xxx_attr_bands = attrBands[ctype]; 2087 long defSeen = attrDefSeen[ctype]; 2088 // Note: attrDefSeen is always a subset of attrFlagMask. 2089 assert((defSeen & ~attrFlagMask[ctype]) == 0); 2090 for (int i = 0; i < attrDefs.get(ctype).size(); i++) { 2091 Attribute.Layout def = attrDefs.get(ctype).get(i); 2092 if (def == null) continue; // unused flag bit 2093 if (def.bandCount == 0) continue; // empty attr 2094 if (i < attrIndexLimit[ctype] && !testBit(defSeen, 1L<<i)) { 2095 // There are already predefined bands here. 2096 assert(attrBandTable.get(def) != null); 2097 continue; 2098 } 2099 int base = xxx_attr_bands.size(); 2100 String pfx = cname+"_"+def.name()+"_"; // debug only 2101 if (verbose > 1) 2102 Utils.log.fine("Making new bands for "+def); 2103 Band[] newAB = makeNewAttributeBands(pfx, def, 2104 xxx_attr_bands); 2105 assert(newAB.length == def.bandCount); 2106 Band[] prevAB = attrBandTable.put(def, newAB); 2107 if (prevAB != null) { 2108 // We won't be using these predefined bands. 2109 for (int j = 0; j < prevAB.length; j++) { 2110 prevAB[j].doneWithUnusedBand(); 2111 } 2112 } 2113 } 2114 } 2115 //System.out.println(prevForAssertMap); 2116 } 2117 private 2118 Band[] makeNewAttributeBands(String pfx, Attribute.Layout def, 2119 MultiBand addHere) { 2120 int base = addHere.size(); 2121 makeNewAttributeBands(pfx, def.elems, addHere); 2122 int nb = addHere.size() - base; 2123 Band[] newAB = new Band[nb]; 2124 for (int i = 0; i < nb; i++) { 2125 newAB[i] = addHere.get(base+i); 2126 } 2127 return newAB; 2128 } 2129 // Recursive helper, operates on a "body" or other sequence of elems: 2130 private 2131 void makeNewAttributeBands(String pfx, Attribute.Layout.Element[] elems, 2132 MultiBand ab) { 2133 for (int i = 0; i < elems.length; i++) { 2134 Attribute.Layout.Element e = elems[i]; 2135 String name = pfx+ab.size()+"_"+e.layout; 2136 { 2137 int tem; 2138 if ((tem = name.indexOf('[')) > 0) 2139 name = name.substring(0, tem); 2140 if ((tem = name.indexOf('(')) > 0) 2141 name = name.substring(0, tem); 2142 if (name.endsWith("H")) 2143 name = name.substring(0, name.length()-1); 2144 } 2145 Band nb; 2146 switch (e.kind) { 2147 case Attribute.EK_INT: 2148 nb = newElemBand(e, name, ab); 2149 break; 2150 case Attribute.EK_BCI: 2151 if (!e.flagTest(Attribute.EF_DELTA)) { 2152 // PH: transmit R(bci), store bci 2153 nb = ab.newIntBand(name, BCI5); 2154 } else { 2155 // POH: transmit D(R(bci)), store bci 2156 nb = ab.newIntBand(name, BRANCH5); 2157 } 2158 // Note: No case for BYTE1 here. 2159 break; 2160 case Attribute.EK_BCO: 2161 // OH: transmit D(R(bci)), store D(bci) 2162 nb = ab.newIntBand(name, BRANCH5); 2163 // Note: No case for BYTE1 here. 2164 break; 2165 case Attribute.EK_FLAG: 2166 assert(!e.flagTest(Attribute.EF_SIGN)); 2167 nb = newElemBand(e, name, ab); 2168 break; 2169 case Attribute.EK_REPL: 2170 assert(!e.flagTest(Attribute.EF_SIGN)); 2171 nb = newElemBand(e, name, ab); 2172 makeNewAttributeBands(pfx, e.body, ab); 2173 break; 2174 case Attribute.EK_UN: 2175 nb = newElemBand(e, name, ab); 2176 makeNewAttributeBands(pfx, e.body, ab); 2177 break; 2178 case Attribute.EK_CASE: 2179 if (!e.flagTest(Attribute.EF_BACK)) { 2180 // If it's not a duplicate body, make the bands. 2181 makeNewAttributeBands(pfx, e.body, ab); 2182 } 2183 continue; // no new band to make 2184 case Attribute.EK_REF: 2185 byte refKind = e.refKind; 2186 boolean nullOK = e.flagTest(Attribute.EF_NULL); 2187 nb = ab.newCPRefBand(name, UNSIGNED5, refKind, nullOK); 2188 // Note: No case for BYTE1 here. 2189 break; 2190 case Attribute.EK_CALL: 2191 continue; // no new band to make 2192 case Attribute.EK_CBLE: 2193 makeNewAttributeBands(pfx, e.body, ab); 2194 continue; // no new band to make 2195 default: assert(false); continue; 2196 } 2197 if (verbose > 1) { 2198 Utils.log.fine("New attribute band "+nb); 2199 } 2200 } 2201 } 2202 private 2203 Band newElemBand(Attribute.Layout.Element e, String name, MultiBand ab) { 2204 if (e.flagTest(Attribute.EF_SIGN)) { 2205 return ab.newIntBand(name, SIGNED5); 2206 } else if (e.len == 1) { 2207 return ab.newIntBand(name, BYTE1); // Not ByteBand, please. 2208 } else { 2209 return ab.newIntBand(name, UNSIGNED5); 2210 } 2211 } 2212 2213 protected int setAttributeLayoutIndex(Attribute.Layout def, int index) { 2214 int ctype = def.ctype; 2215 assert(ATTR_INDEX_OVERFLOW <= index && index < attrIndexLimit[ctype]); 2216 List<Attribute.Layout> defList = attrDefs.get(ctype); 2217 if (index == ATTR_INDEX_OVERFLOW) { 2218 // Overflow attribute. 2219 index = defList.size(); 2220 defList.add(def); 2221 if (verbose > 0) 2222 Utils.log.info("Adding new attribute at "+def +": "+index); 2223 attrIndexTable.put(def, index); 2224 return index; 2225 } 2226 2227 // Detect redefinitions: 2228 if (testBit(attrDefSeen[ctype], 1L<<index)) { 2229 throw new RuntimeException("Multiple explicit definition at "+index+": "+def); 2230 } 2231 attrDefSeen[ctype] |= (1L<<index); 2232 2233 // Adding a new fixed attribute. 2234 assert(0 <= index && index < attrIndexLimit[ctype]); 2235 if (verbose > (attrClassFileVersionMask == 0? 2:0)) 2236 Utils.log.fine("Fixing new attribute at "+index 2237 +": "+def 2238 +(defList.get(index) == null? "": 2239 "; replacing "+defList.get(index))); 2240 attrFlagMask[ctype] |= (1L<<index); 2241 // Remove index binding of any previous fixed attr. 2242 attrIndexTable.put(defList.get(index), null); 2243 defList.set(index, def); 2244 attrIndexTable.put(def, index); 2245 return index; 2246 } 2247 2248 // encodings found in the code_headers band 2249 private static final int[][] shortCodeLimits = { 2250 { 12, 12 }, // s<12, l<12, e=0 [1..144] 2251 { 8, 8 }, // s<8, l<8, e=1 [145..208] 2252 { 7, 7 }, // s<7, l<7, e=2 [209..256] 2253 }; 2254 public final int shortCodeHeader_h_limit = shortCodeLimits.length; 2255 2256 // return 0 if it won't encode, else a number in [1..255] 2257 static int shortCodeHeader(Code code) { 2258 int s = code.max_stack; 2259 int l0 = code.max_locals; 2260 int h = code.handler_class.length; 2261 if (h >= shortCodeLimits.length) return LONG_CODE_HEADER; 2262 int siglen = code.getMethod().getArgumentSize(); 2263 assert(l0 >= siglen); // enough locals for signature! 2264 if (l0 < siglen) return LONG_CODE_HEADER; 2265 int l1 = l0 - siglen; // do not count locals required by the signature 2266 int lims = shortCodeLimits[h][0]; 2267 int liml = shortCodeLimits[h][1]; 2268 if (s >= lims || l1 >= liml) return LONG_CODE_HEADER; 2269 int sc = shortCodeHeader_h_base(h); 2270 sc += s + lims*l1; 2271 if (sc > 255) return LONG_CODE_HEADER; 2272 assert(shortCodeHeader_max_stack(sc) == s); 2273 assert(shortCodeHeader_max_na_locals(sc) == l1); 2274 assert(shortCodeHeader_handler_count(sc) == h); 2275 return sc; 2276 } 2277 2278 static final int LONG_CODE_HEADER = 0; 2279 static int shortCodeHeader_handler_count(int sc) { 2280 assert(sc > 0 && sc <= 255); 2281 for (int h = 0; ; h++) { 2282 if (sc < shortCodeHeader_h_base(h+1)) 2283 return h; 2284 } 2285 } 2286 static int shortCodeHeader_max_stack(int sc) { 2287 int h = shortCodeHeader_handler_count(sc); 2288 int lims = shortCodeLimits[h][0]; 2289 return (sc - shortCodeHeader_h_base(h)) % lims; 2290 } 2291 static int shortCodeHeader_max_na_locals(int sc) { 2292 int h = shortCodeHeader_handler_count(sc); 2293 int lims = shortCodeLimits[h][0]; 2294 return (sc - shortCodeHeader_h_base(h)) / lims; 2295 } 2296 2297 private static int shortCodeHeader_h_base(int h) { 2298 assert(h <= shortCodeLimits.length); 2299 int sc = 1; 2300 for (int h0 = 0; h0 < h; h0++) { 2301 int lims = shortCodeLimits[h0][0]; 2302 int liml = shortCodeLimits[h0][1]; 2303 sc += lims * liml; 2304 } 2305 return sc; 2306 } 2307 2308 // utilities for accessing the bc_label band: 2309 protected void putLabel(IntBand bc_label, Code c, int pc, int targetPC) { 2310 bc_label.putInt(c.encodeBCI(targetPC) - c.encodeBCI(pc)); 2311 } 2312 protected int getLabel(IntBand bc_label, Code c, int pc) { 2313 return c.decodeBCI(bc_label.getInt() + c.encodeBCI(pc)); 2314 } 2315 2316 protected CPRefBand getCPRefOpBand(int bc) { 2317 switch (Instruction.getCPRefOpTag(bc)) { 2318 case CONSTANT_Class: 2319 return bc_classref; 2320 case CONSTANT_Fieldref: 2321 return bc_fieldref; 2322 case CONSTANT_Methodref: 2323 return bc_methodref; 2324 case CONSTANT_InterfaceMethodref: 2325 return bc_imethodref; 2326 case CONSTANT_Literal: 2327 switch (bc) { 2328 case _ildc: case _ildc_w: 2329 return bc_intref; 2330 case _fldc: case _fldc_w: 2331 return bc_floatref; 2332 case _lldc2_w: 2333 return bc_longref; 2334 case _dldc2_w: 2335 return bc_doubleref; 2336 case _aldc: case _aldc_w: 2337 return bc_stringref; 2338 case _cldc: case _cldc_w: 2339 return bc_classref; 2340 } 2341 break; 2342 } 2343 assert(false); 2344 return null; 2345 } 2346 2347 protected CPRefBand selfOpRefBand(int self_bc) { 2348 assert(Instruction.isSelfLinkerOp(self_bc)); 2349 int idx = (self_bc - _self_linker_op); 2350 boolean isSuper = (idx >= _self_linker_super_flag); 2351 if (isSuper) idx -= _self_linker_super_flag; 2352 boolean isAload = (idx >= _self_linker_aload_flag); 2353 if (isAload) idx -= _self_linker_aload_flag; 2354 int origBC = _first_linker_op + idx; 2355 boolean isField = Instruction.isFieldOp(origBC); 2356 if (!isSuper) 2357 return isField? bc_thisfield: bc_thismethod; 2358 else 2359 return isField? bc_superfield: bc_supermethod; 2360 } 2361 2362 //////////////////////////////////////////////////////////////////// 2363 2364 static int nextSeqForDebug; 2365 static File dumpDir = null; 2366 static OutputStream getDumpStream(Band b, String ext) throws IOException { 2367 return getDumpStream(b.name, b.seqForDebug, ext, b); 2368 } 2369 static OutputStream getDumpStream(Index ix, String ext) throws IOException { 2370 if (ix.size() == 0) return new ByteArrayOutputStream(); 2371 int seq = ConstantPool.TAG_ORDER[ix.cpMap[0].tag]; 2372 return getDumpStream(ix.debugName, seq, ext, ix); 2373 } 2374 static OutputStream getDumpStream(String name, int seq, String ext, Object b) throws IOException { 2375 if (dumpDir == null) { 2376 dumpDir = File.createTempFile("BD_", "", new File(".")); 2377 dumpDir.delete(); 2378 if (dumpDir.mkdir()) 2379 Utils.log.info("Dumping bands to "+dumpDir); 2380 } 2381 name = name.replace('(', ' ').replace(')', ' '); 2382 name = name.replace('/', ' '); 2383 name = name.replace('*', ' '); 2384 name = name.trim().replace(' ','_'); 2385 name = ((10000+seq) + "_" + name).substring(1); 2386 File dumpFile = new File(dumpDir, name+ext); 2387 Utils.log.info("Dumping "+b+" to "+dumpFile); 2388 return new BufferedOutputStream(new FileOutputStream(dumpFile)); 2389 } 2390 2391 // DEBUG ONLY: Validate me at each length change. 2392 static boolean assertCanChangeLength(Band b) { 2393 switch (b.phase) { 2394 case COLLECT_PHASE: 2395 case READ_PHASE: 2396 return true; 2397 } 2398 return false; 2399 } 2400 2401 // DEBUG ONLY: Validate a phase. 2402 static boolean assertPhase(Band b, int phaseExpected) { 2403 if (b.phase() != phaseExpected) { 2404 Utils.log.warning("phase expected "+phaseExpected+" was "+b.phase()+" in "+b); 2405 return false; 2406 } 2407 return true; 2408 } 2409 2410 2411 // DEBUG ONLY: Tells whether verbosity is turned on. 2412 static int verbose() { 2413 return Utils.currentPropMap().getInteger(Utils.DEBUG_VERBOSE); 2414 } 2415 2416 2417 // DEBUG ONLY: Validate me at each phase change. 2418 static boolean assertPhaseChangeOK(Band b, int p0, int p1) { 2419 switch (p0*10+p1) { 2420 /// Writing phases: 2421 case NO_PHASE*10+COLLECT_PHASE: 2422 // Ready to collect data from the input classes. 2423 assert(!b.isReader()); 2424 assert(b.capacity() >= 0); 2425 assert(b.length() == 0); 2426 return true; 2427 case COLLECT_PHASE*10+FROZEN_PHASE: 2428 case FROZEN_PHASE*10+FROZEN_PHASE: 2429 assert(b.length() == 0); 2430 return true; 2431 case COLLECT_PHASE*10+WRITE_PHASE: 2432 case FROZEN_PHASE*10+WRITE_PHASE: 2433 // Data is all collected. Ready to write bytes to disk. 2434 return true; 2435 case WRITE_PHASE*10+DONE_PHASE: 2436 // Done writing to disk. Ready to reset, in principle. 2437 return true; 2438 2439 /// Reading phases: 2440 case NO_PHASE*10+EXPECT_PHASE: 2441 assert(b.isReader()); 2442 assert(b.capacity() < 0); 2443 return true; 2444 case EXPECT_PHASE*10+READ_PHASE: 2445 // Ready to read values from disk. 2446 assert(Math.max(0,b.capacity()) >= b.valuesExpected()); 2447 assert(b.length() <= 0); 2448 return true; 2449 case READ_PHASE*10+DISBURSE_PHASE: 2450 // Ready to disburse values. 2451 assert(b.valuesRemainingForDebug() == b.length()); 2452 return true; 2453 case DISBURSE_PHASE*10+DONE_PHASE: 2454 // Done disbursing values. Ready to reset, in principle. 2455 assert(assertDoneDisbursing(b)); 2456 return true; 2457 } 2458 if (p0 == p1) 2459 Utils.log.warning("Already in phase "+p0); 2460 else 2461 Utils.log.warning("Unexpected phase "+p0+" -> "+p1); 2462 return false; 2463 } 2464 2465 static private boolean assertDoneDisbursing(Band b) { 2466 if (b.phase != DISBURSE_PHASE) { 2467 Utils.log.warning("assertDoneDisbursing: still in phase "+b.phase+": "+b); 2468 if (verbose() <= 1) return false; // fail now 2469 } 2470 int left = b.valuesRemainingForDebug(); 2471 if (left > 0) { 2472 Utils.log.warning("assertDoneDisbursing: "+left+" values left in "+b); 2473 if (verbose() <= 1) return false; // fail now 2474 } 2475 if (b instanceof MultiBand) { 2476 MultiBand mb = (MultiBand) b; 2477 for (int i = 0; i < mb.bandCount; i++) { 2478 Band sub = mb.bands[i]; 2479 if (sub.phase != DONE_PHASE) { 2480 Utils.log.warning("assertDoneDisbursing: sub-band still in phase "+sub.phase+": "+sub); 2481 if (verbose() <= 1) return false; // fail now 2482 } 2483 } 2484 } 2485 return true; 2486 } 2487 2488 static private void printCDecl(Band b) { 2489 if (b instanceof MultiBand) { 2490 MultiBand mb = (MultiBand) b; 2491 for (int i = 0; i < mb.bandCount; i++) { 2492 printCDecl(mb.bands[i]); 2493 } 2494 return; 2495 } 2496 String ixS = "NULL"; 2497 if (b instanceof CPRefBand) { 2498 Index ix = ((CPRefBand)b).index; 2499 if (ix != null) ixS = "INDEX("+ix.debugName+")"; 2500 } 2501 Coding[] knownc = { BYTE1, CHAR3, BCI5, BRANCH5, UNSIGNED5, 2502 UDELTA5, SIGNED5, DELTA5, MDELTA5 }; 2503 String[] knowns = { "BYTE1", "CHAR3", "BCI5", "BRANCH5", "UNSIGNED5", 2504 "UDELTA5", "SIGNED5", "DELTA5", "MDELTA5" }; 2505 Coding rc = b.regularCoding; 2506 int rci = Arrays.asList(knownc).indexOf(rc); 2507 String cstr; 2508 if (rci >= 0) 2509 cstr = knowns[rci]; 2510 else 2511 cstr = "CODING"+rc.keyString(); 2512 System.out.println(" BAND_INIT(\""+b.name()+"\"" 2513 +", "+cstr+", "+ixS+"),"); 2514 } 2515 2516 private Map<Band, Band> prevForAssertMap; 2517 2518 // DEBUG ONLY: Record something about the band order. 2519 boolean notePrevForAssert(Band b, Band p) { 2520 if (prevForAssertMap == null) 2521 prevForAssertMap = new HashMap<>(); 2522 prevForAssertMap.put(b, p); 2523 return true; 2524 } 2525 2526 // DEBUG ONLY: Validate next input band. 2527 private boolean assertReadyToReadFrom(Band b, InputStream in) throws IOException { 2528 Band p = prevForAssertMap.get(b); 2529 // Any previous band must be done reading before this one starts. 2530 if (p != null && phaseCmp(p.phase(), DISBURSE_PHASE) < 0) { 2531 Utils.log.warning("Previous band not done reading."); 2532 Utils.log.info(" Previous band: "+p); 2533 Utils.log.info(" Next band: "+b); 2534 Thread.dumpStack(); 2535 assert(verbose > 0); // die unless verbose is true 2536 } 2537 String name = b.name; 2538 if (optDebugBands && !name.startsWith("(")) { 2539 // Verify synchronization between reader & writer: 2540 StringBuilder buf = new StringBuilder(); 2541 int ch; 2542 while ((ch = in.read()) > 0) 2543 buf.append((char)ch); 2544 String inName = buf.toString(); 2545 if (!inName.equals(name)) { 2546 StringBuilder sb = new StringBuilder(); 2547 sb.append("Expected "+name+" but read: "); 2548 inName += (char)ch; 2549 while (inName.length() < 10) { 2550 inName += (char) in.read(); 2551 } 2552 for (int i = 0; i < inName.length(); i++) { 2553 sb.append(inName.charAt(i)); 2554 } 2555 Utils.log.warning(sb.toString()); 2556 return false; 2557 } 2558 } 2559 return true; 2560 } 2561 2562 // DEBUG ONLY: Make sure a bunch of cprefs are correct. 2563 private boolean assertValidCPRefs(CPRefBand b) { 2564 if (b.index == null) return true; 2565 int limit = b.index.size()+1; 2566 for (int i = 0; i < b.length(); i++) { 2567 int v = b.valueAtForDebug(i); 2568 if (v < 0 || v >= limit) { 2569 Utils.log.warning("CP ref out of range "+ 2570 "["+i+"] = "+v+" in "+b); 2571 return false; 2572 } 2573 } 2574 return true; 2575 } 2576 2577 // DEBUG ONLY: Maybe write a debugging cookie to next output band. 2578 private boolean assertReadyToWriteTo(Band b, OutputStream out) throws IOException { 2579 Band p = prevForAssertMap.get(b); 2580 // Any previous band must be done writing before this one starts. 2581 if (p != null && phaseCmp(p.phase(), DONE_PHASE) < 0) { 2582 Utils.log.warning("Previous band not done writing."); 2583 Utils.log.info(" Previous band: "+p); 2584 Utils.log.info(" Next band: "+b); 2585 Thread.dumpStack(); 2586 assert(verbose > 0); // die unless verbose is true 2587 } 2588 String name = b.name; 2589 if (optDebugBands && !name.startsWith("(")) { 2590 // Verify synchronization between reader & writer: 2591 for (int j = 0; j < name.length(); j++) { 2592 out.write((byte)name.charAt(j)); 2593 } 2594 out.write((byte)0); 2595 } 2596 return true; 2597 } 2598 2599 protected static boolean testBit(int flags, int bitMask) { 2600 return (flags & bitMask) != 0; 2601 } 2602 protected static int setBit(int flags, int bitMask, boolean z) { 2603 return z ? (flags | bitMask) : (flags &~ bitMask); 2604 } 2605 protected static boolean testBit(long flags, long bitMask) { 2606 return (flags & bitMask) != 0; 2607 } 2608 protected static long setBit(long flags, long bitMask, boolean z) { 2609 return z ? (flags | bitMask) : (flags &~ bitMask); 2610 } 2611 2612 2613 static void printArrayTo(PrintStream ps, int[] values, int start, int end) { 2614 int len = end-start; 2615 for (int i = 0; i < len; i++) { 2616 if (i % 10 == 0) 2617 ps.println(); 2618 else 2619 ps.print(" "); 2620 ps.print(values[start+i]); 2621 } 2622 ps.println(); 2623 } 2624 2625 static void printArrayTo(PrintStream ps, Entry[] cpMap, int start, int end) { 2626 StringBuffer buf = new StringBuffer(); 2627 int len = end-start; 2628 for (int i = 0; i < len; i++) { 2629 String s = cpMap[start+i].stringValue(); 2630 buf.setLength(0); 2631 for (int j = 0; j < s.length(); j++) { 2632 char ch = s.charAt(j); 2633 if (!(ch < ' ' || ch > '~' || ch == '\\')) { 2634 buf.append(ch); 2635 } else if (ch == '\n') { 2636 buf.append("\\n"); 2637 } else if (ch == '\t') { 2638 buf.append("\\t"); 2639 } else if (ch == '\r') { 2640 buf.append("\\r"); 2641 } else { 2642 buf.append("\\x"+Integer.toHexString(ch)); 2643 } 2644 } 2645 ps.println(buf); 2646 } 2647 } 2648 2649 2650 // Utilities for reallocating: 2651 protected static Object[] realloc(Object[] a, int len) { 2652 java.lang.Class elt = a.getClass().getComponentType(); 2653 Object[] na = (Object[]) java.lang.reflect.Array.newInstance(elt, len); 2654 System.arraycopy(a, 0, na, 0, Math.min(a.length, len)); 2655 return na; 2656 } 2657 protected static Object[] realloc(Object[] a) { 2658 return realloc(a, Math.max(10, a.length*2)); 2659 } 2660 2661 protected static int[] realloc(int[] a, int len) { 2662 if (len == 0) return noInts; 2663 if (a == null) return new int[len]; 2664 int[] na = new int[len]; 2665 System.arraycopy(a, 0, na, 0, Math.min(a.length, len)); 2666 return na; 2667 } 2668 protected static int[] realloc(int[] a) { 2669 return realloc(a, Math.max(10, a.length*2)); 2670 } 2671 2672 protected static byte[] realloc(byte[] a, int len) { 2673 if (len == 0) return noBytes; 2674 if (a == null) return new byte[len]; 2675 byte[] na = new byte[len]; 2676 System.arraycopy(a, 0, na, 0, Math.min(a.length, len)); 2677 return na; 2678 } 2679 protected static byte[] realloc(byte[] a) { 2680 return realloc(a, Math.max(10, a.length*2)); 2681 } 2682 }