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