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