1 /* 2 * Copyright (c) 2001, 2011, 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 addValue(encodeRefOrNull(e, index)); 1007 } 1008 public void putRef(Entry e, Index index) { 1009 assert(this.index == null); 1010 addValue(encodeRefOrNull(e, index)); 1011 } 1012 public void putRef(Entry e, byte cptag) { 1013 putRef(e, getCPIndex(cptag)); 1014 } 1015 1016 public Entry getRef() { 1017 if (index == null) Utils.log.warning("No index for "+this); 1018 assert(index != null); 1019 return decodeRefOrNull(getValue(), index); 1020 } 1021 public Entry getRef(Index index) { 1022 assert(this.index == null); 1023 return decodeRefOrNull(getValue(), index); 1024 } 1025 public Entry getRef(byte cptag) { 1026 return getRef(getCPIndex(cptag)); 1027 } 1028 1029 private int encodeRefOrNull(Entry e, Index index) { 1030 int nonNullCode; // NNC is the coding which assumes nulls are rare 1031 if (e == null) { 1032 nonNullCode = -1; // negative values are rare 1033 } else { 1034 nonNullCode = encodeRef(e, index); 1035 } 1036 // If nulls are expected, increment, to make -1 code turn to 0. 1037 return (nullOK ? 1 : 0) + nonNullCode; 1038 } 1039 private Entry decodeRefOrNull(int code, Index index) { 1040 // Inverse to encodeRefOrNull... 1041 int nonNullCode = code - (nullOK ? 1 : 0); 1042 if (nonNullCode == -1) { 1043 return null; 1044 } else { 1045 return decodeRef(nonNullCode, index); 1046 } 1047 } 1048 } 1049 1050 // Bootstrap support for CPRefBands. These are needed to record 1051 // intended CP indexes, before the CP has been created. 1052 private final List<CPRefBand> allKQBands = new ArrayList<>(); 1053 private List<Object[]> needPredefIndex = new ArrayList<>(); 1054 1055 1056 int encodeRef(Entry e, Index ix) { 1057 if (ix == null) 1058 throw new RuntimeException("null index for " + e.stringValue()); 1059 int coding = ix.indexOf(e); 1060 if (verbose > 2) 1061 Utils.log.fine("putRef "+coding+" => "+e); 1062 return coding; 1063 } 1064 1065 Entry decodeRef(int n, Index ix) { 1066 if (n < 0 || n >= ix.size()) 1067 Utils.log.warning("decoding bad ref "+n+" in "+ix); 1068 Entry e = ix.getEntry(n); 1069 if (verbose > 2) 1070 Utils.log.fine("getRef "+n+" => "+e); 1071 return e; 1072 } 1073 1074 private CodingChooser codingChooser; 1075 protected CodingChooser getCodingChooser() { 1076 if (codingChooser == null) { 1077 codingChooser = new CodingChooser(effort, basicCodings); 1078 if (codingChooser.stress != null 1079 && this instanceof PackageWriter) { 1080 // Twist the random state based on my first file. 1081 // This sends each segment off in a different direction. 1082 List<Package.Class> classes = ((PackageWriter)this).pkg.classes; 1083 if (!classes.isEmpty()) { 1084 Package.Class cls = classes.get(0); 1085 codingChooser.addStressSeed(cls.getName().hashCode()); 1086 } 1087 } 1088 } 1089 return codingChooser; 1090 } 1091 1092 public CodingMethod chooseCoding(int[] values, int start, int end, 1093 Coding regular, String bandName, 1094 int[] sizes) { 1095 assert(optVaryCodings); 1096 if (effort <= MIN_EFFORT) { 1097 return regular; 1098 } 1099 CodingChooser cc = getCodingChooser(); 1100 if (verbose > 1 || cc.verbose > 1) { 1101 Utils.log.fine("--- chooseCoding "+bandName); 1102 } 1103 return cc.choose(values, start, end, regular, sizes); 1104 } 1105 1106 static final byte[] defaultMetaCoding = { _meta_default }; 1107 static final byte[] noMetaCoding = {}; 1108 1109 // The first value in a band is always coded with the default coding D. 1110 // If this first value X is an escape value, it actually represents the 1111 // first (and perhaps only) byte of a meta-coding. 1112 // 1113 // If D.S != 0 and D includes the range [-256..-1], 1114 // the escape values are in that range, 1115 // and the first byte XB is -1-X. 1116 // 1117 // If D.S == 0 and D includes the range [(D.L)..(D.L)+255], 1118 // the escape values are in that range, 1119 // and XB is X-(D.L). 1120 // 1121 // This representation is designed so that a band header is unlikely 1122 // to be confused with the initial value of a headerless band, 1123 // and yet so that a band header is likely to occupy only a byte or two. 1124 // 1125 // Result is in [0..255] if XB was successfully extracted, else -1. 1126 // See section "Coding Specifier Meta-Encoding" in the JSR 200 spec. 1127 protected static int decodeEscapeValue(int X, Coding regularCoding) { 1128 // The first value in a band is always coded with the default coding D. 1129 // If this first value X is an escape value, it actually represents the 1130 // first (and perhaps only) byte of a meta-coding. 1131 // Result is in [0..255] if XB was successfully extracted, else -1. 1132 if (regularCoding.B() == 1 || regularCoding.L() == 0) 1133 return -1; // degenerate regular coding (BYTE1) 1134 if (regularCoding.S() != 0) { 1135 if (-256 <= X && X <= -1 && regularCoding.min() <= -256) { 1136 int XB = -1-X; 1137 assert(XB >= 0 && XB < 256); 1138 return XB; 1139 } 1140 } else { 1141 int L = regularCoding.L(); 1142 if (L <= X && X <= L+255 && regularCoding.max() >= L+255) { 1143 int XB = X-L; 1144 assert(XB >= 0 && XB < 256); 1145 return XB; 1146 } 1147 } 1148 return -1; // negative value for failure 1149 } 1150 // Inverse to decodeEscapeValue(). 1151 protected static int encodeEscapeValue(int XB, Coding regularCoding) { 1152 assert(XB >= 0 && XB < 256); 1153 assert(regularCoding.B() > 1 && regularCoding.L() > 0); 1154 int X; 1155 if (regularCoding.S() != 0) { 1156 assert(regularCoding.min() <= -256); 1157 X = -1-XB; 1158 } else { 1159 int L = regularCoding.L(); 1160 assert(regularCoding.max() >= L+255); 1161 X = XB+L; 1162 } 1163 assert(decodeEscapeValue(X, regularCoding) == XB) 1164 : (regularCoding+" XB="+XB+" X="+X); 1165 return X; 1166 } 1167 1168 static { 1169 boolean checkXB = false; 1170 assert(checkXB = true); 1171 if (checkXB) { 1172 for (int i = 0; i < basicCodings.length; i++) { 1173 Coding D = basicCodings[i]; 1174 if (D == null) continue; 1175 if (D.B() == 1) continue; 1176 if (D.L() == 0) continue; 1177 for (int XB = 0; XB <= 255; XB++) { 1178 // The following exercises decodeEscapeValue also: 1179 encodeEscapeValue(XB, D); 1180 } 1181 } 1182 } 1183 } 1184 1185 class MultiBand extends Band { 1186 MultiBand(String name, Coding regularCoding) { 1187 super(name, regularCoding); 1188 } 1189 1190 public Band init() { 1191 super.init(); 1192 // This is all just to keep the asserts happy: 1193 setCapacity(0); 1194 if (phase() == EXPECT_PHASE) { 1195 // Fast forward: 1196 setPhase(READ_PHASE); 1197 setPhase(DISBURSE_PHASE); 1198 } 1199 return this; 1200 } 1201 1202 Band[] bands = new Band[10]; 1203 int bandCount = 0; 1204 1205 int size() { 1206 return bandCount; 1207 } 1208 Band get(int i) { 1209 assert(i < bandCount); 1210 return bands[i]; 1211 } 1212 Band[] toArray() { 1213 return (Band[]) realloc(bands, bandCount); 1214 } 1215 1216 void add(Band b) { 1217 assert(bandCount == 0 || notePrevForAssert(b, bands[bandCount-1])); 1218 if (bandCount == bands.length) { 1219 bands = (Band[]) realloc(bands); 1220 } 1221 bands[bandCount++] = b; 1222 } 1223 1224 ByteBand newByteBand(String name) { 1225 ByteBand b = new ByteBand(name); 1226 b.init(); add(b); 1227 return b; 1228 } 1229 IntBand newIntBand(String name) { 1230 IntBand b = new IntBand(name, regularCoding); 1231 b.init(); add(b); 1232 return b; 1233 } 1234 IntBand newIntBand(String name, Coding regularCoding) { 1235 IntBand b = new IntBand(name, regularCoding); 1236 b.init(); add(b); 1237 return b; 1238 } 1239 MultiBand newMultiBand(String name, Coding regularCoding) { 1240 MultiBand b = new MultiBand(name, regularCoding); 1241 b.init(); add(b); 1242 return b; 1243 } 1244 CPRefBand newCPRefBand(String name, byte cpTag) { 1245 CPRefBand b = new CPRefBand(name, regularCoding, cpTag); 1246 b.init(); add(b); 1247 return b; 1248 } 1249 CPRefBand newCPRefBand(String name, Coding regularCoding, 1250 byte cpTag) { 1251 CPRefBand b = new CPRefBand(name, regularCoding, cpTag); 1252 b.init(); add(b); 1253 return b; 1254 } 1255 CPRefBand newCPRefBand(String name, Coding regularCoding, 1256 byte cpTag, boolean nullOK) { 1257 CPRefBand b = new CPRefBand(name, regularCoding, cpTag, nullOK); 1258 b.init(); add(b); 1259 return b; 1260 } 1261 1262 int bandCount() { return bandCount; } 1263 1264 private int cap = -1; 1265 public int capacity() { return cap; } 1266 public void setCapacity(int cap) { this.cap = cap; } 1267 1268 public int length() { return 0; } 1269 public int valuesRemainingForDebug() { return 0; } 1270 1271 protected void chooseBandCodings() throws IOException { 1272 // coding decision pass 1273 for (int i = 0; i < bandCount; i++) { 1274 Band b = bands[i]; 1275 b.chooseBandCodings(); 1276 } 1277 } 1278 1279 protected long computeOutputSize() { 1280 // coding decision pass 1281 long sum = 0; 1282 for (int i = 0; i < bandCount; i++) { 1283 Band b = bands[i]; 1284 long bsize = b.outputSize(); 1285 assert(bsize >= 0) : b; 1286 sum += bsize; 1287 } 1288 // do not cache 1289 return sum; 1290 } 1291 1292 protected void writeDataTo(OutputStream out) throws IOException { 1293 long preCount = 0; 1294 if (outputCounter != null) preCount = outputCounter.getCount(); 1295 for (int i = 0; i < bandCount; i++) { 1296 Band b = bands[i]; 1297 b.writeTo(out); 1298 if (outputCounter != null) { 1299 long postCount = outputCounter.getCount(); 1300 long len = postCount - preCount; 1301 preCount = postCount; 1302 if ((verbose > 0 && len > 0) || verbose > 1) { 1303 Utils.log.info(" ...wrote "+len+" bytes from "+b); 1304 } 1305 } 1306 } 1307 } 1308 1309 protected void readDataFrom(InputStream in) throws IOException { 1310 assert(false); // not called? 1311 for (int i = 0; i < bandCount; i++) { 1312 Band b = bands[i]; 1313 b.readFrom(in); 1314 if ((verbose > 0 && b.length() > 0) || verbose > 1) { 1315 Utils.log.info(" ...read "+b); 1316 } 1317 } 1318 } 1319 1320 public String toString() { 1321 return "{"+bandCount()+" bands: "+super.toString()+"}"; 1322 } 1323 } 1324 1325 /** 1326 * An output stream which counts the number of bytes written. 1327 */ 1328 private static 1329 class ByteCounter extends FilterOutputStream { 1330 // (should go public under the name CountingOutputStream?) 1331 1332 private long count; 1333 1334 public ByteCounter(OutputStream out) { 1335 super(out); 1336 } 1337 1338 public long getCount() { return count; } 1339 public void setCount(long c) { count = c; } 1340 1341 public void write(int b) throws IOException { 1342 count++; 1343 if (out != null) out.write(b); 1344 } 1345 public void write(byte b[], int off, int len) throws IOException { 1346 count += len; 1347 if (out != null) out.write(b, off, len); 1348 } 1349 public String toString() { 1350 return String.valueOf(getCount()); 1351 } 1352 } 1353 ByteCounter outputCounter; 1354 1355 void writeAllBandsTo(OutputStream out) throws IOException { 1356 // Wrap a byte-counter around the output stream. 1357 outputCounter = new ByteCounter(out); 1358 out = outputCounter; 1359 all_bands.writeTo(out); 1360 if (verbose > 0) { 1361 long nbytes = outputCounter.getCount(); 1362 Utils.log.info("Wrote total of "+nbytes+" bytes."); 1363 assert(nbytes == archiveSize0+archiveSize1); 1364 } 1365 outputCounter = null; 1366 } 1367 1368 // random AO_XXX bits, decoded from the archive header 1369 protected int archiveOptions; 1370 1371 // archiveSize1 sizes most of the archive [archive_options..file_bits). 1372 protected long archiveSize0; // size through archive_size_lo 1373 protected long archiveSize1; // size reported in archive_header 1374 protected int archiveNextCount; // reported in archive_header 1375 1376 static final int AH_LENGTH_0 = 3; //minver, majver, options 1377 static final int AH_ARCHIVE_SIZE_HI = 0; 1378 static final int AH_ARCHIVE_SIZE_LO = 1; 1379 static final int AH_LENGTH_S = 2; //optional size hi/lo 1380 static final int AH_LENGTH = 26; // mentioned in spec 1381 // Length contributions from optional header fields: 1382 static final int AH_FILE_HEADER_LEN = 5; // sizehi/lo/next/modtime/files 1383 static final int AH_SPECIAL_FORMAT_LEN = 2; // layouts/band-headers 1384 static final int AH_CP_NUMBER_LEN = 4; // int/float/long/double 1385 static final int AH_LENGTH_MIN = AH_LENGTH 1386 -(AH_SPECIAL_FORMAT_LEN+AH_FILE_HEADER_LEN+AH_CP_NUMBER_LEN); 1387 1388 // Common structure of attribute band groups: 1389 static final int AB_FLAGS_HI = 0; 1390 static final int AB_FLAGS_LO = 1; 1391 static final int AB_ATTR_COUNT = 2; 1392 static final int AB_ATTR_INDEXES = 3; 1393 static final int AB_ATTR_CALLS = 4; 1394 1395 static IntBand getAttrBand(MultiBand xxx_attr_bands, int which) { 1396 IntBand b = (IntBand) xxx_attr_bands.get(which); 1397 switch (which) { 1398 case AB_FLAGS_HI: 1399 assert(b.name().endsWith("_flags_hi")); break; 1400 case AB_FLAGS_LO: 1401 assert(b.name().endsWith("_flags_lo")); break; 1402 case AB_ATTR_COUNT: 1403 assert(b.name().endsWith("_attr_count")); break; 1404 case AB_ATTR_INDEXES: 1405 assert(b.name().endsWith("_attr_indexes")); break; 1406 case AB_ATTR_CALLS: 1407 assert(b.name().endsWith("_attr_calls")); break; 1408 default: 1409 assert(false); break; 1410 } 1411 return b; 1412 } 1413 1414 static private final boolean NULL_IS_OK = true; 1415 1416 MultiBand all_bands = (MultiBand) new MultiBand("(package)", UNSIGNED5).init(); 1417 1418 // file header (various random bytes) 1419 ByteBand archive_magic = all_bands.newByteBand("archive_magic"); 1420 IntBand archive_header_0 = all_bands.newIntBand("archive_header_0", UNSIGNED5); 1421 IntBand archive_header_S = all_bands.newIntBand("archive_header_S", UNSIGNED5); 1422 IntBand archive_header_1 = all_bands.newIntBand("archive_header_1", UNSIGNED5); 1423 ByteBand band_headers = all_bands.newByteBand("band_headers"); 1424 1425 // constant pool contents 1426 MultiBand cp_bands = all_bands.newMultiBand("(constant_pool)", DELTA5); 1427 IntBand cp_Utf8_prefix = cp_bands.newIntBand("cp_Utf8_prefix"); 1428 IntBand cp_Utf8_suffix = cp_bands.newIntBand("cp_Utf8_suffix", UNSIGNED5); 1429 IntBand cp_Utf8_chars = cp_bands.newIntBand("cp_Utf8_chars", CHAR3); 1430 IntBand cp_Utf8_big_suffix = cp_bands.newIntBand("cp_Utf8_big_suffix"); 1431 MultiBand cp_Utf8_big_chars = cp_bands.newMultiBand("(cp_Utf8_big_chars)", DELTA5); 1432 IntBand cp_Int = cp_bands.newIntBand("cp_Int", UDELTA5); 1433 IntBand cp_Float = cp_bands.newIntBand("cp_Float", UDELTA5); 1434 IntBand cp_Long_hi = cp_bands.newIntBand("cp_Long_hi", UDELTA5); 1435 IntBand cp_Long_lo = cp_bands.newIntBand("cp_Long_lo"); 1436 IntBand cp_Double_hi = cp_bands.newIntBand("cp_Double_hi", UDELTA5); 1437 IntBand cp_Double_lo = cp_bands.newIntBand("cp_Double_lo"); 1438 CPRefBand cp_String = cp_bands.newCPRefBand("cp_String", UDELTA5, CONSTANT_Utf8); 1439 CPRefBand cp_Class = cp_bands.newCPRefBand("cp_Class", UDELTA5, CONSTANT_Utf8); 1440 CPRefBand cp_Signature_form = cp_bands.newCPRefBand("cp_Signature_form", CONSTANT_Utf8); 1441 CPRefBand cp_Signature_classes = cp_bands.newCPRefBand("cp_Signature_classes", UDELTA5, CONSTANT_Class); 1442 CPRefBand cp_Descr_name = cp_bands.newCPRefBand("cp_Descr_name", CONSTANT_Utf8); 1443 CPRefBand cp_Descr_type = cp_bands.newCPRefBand("cp_Descr_type", UDELTA5, CONSTANT_Signature); 1444 CPRefBand cp_Field_class = cp_bands.newCPRefBand("cp_Field_class", CONSTANT_Class); 1445 CPRefBand cp_Field_desc = cp_bands.newCPRefBand("cp_Field_desc", UDELTA5, CONSTANT_NameandType); 1446 CPRefBand cp_Method_class = cp_bands.newCPRefBand("cp_Method_class", CONSTANT_Class); 1447 CPRefBand cp_Method_desc = cp_bands.newCPRefBand("cp_Method_desc", UDELTA5, CONSTANT_NameandType); 1448 CPRefBand cp_Imethod_class = cp_bands.newCPRefBand("cp_Imethod_class", CONSTANT_Class); 1449 CPRefBand cp_Imethod_desc = cp_bands.newCPRefBand("cp_Imethod_desc", UDELTA5, CONSTANT_NameandType); 1450 1451 // bands for carrying attribute definitions: 1452 MultiBand attr_definition_bands = all_bands.newMultiBand("(attr_definition_bands)", UNSIGNED5); 1453 ByteBand attr_definition_headers = attr_definition_bands.newByteBand("attr_definition_headers"); 1454 CPRefBand attr_definition_name = attr_definition_bands.newCPRefBand("attr_definition_name", CONSTANT_Utf8); 1455 CPRefBand attr_definition_layout = attr_definition_bands.newCPRefBand("attr_definition_layout", CONSTANT_Utf8); 1456 1457 // bands for hardwired InnerClasses attribute (shared across the package) 1458 MultiBand ic_bands = all_bands.newMultiBand("(ic_bands)", DELTA5); 1459 CPRefBand ic_this_class = ic_bands.newCPRefBand("ic_this_class", UDELTA5, CONSTANT_Class); 1460 IntBand ic_flags = ic_bands.newIntBand("ic_flags", UNSIGNED5); 1461 // These bands contain data only where flags sets ACC_IC_LONG_FORM: 1462 CPRefBand ic_outer_class = ic_bands.newCPRefBand("ic_outer_class", DELTA5, CONSTANT_Class, NULL_IS_OK); 1463 CPRefBand ic_name = ic_bands.newCPRefBand("ic_name", DELTA5, CONSTANT_Utf8, NULL_IS_OK); 1464 1465 // bands for carrying class schema information: 1466 MultiBand class_bands = all_bands.newMultiBand("(class_bands)", DELTA5); 1467 CPRefBand class_this = class_bands.newCPRefBand("class_this", CONSTANT_Class); 1468 CPRefBand class_super = class_bands.newCPRefBand("class_super", CONSTANT_Class); 1469 IntBand class_interface_count = class_bands.newIntBand("class_interface_count"); 1470 CPRefBand class_interface = class_bands.newCPRefBand("class_interface", CONSTANT_Class); 1471 1472 // bands for class members 1473 IntBand class_field_count = class_bands.newIntBand("class_field_count"); 1474 IntBand class_method_count = class_bands.newIntBand("class_method_count"); 1475 1476 CPRefBand field_descr = class_bands.newCPRefBand("field_descr", CONSTANT_NameandType); 1477 MultiBand field_attr_bands = class_bands.newMultiBand("(field_attr_bands)", UNSIGNED5); 1478 IntBand field_flags_hi = field_attr_bands.newIntBand("field_flags_hi"); 1479 IntBand field_flags_lo = field_attr_bands.newIntBand("field_flags_lo"); 1480 IntBand field_attr_count = field_attr_bands.newIntBand("field_attr_count"); 1481 IntBand field_attr_indexes = field_attr_bands.newIntBand("field_attr_indexes"); 1482 IntBand field_attr_calls = field_attr_bands.newIntBand("field_attr_calls"); 1483 1484 // bands for predefined field attributes 1485 CPRefBand field_ConstantValue_KQ = field_attr_bands.newCPRefBand("field_ConstantValue_KQ", CONSTANT_Literal); 1486 CPRefBand field_Signature_RS = field_attr_bands.newCPRefBand("field_Signature_RS", CONSTANT_Signature); 1487 MultiBand field_metadata_bands = field_attr_bands.newMultiBand("(field_metadata_bands)", UNSIGNED5); 1488 1489 CPRefBand method_descr = class_bands.newCPRefBand("method_descr", MDELTA5, CONSTANT_NameandType); 1490 MultiBand method_attr_bands = class_bands.newMultiBand("(method_attr_bands)", UNSIGNED5); 1491 IntBand method_flags_hi = method_attr_bands.newIntBand("method_flags_hi"); 1492 IntBand method_flags_lo = method_attr_bands.newIntBand("method_flags_lo"); 1493 IntBand method_attr_count = method_attr_bands.newIntBand("method_attr_count"); 1494 IntBand method_attr_indexes = method_attr_bands.newIntBand("method_attr_indexes"); 1495 IntBand method_attr_calls = method_attr_bands.newIntBand("method_attr_calls"); 1496 // band for predefined method attributes 1497 IntBand method_Exceptions_N = method_attr_bands.newIntBand("method_Exceptions_N"); 1498 CPRefBand method_Exceptions_RC = method_attr_bands.newCPRefBand("method_Exceptions_RC", CONSTANT_Class); 1499 CPRefBand method_Signature_RS = method_attr_bands.newCPRefBand("method_Signature_RS", CONSTANT_Signature); 1500 MultiBand method_metadata_bands = method_attr_bands.newMultiBand("(method_metadata_bands)", UNSIGNED5); 1501 1502 MultiBand class_attr_bands = class_bands.newMultiBand("(class_attr_bands)", UNSIGNED5); 1503 IntBand class_flags_hi = class_attr_bands.newIntBand("class_flags_hi"); 1504 IntBand class_flags_lo = class_attr_bands.newIntBand("class_flags_lo"); 1505 IntBand class_attr_count = class_attr_bands.newIntBand("class_attr_count"); 1506 IntBand class_attr_indexes = class_attr_bands.newIntBand("class_attr_indexes"); 1507 IntBand class_attr_calls = class_attr_bands.newIntBand("class_attr_calls"); 1508 // band for predefined SourceFile and other class attributes 1509 CPRefBand class_SourceFile_RUN = class_attr_bands.newCPRefBand("class_SourceFile_RUN", UNSIGNED5, CONSTANT_Utf8, NULL_IS_OK); 1510 CPRefBand class_EnclosingMethod_RC = class_attr_bands.newCPRefBand("class_EnclosingMethod_RC", CONSTANT_Class); 1511 CPRefBand class_EnclosingMethod_RDN = class_attr_bands.newCPRefBand("class_EnclosingMethod_RDN", UNSIGNED5, CONSTANT_NameandType, NULL_IS_OK); 1512 CPRefBand class_Signature_RS = class_attr_bands.newCPRefBand("class_Signature_RS", CONSTANT_Signature); 1513 MultiBand class_metadata_bands = class_attr_bands.newMultiBand("(class_metadata_bands)", UNSIGNED5); 1514 IntBand class_InnerClasses_N = class_attr_bands.newIntBand("class_InnerClasses_N"); 1515 CPRefBand class_InnerClasses_RC = class_attr_bands.newCPRefBand("class_InnerClasses_RC", CONSTANT_Class); 1516 IntBand class_InnerClasses_F = class_attr_bands.newIntBand("class_InnerClasses_F"); 1517 CPRefBand class_InnerClasses_outer_RCN = class_attr_bands.newCPRefBand("class_InnerClasses_outer_RCN", UNSIGNED5, CONSTANT_Class, NULL_IS_OK); 1518 CPRefBand class_InnerClasses_name_RUN = class_attr_bands.newCPRefBand("class_InnerClasses_name_RUN", UNSIGNED5, CONSTANT_Utf8, NULL_IS_OK); 1519 IntBand class_ClassFile_version_minor_H = class_attr_bands.newIntBand("class_ClassFile_version_minor_H"); 1520 IntBand class_ClassFile_version_major_H = class_attr_bands.newIntBand("class_ClassFile_version_major_H"); 1521 1522 MultiBand code_bands = class_bands.newMultiBand("(code_bands)", UNSIGNED5); 1523 ByteBand code_headers = code_bands.newByteBand("code_headers"); //BYTE1 1524 IntBand code_max_stack = code_bands.newIntBand("code_max_stack", UNSIGNED5); 1525 IntBand code_max_na_locals = code_bands.newIntBand("code_max_na_locals", UNSIGNED5); 1526 IntBand code_handler_count = code_bands.newIntBand("code_handler_count", UNSIGNED5); 1527 IntBand code_handler_start_P = code_bands.newIntBand("code_handler_start_P", BCI5); 1528 IntBand code_handler_end_PO = code_bands.newIntBand("code_handler_end_PO", BRANCH5); 1529 IntBand code_handler_catch_PO = code_bands.newIntBand("code_handler_catch_PO", BRANCH5); 1530 CPRefBand code_handler_class_RCN = code_bands.newCPRefBand("code_handler_class_RCN", UNSIGNED5, CONSTANT_Class, NULL_IS_OK); 1531 1532 MultiBand code_attr_bands = class_bands.newMultiBand("(code_attr_bands)", UNSIGNED5); 1533 IntBand code_flags_hi = code_attr_bands.newIntBand("code_flags_hi"); 1534 IntBand code_flags_lo = code_attr_bands.newIntBand("code_flags_lo"); 1535 IntBand code_attr_count = code_attr_bands.newIntBand("code_attr_count"); 1536 IntBand code_attr_indexes = code_attr_bands.newIntBand("code_attr_indexes"); 1537 IntBand code_attr_calls = code_attr_bands.newIntBand("code_attr_calls"); 1538 1539 MultiBand stackmap_bands = code_attr_bands.newMultiBand("StackMapTable_bands", UNSIGNED5); 1540 IntBand code_StackMapTable_N = stackmap_bands.newIntBand("code_StackMapTable_N"); 1541 IntBand code_StackMapTable_frame_T = stackmap_bands.newIntBand("code_StackMapTable_frame_T",BYTE1); 1542 IntBand code_StackMapTable_local_N = stackmap_bands.newIntBand("code_StackMapTable_local_N"); 1543 IntBand code_StackMapTable_stack_N = stackmap_bands.newIntBand("code_StackMapTable_stack_N"); 1544 IntBand code_StackMapTable_offset = stackmap_bands.newIntBand("code_StackMapTable_offset", UNSIGNED5); 1545 IntBand code_StackMapTable_T = stackmap_bands.newIntBand("code_StackMapTable_T", BYTE1); 1546 CPRefBand code_StackMapTable_RC = stackmap_bands.newCPRefBand("code_StackMapTable_RC", CONSTANT_Class); 1547 IntBand code_StackMapTable_P = stackmap_bands.newIntBand("code_StackMapTable_P", BCI5); 1548 1549 // bands for predefined LineNumberTable attribute 1550 IntBand code_LineNumberTable_N = code_attr_bands.newIntBand("code_LineNumberTable_N"); 1551 IntBand code_LineNumberTable_bci_P = code_attr_bands.newIntBand("code_LineNumberTable_bci_P", BCI5); 1552 IntBand code_LineNumberTable_line = code_attr_bands.newIntBand("code_LineNumberTable_line"); 1553 1554 // bands for predefined LocalVariable{Type}Table attributes 1555 IntBand code_LocalVariableTable_N = code_attr_bands.newIntBand("code_LocalVariableTable_N"); 1556 IntBand code_LocalVariableTable_bci_P = code_attr_bands.newIntBand("code_LocalVariableTable_bci_P", BCI5); 1557 IntBand code_LocalVariableTable_span_O = code_attr_bands.newIntBand("code_LocalVariableTable_span_O", BRANCH5); 1558 CPRefBand code_LocalVariableTable_name_RU = code_attr_bands.newCPRefBand("code_LocalVariableTable_name_RU", CONSTANT_Utf8); 1559 CPRefBand code_LocalVariableTable_type_RS = code_attr_bands.newCPRefBand("code_LocalVariableTable_type_RS", CONSTANT_Signature); 1560 IntBand code_LocalVariableTable_slot = code_attr_bands.newIntBand("code_LocalVariableTable_slot"); 1561 IntBand code_LocalVariableTypeTable_N = code_attr_bands.newIntBand("code_LocalVariableTypeTable_N"); 1562 IntBand code_LocalVariableTypeTable_bci_P = code_attr_bands.newIntBand("code_LocalVariableTypeTable_bci_P", BCI5); 1563 IntBand code_LocalVariableTypeTable_span_O = code_attr_bands.newIntBand("code_LocalVariableTypeTable_span_O", BRANCH5); 1564 CPRefBand code_LocalVariableTypeTable_name_RU = code_attr_bands.newCPRefBand("code_LocalVariableTypeTable_name_RU", CONSTANT_Utf8); 1565 CPRefBand code_LocalVariableTypeTable_type_RS = code_attr_bands.newCPRefBand("code_LocalVariableTypeTable_type_RS", CONSTANT_Signature); 1566 IntBand code_LocalVariableTypeTable_slot = code_attr_bands.newIntBand("code_LocalVariableTypeTable_slot"); 1567 1568 // bands for bytecodes 1569 MultiBand bc_bands = all_bands.newMultiBand("(byte_codes)", UNSIGNED5); 1570 ByteBand bc_codes = bc_bands.newByteBand("bc_codes"); //BYTE1 1571 // remaining bands provide typed opcode fields required by the bc_codes 1572 1573 IntBand bc_case_count = bc_bands.newIntBand("bc_case_count"); // *switch 1574 IntBand bc_case_value = bc_bands.newIntBand("bc_case_value", DELTA5); // *switch 1575 ByteBand bc_byte = bc_bands.newByteBand("bc_byte"); //BYTE1 // bipush, iinc, *newarray 1576 IntBand bc_short = bc_bands.newIntBand("bc_short", DELTA5); // sipush, wide iinc 1577 IntBand bc_local = bc_bands.newIntBand("bc_local"); // *load, *store, iinc, ret 1578 IntBand bc_label = bc_bands.newIntBand("bc_label", BRANCH5); // if*, goto*, jsr*, *switch 1579 1580 // Most CP refs exhibit some correlation, and benefit from delta coding. 1581 // The notable exceptions are class and method references. 1582 1583 // ldc* operands: 1584 CPRefBand bc_intref = bc_bands.newCPRefBand("bc_intref", DELTA5, CONSTANT_Integer); 1585 CPRefBand bc_floatref = bc_bands.newCPRefBand("bc_floatref", DELTA5, CONSTANT_Float); 1586 CPRefBand bc_longref = bc_bands.newCPRefBand("bc_longref", DELTA5, CONSTANT_Long); 1587 CPRefBand bc_doubleref = bc_bands.newCPRefBand("bc_doubleref", DELTA5, CONSTANT_Double); 1588 CPRefBand bc_stringref = bc_bands.newCPRefBand("bc_stringref", DELTA5, CONSTANT_String); 1589 1590 // nulls produced by bc_classref are taken to mean the current class 1591 CPRefBand bc_classref = bc_bands.newCPRefBand("bc_classref", UNSIGNED5, CONSTANT_Class, NULL_IS_OK); // new, *anew*, c*cast, i*of, ldc 1592 CPRefBand bc_fieldref = bc_bands.newCPRefBand("bc_fieldref", DELTA5, CONSTANT_Fieldref); // get*, put* 1593 CPRefBand bc_methodref = bc_bands.newCPRefBand("bc_methodref", CONSTANT_Methodref); // invoke[vs]* 1594 CPRefBand bc_imethodref = bc_bands.newCPRefBand("bc_imethodref", DELTA5, CONSTANT_InterfaceMethodref); // invokeinterface 1595 1596 // _self_linker_op family 1597 CPRefBand bc_thisfield = bc_bands.newCPRefBand("bc_thisfield", CONSTANT_None); // any field within cur. class 1598 CPRefBand bc_superfield = bc_bands.newCPRefBand("bc_superfield", CONSTANT_None); // any field within superclass 1599 CPRefBand bc_thismethod = bc_bands.newCPRefBand("bc_thismethod", CONSTANT_None); // any method within cur. class 1600 CPRefBand bc_supermethod = bc_bands.newCPRefBand("bc_supermethod", CONSTANT_None); // any method within superclass 1601 // bc_invokeinit family: 1602 IntBand bc_initref = bc_bands.newIntBand("bc_initref"); 1603 // escapes 1604 CPRefBand bc_escref = bc_bands.newCPRefBand("bc_escref", CONSTANT_All); 1605 IntBand bc_escrefsize = bc_bands.newIntBand("bc_escrefsize"); 1606 IntBand bc_escsize = bc_bands.newIntBand("bc_escsize"); 1607 ByteBand bc_escbyte = bc_bands.newByteBand("bc_escbyte"); 1608 1609 // bands for carrying resource files and file attributes: 1610 MultiBand file_bands = all_bands.newMultiBand("(file_bands)", UNSIGNED5); 1611 CPRefBand file_name = file_bands.newCPRefBand("file_name", CONSTANT_Utf8); 1612 IntBand file_size_hi = file_bands.newIntBand("file_size_hi"); 1613 IntBand file_size_lo = file_bands.newIntBand("file_size_lo"); 1614 IntBand file_modtime = file_bands.newIntBand("file_modtime", DELTA5); 1615 IntBand file_options = file_bands.newIntBand("file_options"); 1616 ByteBand file_bits = file_bands.newByteBand("file_bits"); 1617 1618 // End of band definitions! 1619 1620 /** Given CP indexes, distribute tag-specific indexes to bands. */ 1621 protected void setBandIndexes() { 1622 // Handle prior calls to setBandIndex: 1623 for (Object[] need : needPredefIndex) { 1624 CPRefBand b = (CPRefBand) need[0]; 1625 Byte which = (Byte) need[1]; 1626 b.setIndex(getCPIndex(which.byteValue())); 1627 } 1628 needPredefIndex = null; // no more predefs 1629 1630 if (verbose > 3) { 1631 printCDecl(all_bands); 1632 } 1633 } 1634 1635 protected void setBandIndex(CPRefBand b, byte which) { 1636 Object[] need = { b, Byte.valueOf(which) }; 1637 if (which == CONSTANT_Literal) { 1638 // I.e., attribute layouts KQ (no null) or KQN (null ok). 1639 allKQBands.add(b); 1640 } else if (needPredefIndex != null) { 1641 needPredefIndex.add(need); 1642 } else { 1643 // Not in predefinition mode; getCPIndex now works. 1644 b.setIndex(getCPIndex(which)); 1645 } 1646 } 1647 1648 protected void setConstantValueIndex(Field f) { 1649 Index ix = null; 1650 if (f != null) { 1651 byte tag = f.getLiteralTag(); 1652 ix = getCPIndex(tag); 1653 if (verbose > 2) 1654 Utils.log.fine("setConstantValueIndex "+f+" "+ConstantPool.tagName(tag)+" => "+ix); 1655 assert(ix != null); 1656 } 1657 // Typically, allKQBands is the singleton of field_ConstantValue_KQ. 1658 for (CPRefBand xxx_KQ : allKQBands) { 1659 xxx_KQ.setIndex(ix); 1660 } 1661 } 1662 1663 // Table of bands which contain metadata. 1664 protected MultiBand[] metadataBands = new MultiBand[ATTR_CONTEXT_LIMIT]; 1665 { 1666 metadataBands[ATTR_CONTEXT_CLASS] = class_metadata_bands; 1667 metadataBands[ATTR_CONTEXT_FIELD] = field_metadata_bands; 1668 metadataBands[ATTR_CONTEXT_METHOD] = method_metadata_bands; 1669 } 1670 1671 // Attribute layouts. 1672 public static final int ADH_CONTEXT_MASK = 0x3; // (ad_hdr & ADH_CONTEXT_MASK) 1673 public static final int ADH_BIT_SHIFT = 0x2; // (ad_hdr >> ADH_BIT_SHIFT) 1674 public static final int ADH_BIT_IS_LSB = 1; 1675 public static final int ATTR_INDEX_OVERFLOW = -1; 1676 1677 public int[] attrIndexLimit = new int[ATTR_CONTEXT_LIMIT]; 1678 // Each index limit is either 32 or 63, depending on AO_HAVE_XXX_FLAGS_HI. 1679 1680 // Which flag bits are taken over by attributes? 1681 protected long[] attrFlagMask = new long[ATTR_CONTEXT_LIMIT]; 1682 // Which flag bits have been taken over explicitly? 1683 protected long[] attrDefSeen = new long[ATTR_CONTEXT_LIMIT]; 1684 1685 // What pseudo-attribute bits are there to watch for? 1686 protected int[] attrOverflowMask = new int[ATTR_CONTEXT_LIMIT]; 1687 protected int attrClassFileVersionMask; 1688 1689 // Mapping from Attribute.Layout to Band[] (layout element bands). 1690 protected Map<Attribute.Layout, Band[]> attrBandTable = new HashMap<>(); 1691 1692 // Well-known attributes: 1693 protected final Attribute.Layout attrCodeEmpty; 1694 protected final Attribute.Layout attrInnerClassesEmpty; 1695 protected final Attribute.Layout attrClassFileVersion; 1696 protected final Attribute.Layout attrConstantValue; 1697 1698 // Mapping from Attribute.Layout to Integer (inverse of attrDefs) 1699 Map<Attribute.Layout, Integer> attrIndexTable = new HashMap<>(); 1700 1701 // Mapping from attribute index (<32 are flag bits) to attributes. 1702 protected List<List<Attribute.Layout>> attrDefs = 1703 new FixedList<>(ATTR_CONTEXT_LIMIT); 1704 { 1705 for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { 1706 assert(attrIndexLimit[i] == 0); 1707 attrIndexLimit[i] = 32; // just for the sake of predefs. 1708 attrDefs.set(i, new ArrayList<Attribute.Layout>(Collections.nCopies( 1709 attrIndexLimit[i], (Attribute.Layout)null))); 1710 1711 } 1712 1713 // Add predefined attribute definitions: 1714 attrInnerClassesEmpty = 1715 predefineAttribute(CLASS_ATTR_InnerClasses, ATTR_CONTEXT_CLASS, null, 1716 "InnerClasses", ""); 1717 assert(attrInnerClassesEmpty == Package.attrInnerClassesEmpty); 1718 predefineAttribute(CLASS_ATTR_SourceFile, ATTR_CONTEXT_CLASS, 1719 new Band[] { class_SourceFile_RUN }, 1720 "SourceFile", "RUNH"); 1721 predefineAttribute(CLASS_ATTR_EnclosingMethod, ATTR_CONTEXT_CLASS, 1722 new Band[] { 1723 class_EnclosingMethod_RC, 1724 class_EnclosingMethod_RDN 1725 }, 1726 "EnclosingMethod", "RCHRDNH"); 1727 attrClassFileVersion = 1728 predefineAttribute(CLASS_ATTR_ClassFile_version, ATTR_CONTEXT_CLASS, 1729 new Band[] { 1730 class_ClassFile_version_minor_H, 1731 class_ClassFile_version_major_H 1732 }, 1733 ".ClassFile.version", "HH"); 1734 predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_CLASS, 1735 new Band[] { class_Signature_RS }, 1736 "Signature", "RSH"); 1737 predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_CLASS, null, 1738 "Deprecated", ""); 1739 //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_CLASS, null, 1740 // "Synthetic", ""); 1741 predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_CLASS, null, 1742 ".Overflow", ""); 1743 attrConstantValue = 1744 predefineAttribute(FIELD_ATTR_ConstantValue, ATTR_CONTEXT_FIELD, 1745 new Band[] { field_ConstantValue_KQ }, 1746 "ConstantValue", "KQH"); 1747 predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_FIELD, 1748 new Band[] { field_Signature_RS }, 1749 "Signature", "RSH"); 1750 predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_FIELD, null, 1751 "Deprecated", ""); 1752 //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_FIELD, null, 1753 // "Synthetic", ""); 1754 predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_FIELD, null, 1755 ".Overflow", ""); 1756 attrCodeEmpty = 1757 predefineAttribute(METHOD_ATTR_Code, ATTR_CONTEXT_METHOD, null, 1758 "Code", ""); 1759 predefineAttribute(METHOD_ATTR_Exceptions, ATTR_CONTEXT_METHOD, 1760 new Band[] { 1761 method_Exceptions_N, 1762 method_Exceptions_RC 1763 }, 1764 "Exceptions", "NH[RCH]"); 1765 assert(attrCodeEmpty == Package.attrCodeEmpty); 1766 predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_METHOD, 1767 new Band[] { method_Signature_RS }, 1768 "Signature", "RSH"); 1769 predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_METHOD, null, 1770 "Deprecated", ""); 1771 //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_METHOD, null, 1772 // "Synthetic", ""); 1773 predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_METHOD, null, 1774 ".Overflow", ""); 1775 1776 for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) { 1777 MultiBand xxx_metadata_bands = metadataBands[ctype]; 1778 if (xxx_metadata_bands == null) 1779 continue; // no code attrs 1780 1781 // These arguments cause the bands to be built 1782 // automatically for this complicated layout: 1783 predefineAttribute(X_ATTR_RuntimeVisibleAnnotations, 1784 ATTR_CONTEXT_NAME[ctype]+"_RVA_", 1785 xxx_metadata_bands, 1786 Attribute.lookup(null, ctype, 1787 "RuntimeVisibleAnnotations")); 1788 predefineAttribute(X_ATTR_RuntimeInvisibleAnnotations, 1789 ATTR_CONTEXT_NAME[ctype]+"_RIA_", 1790 xxx_metadata_bands, 1791 Attribute.lookup(null, ctype, 1792 "RuntimeInvisibleAnnotations")); 1793 if (ctype != ATTR_CONTEXT_METHOD) 1794 continue; 1795 1796 predefineAttribute(METHOD_ATTR_RuntimeVisibleParameterAnnotations, 1797 "method_RVPA_", xxx_metadata_bands, 1798 Attribute.lookup(null, ctype, 1799 "RuntimeVisibleParameterAnnotations")); 1800 predefineAttribute(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, 1801 "method_RIPA_", xxx_metadata_bands, 1802 Attribute.lookup(null, ctype, 1803 "RuntimeInvisibleParameterAnnotations")); 1804 predefineAttribute(METHOD_ATTR_AnnotationDefault, 1805 "method_AD_", xxx_metadata_bands, 1806 Attribute.lookup(null, ctype, 1807 "AnnotationDefault")); 1808 } 1809 1810 1811 Attribute.Layout stackMapDef = Attribute.lookup(null, ATTR_CONTEXT_CODE, "StackMapTable").layout(); 1812 predefineAttribute(CODE_ATTR_StackMapTable, ATTR_CONTEXT_CODE, 1813 stackmap_bands.toArray(), 1814 stackMapDef.name(), stackMapDef.layout()); 1815 1816 predefineAttribute(CODE_ATTR_LineNumberTable, ATTR_CONTEXT_CODE, 1817 new Band[] { 1818 code_LineNumberTable_N, 1819 code_LineNumberTable_bci_P, 1820 code_LineNumberTable_line 1821 }, 1822 "LineNumberTable", "NH[PHH]"); 1823 predefineAttribute(CODE_ATTR_LocalVariableTable, ATTR_CONTEXT_CODE, 1824 new Band[] { 1825 code_LocalVariableTable_N, 1826 code_LocalVariableTable_bci_P, 1827 code_LocalVariableTable_span_O, 1828 code_LocalVariableTable_name_RU, 1829 code_LocalVariableTable_type_RS, 1830 code_LocalVariableTable_slot 1831 }, 1832 "LocalVariableTable", "NH[PHOHRUHRSHH]"); 1833 predefineAttribute(CODE_ATTR_LocalVariableTypeTable, ATTR_CONTEXT_CODE, 1834 new Band[] { 1835 code_LocalVariableTypeTable_N, 1836 code_LocalVariableTypeTable_bci_P, 1837 code_LocalVariableTypeTable_span_O, 1838 code_LocalVariableTypeTable_name_RU, 1839 code_LocalVariableTypeTable_type_RS, 1840 code_LocalVariableTypeTable_slot 1841 }, 1842 "LocalVariableTypeTable", "NH[PHOHRUHRSHH]"); 1843 predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_CODE, null, 1844 ".Overflow", ""); 1845 1846 // Clear the record of having seen these definitions, 1847 // so they may be redefined without error. 1848 for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { 1849 attrDefSeen[i] = 0; 1850 } 1851 1852 // Set up the special masks: 1853 for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { 1854 attrOverflowMask[i] = (1<<X_ATTR_OVERFLOW); 1855 attrIndexLimit[i] = 0; // will make a final decision later 1856 } 1857 attrClassFileVersionMask = (1<<CLASS_ATTR_ClassFile_version); 1858 } 1859 1860 private void adjustToMajver() { 1861 if (getPackageMajver() < JAVA6_PACKAGE_MAJOR_VERSION) { 1862 if (verbose > 0) Utils.log.fine("Legacy package version"); 1863 // Revoke definition of pre-1.6 attribute type. 1864 undefineAttribute(CODE_ATTR_StackMapTable, ATTR_CONTEXT_CODE); 1865 } 1866 } 1867 1868 protected void initAttrIndexLimit() { 1869 for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { 1870 assert(attrIndexLimit[i] == 0); // decide on it now! 1871 attrIndexLimit[i] = (haveFlagsHi(i)? 63: 32); 1872 List<Attribute.Layout> defList = attrDefs.get(i); 1873 assert(defList.size() == 32); // all predef indexes are <32 1874 int addMore = attrIndexLimit[i] - defList.size(); 1875 defList.addAll(Collections.nCopies(addMore, (Attribute.Layout) null)); 1876 } 1877 } 1878 1879 protected boolean haveFlagsHi(int ctype) { 1880 int mask = 1<<(LG_AO_HAVE_XXX_FLAGS_HI+ctype); 1881 switch (ctype) { 1882 case ATTR_CONTEXT_CLASS: 1883 assert(mask == AO_HAVE_CLASS_FLAGS_HI); break; 1884 case ATTR_CONTEXT_FIELD: 1885 assert(mask == AO_HAVE_FIELD_FLAGS_HI); break; 1886 case ATTR_CONTEXT_METHOD: 1887 assert(mask == AO_HAVE_METHOD_FLAGS_HI); break; 1888 case ATTR_CONTEXT_CODE: 1889 assert(mask == AO_HAVE_CODE_FLAGS_HI); break; 1890 default: 1891 assert(false); 1892 } 1893 return testBit(archiveOptions, mask); 1894 } 1895 1896 protected List getPredefinedAttrs(int ctype) { 1897 assert(attrIndexLimit[ctype] != 0); 1898 List<Attribute.Layout> res = new ArrayList<>(attrIndexLimit[ctype]); 1899 // Remove nulls and non-predefs. 1900 for (int ai = 0; ai < attrIndexLimit[ctype]; ai++) { 1901 if (testBit(attrDefSeen[ctype], 1L<<ai)) continue; 1902 Attribute.Layout def = attrDefs.get(ctype).get(ai); 1903 if (def == null) continue; // unused flag bit 1904 assert(isPredefinedAttr(ctype, ai)); 1905 res.add(def); 1906 } 1907 return res; 1908 } 1909 1910 protected boolean isPredefinedAttr(int ctype, int ai) { 1911 assert(attrIndexLimit[ctype] != 0); 1912 // Overflow attrs are never predefined. 1913 if (ai >= attrIndexLimit[ctype]) return false; 1914 // If the bit is set, it was explicitly def'd. 1915 if (testBit(attrDefSeen[ctype], 1L<<ai)) return false; 1916 return (attrDefs.get(ctype).get(ai) != null); 1917 } 1918 1919 protected void adjustSpecialAttrMasks() { 1920 // Clear special masks if new definitions have been seen for them. 1921 attrClassFileVersionMask &= ~ attrDefSeen[ATTR_CONTEXT_CLASS]; 1922 // It is possible to clear the overflow mask (bit 16). 1923 for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { 1924 attrOverflowMask[i] &= ~ attrDefSeen[i]; 1925 } 1926 } 1927 1928 protected Attribute makeClassFileVersionAttr(int minver, int majver) { 1929 byte[] bytes = { 1930 (byte)(minver >> 8), (byte)minver, 1931 (byte)(majver >> 8), (byte)majver 1932 }; 1933 return attrClassFileVersion.addContent(bytes); 1934 } 1935 1936 protected short[] parseClassFileVersionAttr(Attribute attr) { 1937 assert(attr.layout() == attrClassFileVersion); 1938 assert(attr.size() == 4); 1939 byte[] bytes = attr.bytes(); 1940 int minver = ((bytes[0] & 0xFF) << 8) | (bytes[1] & 0xFF); 1941 int majver = ((bytes[2] & 0xFF) << 8) | (bytes[3] & 0xFF); 1942 return new short[]{ (short) minver, (short) majver }; 1943 } 1944 1945 private boolean assertBandOKForElems(Band[] ab, Attribute.Layout.Element[] elems) { 1946 for (int i = 0; i < elems.length; i++) { 1947 assert(assertBandOKForElem(ab, elems[i])); 1948 } 1949 return true; 1950 } 1951 private boolean assertBandOKForElem(Band[] ab, Attribute.Layout.Element e) { 1952 Band b = null; 1953 if (e.bandIndex != Attribute.NO_BAND_INDEX) 1954 b = ab[e.bandIndex]; 1955 Coding rc = UNSIGNED5; 1956 boolean wantIntBand = true; 1957 switch (e.kind) { 1958 case Attribute.EK_INT: 1959 if (e.flagTest(Attribute.EF_SIGN)) { 1960 rc = SIGNED5; 1961 } else if (e.len == 1) { 1962 rc = BYTE1; 1963 } 1964 break; 1965 case Attribute.EK_BCI: 1966 if (!e.flagTest(Attribute.EF_DELTA)) { 1967 rc = BCI5; 1968 } else { 1969 rc = BRANCH5; 1970 } 1971 break; 1972 case Attribute.EK_BCO: 1973 rc = BRANCH5; 1974 break; 1975 case Attribute.EK_FLAG: 1976 if (e.len == 1) rc = BYTE1; 1977 break; 1978 case Attribute.EK_REPL: 1979 if (e.len == 1) rc = BYTE1; 1980 assertBandOKForElems(ab, e.body); 1981 break; 1982 case Attribute.EK_UN: 1983 if (e.flagTest(Attribute.EF_SIGN)) { 1984 rc = SIGNED5; 1985 } else if (e.len == 1) { 1986 rc = BYTE1; 1987 } 1988 assertBandOKForElems(ab, e.body); 1989 break; 1990 case Attribute.EK_CASE: 1991 assert(b == null); 1992 assertBandOKForElems(ab, e.body); 1993 return true; // no direct band 1994 case Attribute.EK_CALL: 1995 assert(b == null); 1996 return true; // no direct band 1997 case Attribute.EK_CBLE: 1998 assert(b == null); 1999 assertBandOKForElems(ab, e.body); 2000 return true; // no direct band 2001 case Attribute.EK_REF: 2002 wantIntBand = false; 2003 assert(b instanceof CPRefBand); 2004 assert(((CPRefBand)b).nullOK == e.flagTest(Attribute.EF_NULL)); 2005 break; 2006 default: assert(false); 2007 } 2008 assert(b.regularCoding == rc) 2009 : (e+" // "+b); 2010 if (wantIntBand) 2011 assert(b instanceof IntBand); 2012 return true; 2013 } 2014 2015 private 2016 Attribute.Layout predefineAttribute(int index, int ctype, Band[] ab, 2017 String name, String layout) { 2018 // Use Attribute.find to get uniquification of layouts. 2019 Attribute.Layout def = Attribute.find(ctype, name, layout).layout(); 2020 //def.predef = true; 2021 if (index >= 0) { 2022 setAttributeLayoutIndex(def, index); 2023 } 2024 if (ab == null) { 2025 ab = new Band[0]; 2026 } 2027 assert(attrBandTable.get(def) == null); // no redef 2028 attrBandTable.put(def, ab); 2029 assert(def.bandCount == ab.length) 2030 : (def+" // "+Arrays.asList(ab)); 2031 // Let's make sure the band types match: 2032 assert(assertBandOKForElems(ab, def.elems)); 2033 return def; 2034 } 2035 2036 // This version takes bandPrefix/addHere instead of prebuilt Band[] ab. 2037 private 2038 Attribute.Layout predefineAttribute(int index, 2039 String bandPrefix, MultiBand addHere, 2040 Attribute attr) { 2041 //Attribute.Layout def = Attribute.find(ctype, name, layout).layout(); 2042 Attribute.Layout def = attr.layout(); 2043 int ctype = def.ctype(); 2044 return predefineAttribute(index, ctype, 2045 makeNewAttributeBands(bandPrefix, def, 2046 addHere), 2047 def.name(), def.layout()); 2048 } 2049 2050 private 2051 void undefineAttribute(int index, int ctype) { 2052 if (verbose > 1) { 2053 System.out.println("Removing predefined "+ATTR_CONTEXT_NAME[ctype]+ 2054 " attribute on bit "+index); 2055 } 2056 List<Attribute.Layout> defList = attrDefs.get(ctype); 2057 Attribute.Layout def = defList.get(index); 2058 assert(def != null); 2059 defList.set(index, null); 2060 attrIndexTable.put(def, null); 2061 // Clear the def bit. (For predefs, it's already clear.) 2062 assert(index < 64); 2063 attrDefSeen[ctype] &= ~(1L<<index); 2064 attrFlagMask[ctype] &= ~(1L<<index); 2065 Band[] ab = attrBandTable.get(def); 2066 for (int j = 0; j < ab.length; j++) { 2067 ab[j].doneWithUnusedBand(); 2068 } 2069 } 2070 2071 // Bands which contain non-predefined attrs. 2072 protected MultiBand[] attrBands = new MultiBand[ATTR_CONTEXT_LIMIT]; 2073 { 2074 attrBands[ATTR_CONTEXT_CLASS] = class_attr_bands; 2075 attrBands[ATTR_CONTEXT_FIELD] = field_attr_bands; 2076 attrBands[ATTR_CONTEXT_METHOD] = method_attr_bands; 2077 attrBands[ATTR_CONTEXT_CODE] = code_attr_bands; 2078 } 2079 2080 // Create bands for all non-predefined attrs. 2081 void makeNewAttributeBands() { 2082 // Retract special flag bit bindings, if they were taken over. 2083 adjustSpecialAttrMasks(); 2084 2085 for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) { 2086 String cname = ATTR_CONTEXT_NAME[ctype]; 2087 MultiBand xxx_attr_bands = attrBands[ctype]; 2088 long defSeen = attrDefSeen[ctype]; 2089 // Note: attrDefSeen is always a subset of attrFlagMask. 2090 assert((defSeen & ~attrFlagMask[ctype]) == 0); 2091 for (int i = 0; i < attrDefs.get(ctype).size(); i++) { 2092 Attribute.Layout def = attrDefs.get(ctype).get(i); 2093 if (def == null) continue; // unused flag bit 2094 if (def.bandCount == 0) continue; // empty attr 2095 if (i < attrIndexLimit[ctype] && !testBit(defSeen, 1L<<i)) { 2096 // There are already predefined bands here. 2097 assert(attrBandTable.get(def) != null); 2098 continue; 2099 } 2100 int base = xxx_attr_bands.size(); 2101 String pfx = cname+"_"+def.name()+"_"; // debug only 2102 if (verbose > 1) 2103 Utils.log.fine("Making new bands for "+def); 2104 Band[] newAB = makeNewAttributeBands(pfx, def, 2105 xxx_attr_bands); 2106 assert(newAB.length == def.bandCount); 2107 Band[] prevAB = attrBandTable.put(def, newAB); 2108 if (prevAB != null) { 2109 // We won't be using these predefined bands. 2110 for (int j = 0; j < prevAB.length; j++) { 2111 prevAB[j].doneWithUnusedBand(); 2112 } 2113 } 2114 } 2115 } 2116 //System.out.println(prevForAssertMap); 2117 } 2118 private 2119 Band[] makeNewAttributeBands(String pfx, Attribute.Layout def, 2120 MultiBand addHere) { 2121 int base = addHere.size(); 2122 makeNewAttributeBands(pfx, def.elems, addHere); 2123 int nb = addHere.size() - base; 2124 Band[] newAB = new Band[nb]; 2125 for (int i = 0; i < nb; i++) { 2126 newAB[i] = addHere.get(base+i); 2127 } 2128 return newAB; 2129 } 2130 // Recursive helper, operates on a "body" or other sequence of elems: 2131 private 2132 void makeNewAttributeBands(String pfx, Attribute.Layout.Element[] elems, 2133 MultiBand ab) { 2134 for (int i = 0; i < elems.length; i++) { 2135 Attribute.Layout.Element e = elems[i]; 2136 String name = pfx+ab.size()+"_"+e.layout; 2137 { 2138 int tem; 2139 if ((tem = name.indexOf('[')) > 0) 2140 name = name.substring(0, tem); 2141 if ((tem = name.indexOf('(')) > 0) 2142 name = name.substring(0, tem); 2143 if (name.endsWith("H")) 2144 name = name.substring(0, name.length()-1); 2145 } 2146 Band nb; 2147 switch (e.kind) { 2148 case Attribute.EK_INT: 2149 nb = newElemBand(e, name, ab); 2150 break; 2151 case Attribute.EK_BCI: 2152 if (!e.flagTest(Attribute.EF_DELTA)) { 2153 // PH: transmit R(bci), store bci 2154 nb = ab.newIntBand(name, BCI5); 2155 } else { 2156 // POH: transmit D(R(bci)), store bci 2157 nb = ab.newIntBand(name, BRANCH5); 2158 } 2159 // Note: No case for BYTE1 here. 2160 break; 2161 case Attribute.EK_BCO: 2162 // OH: transmit D(R(bci)), store D(bci) 2163 nb = ab.newIntBand(name, BRANCH5); 2164 // Note: No case for BYTE1 here. 2165 break; 2166 case Attribute.EK_FLAG: 2167 assert(!e.flagTest(Attribute.EF_SIGN)); 2168 nb = newElemBand(e, name, ab); 2169 break; 2170 case Attribute.EK_REPL: 2171 assert(!e.flagTest(Attribute.EF_SIGN)); 2172 nb = newElemBand(e, name, ab); 2173 makeNewAttributeBands(pfx, e.body, ab); 2174 break; 2175 case Attribute.EK_UN: 2176 nb = newElemBand(e, name, ab); 2177 makeNewAttributeBands(pfx, e.body, ab); 2178 break; 2179 case Attribute.EK_CASE: 2180 if (!e.flagTest(Attribute.EF_BACK)) { 2181 // If it's not a duplicate body, make the bands. 2182 makeNewAttributeBands(pfx, e.body, ab); 2183 } 2184 continue; // no new band to make 2185 case Attribute.EK_REF: 2186 byte refKind = e.refKind; 2187 boolean nullOK = e.flagTest(Attribute.EF_NULL); 2188 nb = ab.newCPRefBand(name, UNSIGNED5, refKind, nullOK); 2189 // Note: No case for BYTE1 here. 2190 break; 2191 case Attribute.EK_CALL: 2192 continue; // no new band to make 2193 case Attribute.EK_CBLE: 2194 makeNewAttributeBands(pfx, e.body, ab); 2195 continue; // no new band to make 2196 default: assert(false); continue; 2197 } 2198 if (verbose > 1) { 2199 Utils.log.fine("New attribute band "+nb); 2200 } 2201 } 2202 } 2203 private 2204 Band newElemBand(Attribute.Layout.Element e, String name, MultiBand ab) { 2205 if (e.flagTest(Attribute.EF_SIGN)) { 2206 return ab.newIntBand(name, SIGNED5); 2207 } else if (e.len == 1) { 2208 return ab.newIntBand(name, BYTE1); // Not ByteBand, please. 2209 } else { 2210 return ab.newIntBand(name, UNSIGNED5); 2211 } 2212 } 2213 2214 protected int setAttributeLayoutIndex(Attribute.Layout def, int index) { 2215 int ctype = def.ctype; 2216 assert(ATTR_INDEX_OVERFLOW <= index && index < attrIndexLimit[ctype]); 2217 List<Attribute.Layout> defList = attrDefs.get(ctype); 2218 if (index == ATTR_INDEX_OVERFLOW) { 2219 // Overflow attribute. 2220 index = defList.size(); 2221 defList.add(def); 2222 if (verbose > 0) 2223 Utils.log.info("Adding new attribute at "+def +": "+index); 2224 attrIndexTable.put(def, index); 2225 return index; 2226 } 2227 2228 // Detect redefinitions: 2229 if (testBit(attrDefSeen[ctype], 1L<<index)) { 2230 throw new RuntimeException("Multiple explicit definition at "+index+": "+def); 2231 } 2232 attrDefSeen[ctype] |= (1L<<index); 2233 2234 // Adding a new fixed attribute. 2235 assert(0 <= index && index < attrIndexLimit[ctype]); 2236 if (verbose > (attrClassFileVersionMask == 0? 2:0)) 2237 Utils.log.fine("Fixing new attribute at "+index 2238 +": "+def 2239 +(defList.get(index) == null? "": 2240 "; replacing "+defList.get(index))); 2241 attrFlagMask[ctype] |= (1L<<index); 2242 // Remove index binding of any previous fixed attr. 2243 attrIndexTable.put(defList.get(index), null); 2244 defList.set(index, def); 2245 attrIndexTable.put(def, index); 2246 return index; 2247 } 2248 2249 // encodings found in the code_headers band 2250 private static final int[][] shortCodeLimits = { 2251 { 12, 12 }, // s<12, l<12, e=0 [1..144] 2252 { 8, 8 }, // s<8, l<8, e=1 [145..208] 2253 { 7, 7 }, // s<7, l<7, e=2 [209..256] 2254 }; 2255 public final int shortCodeHeader_h_limit = shortCodeLimits.length; 2256 2257 // return 0 if it won't encode, else a number in [1..255] 2258 static int shortCodeHeader(Code code) { 2259 int s = code.max_stack; 2260 int l0 = code.max_locals; 2261 int h = code.handler_class.length; 2262 if (h >= shortCodeLimits.length) return LONG_CODE_HEADER; 2263 int siglen = code.getMethod().getArgumentSize(); 2264 assert(l0 >= siglen); // enough locals for signature! 2265 if (l0 < siglen) return LONG_CODE_HEADER; 2266 int l1 = l0 - siglen; // do not count locals required by the signature 2267 int lims = shortCodeLimits[h][0]; 2268 int liml = shortCodeLimits[h][1]; 2269 if (s >= lims || l1 >= liml) return LONG_CODE_HEADER; 2270 int sc = shortCodeHeader_h_base(h); 2271 sc += s + lims*l1; 2272 if (sc > 255) return LONG_CODE_HEADER; 2273 assert(shortCodeHeader_max_stack(sc) == s); 2274 assert(shortCodeHeader_max_na_locals(sc) == l1); 2275 assert(shortCodeHeader_handler_count(sc) == h); 2276 return sc; 2277 } 2278 2279 static final int LONG_CODE_HEADER = 0; 2280 static int shortCodeHeader_handler_count(int sc) { 2281 assert(sc > 0 && sc <= 255); 2282 for (int h = 0; ; h++) { 2283 if (sc < shortCodeHeader_h_base(h+1)) 2284 return h; 2285 } 2286 } 2287 static int shortCodeHeader_max_stack(int sc) { 2288 int h = shortCodeHeader_handler_count(sc); 2289 int lims = shortCodeLimits[h][0]; 2290 return (sc - shortCodeHeader_h_base(h)) % lims; 2291 } 2292 static int shortCodeHeader_max_na_locals(int sc) { 2293 int h = shortCodeHeader_handler_count(sc); 2294 int lims = shortCodeLimits[h][0]; 2295 return (sc - shortCodeHeader_h_base(h)) / lims; 2296 } 2297 2298 private static int shortCodeHeader_h_base(int h) { 2299 assert(h <= shortCodeLimits.length); 2300 int sc = 1; 2301 for (int h0 = 0; h0 < h; h0++) { 2302 int lims = shortCodeLimits[h0][0]; 2303 int liml = shortCodeLimits[h0][1]; 2304 sc += lims * liml; 2305 } 2306 return sc; 2307 } 2308 2309 // utilities for accessing the bc_label band: 2310 protected void putLabel(IntBand bc_label, Code c, int pc, int targetPC) { 2311 bc_label.putInt(c.encodeBCI(targetPC) - c.encodeBCI(pc)); 2312 } 2313 protected int getLabel(IntBand bc_label, Code c, int pc) { 2314 return c.decodeBCI(bc_label.getInt() + c.encodeBCI(pc)); 2315 } 2316 2317 protected CPRefBand getCPRefOpBand(int bc) { 2318 switch (Instruction.getCPRefOpTag(bc)) { 2319 case CONSTANT_Class: 2320 return bc_classref; 2321 case CONSTANT_Fieldref: 2322 return bc_fieldref; 2323 case CONSTANT_Methodref: 2324 return bc_methodref; 2325 case CONSTANT_InterfaceMethodref: 2326 return bc_imethodref; 2327 case CONSTANT_Literal: 2328 switch (bc) { 2329 case _ildc: case _ildc_w: 2330 return bc_intref; 2331 case _fldc: case _fldc_w: 2332 return bc_floatref; 2333 case _lldc2_w: 2334 return bc_longref; 2335 case _dldc2_w: 2336 return bc_doubleref; 2337 case _aldc: case _aldc_w: 2338 return bc_stringref; 2339 case _cldc: case _cldc_w: 2340 return bc_classref; 2341 } 2342 break; 2343 } 2344 assert(false); 2345 return null; 2346 } 2347 2348 protected CPRefBand selfOpRefBand(int self_bc) { 2349 assert(Instruction.isSelfLinkerOp(self_bc)); 2350 int idx = (self_bc - _self_linker_op); 2351 boolean isSuper = (idx >= _self_linker_super_flag); 2352 if (isSuper) idx -= _self_linker_super_flag; 2353 boolean isAload = (idx >= _self_linker_aload_flag); 2354 if (isAload) idx -= _self_linker_aload_flag; 2355 int origBC = _first_linker_op + idx; 2356 boolean isField = Instruction.isFieldOp(origBC); 2357 if (!isSuper) 2358 return isField? bc_thisfield: bc_thismethod; 2359 else 2360 return isField? bc_superfield: bc_supermethod; 2361 } 2362 2363 //////////////////////////////////////////////////////////////////// 2364 2365 static int nextSeqForDebug; 2366 static File dumpDir = null; 2367 static OutputStream getDumpStream(Band b, String ext) throws IOException { 2368 return getDumpStream(b.name, b.seqForDebug, ext, b); 2369 } 2370 static OutputStream getDumpStream(Index ix, String ext) throws IOException { 2371 if (ix.size() == 0) return new ByteArrayOutputStream(); 2372 int seq = ConstantPool.TAG_ORDER[ix.cpMap[0].tag]; 2373 return getDumpStream(ix.debugName, seq, ext, ix); 2374 } 2375 static OutputStream getDumpStream(String name, int seq, String ext, Object b) throws IOException { 2376 if (dumpDir == null) { 2377 dumpDir = File.createTempFile("BD_", "", new File(".")); 2378 dumpDir.delete(); 2379 if (dumpDir.mkdir()) 2380 Utils.log.info("Dumping bands to "+dumpDir); 2381 } 2382 name = name.replace('(', ' ').replace(')', ' '); 2383 name = name.replace('/', ' '); 2384 name = name.replace('*', ' '); 2385 name = name.trim().replace(' ','_'); 2386 name = ((10000+seq) + "_" + name).substring(1); 2387 File dumpFile = new File(dumpDir, name+ext); 2388 Utils.log.info("Dumping "+b+" to "+dumpFile); 2389 return new BufferedOutputStream(new FileOutputStream(dumpFile)); 2390 } 2391 2392 // DEBUG ONLY: Validate me at each length change. 2393 static boolean assertCanChangeLength(Band b) { 2394 switch (b.phase) { 2395 case COLLECT_PHASE: 2396 case READ_PHASE: 2397 return true; 2398 } 2399 return false; 2400 } 2401 2402 // DEBUG ONLY: Validate a phase. 2403 static boolean assertPhase(Band b, int phaseExpected) { 2404 if (b.phase() != phaseExpected) { 2405 Utils.log.warning("phase expected "+phaseExpected+" was "+b.phase()+" in "+b); 2406 return false; 2407 } 2408 return true; 2409 } 2410 2411 2412 // DEBUG ONLY: Tells whether verbosity is turned on. 2413 static int verbose() { 2414 return Utils.currentPropMap().getInteger(Utils.DEBUG_VERBOSE); 2415 } 2416 2417 2418 // DEBUG ONLY: Validate me at each phase change. 2419 static boolean assertPhaseChangeOK(Band b, int p0, int p1) { 2420 switch (p0*10+p1) { 2421 /// Writing phases: 2422 case NO_PHASE*10+COLLECT_PHASE: 2423 // Ready to collect data from the input classes. 2424 assert(!b.isReader()); 2425 assert(b.capacity() >= 0); 2426 assert(b.length() == 0); 2427 return true; 2428 case COLLECT_PHASE*10+FROZEN_PHASE: 2429 case FROZEN_PHASE*10+FROZEN_PHASE: 2430 assert(b.length() == 0); 2431 return true; 2432 case COLLECT_PHASE*10+WRITE_PHASE: 2433 case FROZEN_PHASE*10+WRITE_PHASE: 2434 // Data is all collected. Ready to write bytes to disk. 2435 return true; 2436 case WRITE_PHASE*10+DONE_PHASE: 2437 // Done writing to disk. Ready to reset, in principle. 2438 return true; 2439 2440 /// Reading phases: 2441 case NO_PHASE*10+EXPECT_PHASE: 2442 assert(b.isReader()); 2443 assert(b.capacity() < 0); 2444 return true; 2445 case EXPECT_PHASE*10+READ_PHASE: 2446 // Ready to read values from disk. 2447 assert(Math.max(0,b.capacity()) >= b.valuesExpected()); 2448 assert(b.length() <= 0); 2449 return true; 2450 case READ_PHASE*10+DISBURSE_PHASE: 2451 // Ready to disburse values. 2452 assert(b.valuesRemainingForDebug() == b.length()); 2453 return true; 2454 case DISBURSE_PHASE*10+DONE_PHASE: 2455 // Done disbursing values. Ready to reset, in principle. 2456 assert(assertDoneDisbursing(b)); 2457 return true; 2458 } 2459 if (p0 == p1) 2460 Utils.log.warning("Already in phase "+p0); 2461 else 2462 Utils.log.warning("Unexpected phase "+p0+" -> "+p1); 2463 return false; 2464 } 2465 2466 static private boolean assertDoneDisbursing(Band b) { 2467 if (b.phase != DISBURSE_PHASE) { 2468 Utils.log.warning("assertDoneDisbursing: still in phase "+b.phase+": "+b); 2469 if (verbose() <= 1) return false; // fail now 2470 } 2471 int left = b.valuesRemainingForDebug(); 2472 if (left > 0) { 2473 Utils.log.warning("assertDoneDisbursing: "+left+" values left in "+b); 2474 if (verbose() <= 1) return false; // fail now 2475 } 2476 if (b instanceof MultiBand) { 2477 MultiBand mb = (MultiBand) b; 2478 for (int i = 0; i < mb.bandCount; i++) { 2479 Band sub = mb.bands[i]; 2480 if (sub.phase != DONE_PHASE) { 2481 Utils.log.warning("assertDoneDisbursing: sub-band still in phase "+sub.phase+": "+sub); 2482 if (verbose() <= 1) return false; // fail now 2483 } 2484 } 2485 } 2486 return true; 2487 } 2488 2489 static private void printCDecl(Band b) { 2490 if (b instanceof MultiBand) { 2491 MultiBand mb = (MultiBand) b; 2492 for (int i = 0; i < mb.bandCount; i++) { 2493 printCDecl(mb.bands[i]); 2494 } 2495 return; 2496 } 2497 String ixS = "NULL"; 2498 if (b instanceof CPRefBand) { 2499 Index ix = ((CPRefBand)b).index; 2500 if (ix != null) ixS = "INDEX("+ix.debugName+")"; 2501 } 2502 Coding[] knownc = { BYTE1, CHAR3, BCI5, BRANCH5, UNSIGNED5, 2503 UDELTA5, SIGNED5, DELTA5, MDELTA5 }; 2504 String[] knowns = { "BYTE1", "CHAR3", "BCI5", "BRANCH5", "UNSIGNED5", 2505 "UDELTA5", "SIGNED5", "DELTA5", "MDELTA5" }; 2506 Coding rc = b.regularCoding; 2507 int rci = Arrays.asList(knownc).indexOf(rc); 2508 String cstr; 2509 if (rci >= 0) 2510 cstr = knowns[rci]; 2511 else 2512 cstr = "CODING"+rc.keyString(); 2513 System.out.println(" BAND_INIT(\""+b.name()+"\"" 2514 +", "+cstr+", "+ixS+"),"); 2515 } 2516 2517 private Map<Band, Band> prevForAssertMap; 2518 2519 // DEBUG ONLY: Record something about the band order. 2520 boolean notePrevForAssert(Band b, Band p) { 2521 if (prevForAssertMap == null) 2522 prevForAssertMap = new HashMap<>(); 2523 prevForAssertMap.put(b, p); 2524 return true; 2525 } 2526 2527 // DEBUG ONLY: Validate next input band. 2528 private boolean assertReadyToReadFrom(Band b, InputStream in) throws IOException { 2529 Band p = prevForAssertMap.get(b); 2530 // Any previous band must be done reading before this one starts. 2531 if (p != null && phaseCmp(p.phase(), DISBURSE_PHASE) < 0) { 2532 Utils.log.warning("Previous band not done reading."); 2533 Utils.log.info(" Previous band: "+p); 2534 Utils.log.info(" Next band: "+b); 2535 Thread.dumpStack(); 2536 assert(verbose > 0); // die unless verbose is true 2537 } 2538 String name = b.name; 2539 if (optDebugBands && !name.startsWith("(")) { 2540 // Verify synchronization between reader & writer: 2541 StringBuilder buf = new StringBuilder(); 2542 int ch; 2543 while ((ch = in.read()) > 0) 2544 buf.append((char)ch); 2545 String inName = buf.toString(); 2546 if (!inName.equals(name)) { 2547 StringBuilder sb = new StringBuilder(); 2548 sb.append("Expected "+name+" but read: "); 2549 inName += (char)ch; 2550 while (inName.length() < 10) { 2551 inName += (char) in.read(); 2552 } 2553 for (int i = 0; i < inName.length(); i++) { 2554 sb.append(inName.charAt(i)); 2555 } 2556 Utils.log.warning(sb.toString()); 2557 return false; 2558 } 2559 } 2560 return true; 2561 } 2562 2563 // DEBUG ONLY: Make sure a bunch of cprefs are correct. 2564 private boolean assertValidCPRefs(CPRefBand b) { 2565 if (b.index == null) return true; 2566 int limit = b.index.size()+1; 2567 for (int i = 0; i < b.length(); i++) { 2568 int v = b.valueAtForDebug(i); 2569 if (v < 0 || v >= limit) { 2570 Utils.log.warning("CP ref out of range "+ 2571 "["+i+"] = "+v+" in "+b); 2572 return false; 2573 } 2574 } 2575 return true; 2576 } 2577 2578 // DEBUG ONLY: Maybe write a debugging cookie to next output band. 2579 private boolean assertReadyToWriteTo(Band b, OutputStream out) throws IOException { 2580 Band p = prevForAssertMap.get(b); 2581 // Any previous band must be done writing before this one starts. 2582 if (p != null && phaseCmp(p.phase(), DONE_PHASE) < 0) { 2583 Utils.log.warning("Previous band not done writing."); 2584 Utils.log.info(" Previous band: "+p); 2585 Utils.log.info(" Next band: "+b); 2586 Thread.dumpStack(); 2587 assert(verbose > 0); // die unless verbose is true 2588 } 2589 String name = b.name; 2590 if (optDebugBands && !name.startsWith("(")) { 2591 // Verify synchronization between reader & writer: 2592 for (int j = 0; j < name.length(); j++) { 2593 out.write((byte)name.charAt(j)); 2594 } 2595 out.write((byte)0); 2596 } 2597 return true; 2598 } 2599 2600 protected static boolean testBit(int flags, int bitMask) { 2601 return (flags & bitMask) != 0; 2602 } 2603 protected static int setBit(int flags, int bitMask, boolean z) { 2604 return z ? (flags | bitMask) : (flags &~ bitMask); 2605 } 2606 protected static boolean testBit(long flags, long bitMask) { 2607 return (flags & bitMask) != 0; 2608 } 2609 protected static long setBit(long flags, long bitMask, boolean z) { 2610 return z ? (flags | bitMask) : (flags &~ bitMask); 2611 } 2612 2613 2614 static void printArrayTo(PrintStream ps, int[] values, int start, int end) { 2615 int len = end-start; 2616 for (int i = 0; i < len; i++) { 2617 if (i % 10 == 0) 2618 ps.println(); 2619 else 2620 ps.print(" "); 2621 ps.print(values[start+i]); 2622 } 2623 ps.println(); 2624 } 2625 2626 static void printArrayTo(PrintStream ps, Entry[] cpMap, int start, int end) { 2627 StringBuffer buf = new StringBuffer(); 2628 int len = end-start; 2629 for (int i = 0; i < len; i++) { 2630 String s = cpMap[start+i].stringValue(); 2631 buf.setLength(0); 2632 for (int j = 0; j < s.length(); j++) { 2633 char ch = s.charAt(j); 2634 if (!(ch < ' ' || ch > '~' || ch == '\\')) { 2635 buf.append(ch); 2636 } else if (ch == '\n') { 2637 buf.append("\\n"); 2638 } else if (ch == '\t') { 2639 buf.append("\\t"); 2640 } else if (ch == '\r') { 2641 buf.append("\\r"); 2642 } else { 2643 buf.append("\\x"+Integer.toHexString(ch)); 2644 } 2645 } 2646 ps.println(buf); 2647 } 2648 } 2649 2650 2651 // Utilities for reallocating: 2652 protected static Object[] realloc(Object[] a, int len) { 2653 java.lang.Class elt = a.getClass().getComponentType(); 2654 Object[] na = (Object[]) java.lang.reflect.Array.newInstance(elt, len); 2655 System.arraycopy(a, 0, na, 0, Math.min(a.length, len)); 2656 return na; 2657 } 2658 protected static Object[] realloc(Object[] a) { 2659 return realloc(a, Math.max(10, a.length*2)); 2660 } 2661 2662 protected static int[] realloc(int[] a, int len) { 2663 if (len == 0) return noInts; 2664 if (a == null) return new int[len]; 2665 int[] na = new int[len]; 2666 System.arraycopy(a, 0, na, 0, Math.min(a.length, len)); 2667 return na; 2668 } 2669 protected static int[] realloc(int[] a) { 2670 return realloc(a, Math.max(10, a.length*2)); 2671 } 2672 2673 protected static byte[] realloc(byte[] a, int len) { 2674 if (len == 0) return noBytes; 2675 if (a == null) return new byte[len]; 2676 byte[] na = new byte[len]; 2677 System.arraycopy(a, 0, na, 0, Math.min(a.length, len)); 2678 return na; 2679 } 2680 protected static byte[] realloc(byte[] a) { 2681 return realloc(a, Math.max(10, a.length*2)); 2682 } 2683 }