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