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