1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.commons.compress.harmony.pack200;
20
21 import java.io.IOException;
22 import java.io.OutputStream;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Comparator;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Set;
31
32 import org.apache.commons.compress.harmony.pack200.AttributeDefinitionBands.AttributeDefinition;
33 import org.apache.commons.compress.harmony.pack200.IcBands.IcTuple;
34 import org.apache.commons.compress.harmony.pack200.Segment.SegmentMethodVisitor;
35 import org.objectweb.asm.Label;
36 import org.objectweb.asm.Opcodes;
37
38
39
40
41 public class ClassBands extends BandSet {
42
43 private static final class TempParamAnnotation {
44
45 int numParams;
46 int[] annoN;
47 IntList pairN = new IntList();
48 List<String> typeRS = new ArrayList<>();
49 List<String> nameRU = new ArrayList<>();
50 List<String> tags = new ArrayList<>();
51 List<Object> values = new ArrayList<>();
52 List<Integer> caseArrayN = new ArrayList<>();
53 List<String> nestTypeRS = new ArrayList<>();
54 List<String> nestNameRU = new ArrayList<>();
55 List<Integer> nestPairN = new ArrayList<>();
56
57 TempParamAnnotation(final int numParams) {
58 this.numParams = numParams;
59 annoN = new int[numParams];
60 }
61
62 void addParameterAnnotation(final int parameter, final String desc, final List<String> nameRU, final List<String> tags,
63 final List<Object> values, final List<Integer> caseArrayN, final List<String> nestTypeRS, final List<String> nestNameRU,
64 final List<Integer> nestPairN) {
65 annoN[parameter]++;
66 typeRS.add(desc);
67 pairN.add(nameRU.size());
68 this.nameRU.addAll(nameRU);
69 this.tags.addAll(tags);
70 this.values.addAll(values);
71 this.caseArrayN.addAll(caseArrayN);
72 this.nestTypeRS.addAll(nestTypeRS);
73 this.nestNameRU.addAll(nestNameRU);
74 this.nestPairN.addAll(nestPairN);
75 }
76 }
77
78 private static final long[] EMPTY_LONG_ARRAY = {};
79
80
81
82
83
84
85
86 protected static int countArgs(final String descriptor) {
87 final int bra = descriptor.indexOf('(');
88 final int ket = descriptor.indexOf(')');
89 if (bra == -1 || ket == -1 || ket < bra) {
90 throw new IllegalArgumentException("No arguments");
91 }
92
93 boolean inType = false;
94 boolean consumingNextType = false;
95 int count = 0;
96 for (int i = bra + 1; i < ket; i++) {
97 final char charAt = descriptor.charAt(i);
98 if (inType && charAt == ';') {
99 inType = false;
100 consumingNextType = false;
101 } else if (!inType && charAt == 'L') {
102 inType = true;
103 count++;
104 } else if (charAt == '[') {
105 consumingNextType = true;
106 } else if (inType) {
107
108 } else if (consumingNextType) {
109 count++;
110 consumingNextType = false;
111 } else if (charAt == 'D' || charAt == 'J') {
112 count += 2;
113 } else {
114 count++;
115 }
116 }
117 return count;
118 }
119
120 private final CpBands cpBands;
121 private final AttributeDefinitionBands attrBands;
122 private final CPClass[] class_this;
123 private final CPClass[] class_super;
124
125 private final CPClass[][] class_interface;
126
127 private final int[] class_interface_count;
128 private final int[] major_versions;
129 private final long[] class_flags;
130 private int[] class_attr_calls;
131 private final List<CPUTF8> classSourceFile = new ArrayList<>();
132 private final List<ConstantPoolEntry> classEnclosingMethodClass = new ArrayList<>();
133
134 private final List<ConstantPoolEntry> classEnclosingMethodDesc = new ArrayList<>();
135 private final List<CPSignature> classSignature = new ArrayList<>();
136
137 private final IntList classFileVersionMinor = new IntList();
138 private final IntList classFileVersionMajor = new IntList();
139 private final int[] class_field_count;
140 private final CPNameAndType[][] field_descr;
141 private final long[][] field_flags;
142 private int[] field_attr_calls;
143
144 private final List<CPConstant<?>> fieldConstantValueKQ = new ArrayList<>();
145 private final List<CPSignature> fieldSignature = new ArrayList<>();
146 private final int[] class_method_count;
147 private final CPNameAndType[][] method_descr;
148 private final long[][] method_flags;
149 private int[] method_attr_calls;
150 private final List<CPSignature> methodSignature = new ArrayList<>();
151
152 private final IntList methodExceptionNumber = new IntList();
153 private final List<CPClass> methodExceptionClasses = new ArrayList<>();
154 private int[] codeHeaders;
155 private final IntList codeMaxStack = new IntList();
156 private final IntList codeMaxLocals = new IntList();
157 private final IntList codeHandlerCount = new IntList();
158 private final List codeHandlerStartP = new ArrayList();
159 private final List codeHandlerEndPO = new ArrayList();
160 private final List codeHandlerCatchPO = new ArrayList();
161 private final List<CPClass> codeHandlerClass = new ArrayList<>();
162 private final List<Long> codeFlags = new ArrayList<>();
163 private int[] code_attr_calls;
164 private final IntList codeLineNumberTableN = new IntList();
165 private final List codeLineNumberTableBciP = new ArrayList();
166 private final IntList codeLineNumberTableLine = new IntList();
167 private final IntList codeLocalVariableTableN = new IntList();
168 private final List codeLocalVariableTableBciP = new ArrayList();
169 private final List codeLocalVariableTableSpanO = new ArrayList();
170 private final List<ConstantPoolEntry> codeLocalVariableTableNameRU = new ArrayList<>();
171 private final List<ConstantPoolEntry> codeLocalVariableTableTypeRS = new ArrayList<>();
172 private final IntList codeLocalVariableTableSlot = new IntList();
173 private final IntList codeLocalVariableTypeTableN = new IntList();
174 private final List codeLocalVariableTypeTableBciP = new ArrayList();
175 private final List codeLocalVariableTypeTableSpanO = new ArrayList();
176 private final List<ConstantPoolEntry> codeLocalVariableTypeTableNameRU = new ArrayList<>();
177
178 private final List<ConstantPoolEntry> codeLocalVariableTypeTableTypeRS = new ArrayList<>();
179 private final IntList codeLocalVariableTypeTableSlot = new IntList();
180 private final MetadataBandGroup class_RVA_bands;
181 private final MetadataBandGroup class_RIA_bands;
182 private final MetadataBandGroup field_RVA_bands;
183 private final MetadataBandGroup field_RIA_bands;
184 private final MetadataBandGroup method_RVA_bands;
185 private final MetadataBandGroup method_RIA_bands;
186 private final MetadataBandGroup method_RVPA_bands;
187
188 private final MetadataBandGroup method_RIPA_bands;
189 private final MetadataBandGroup method_AD_bands;
190 private final List<NewAttributeBands> classAttributeBands = new ArrayList<>();
191 private final List<NewAttributeBands> methodAttributeBands = new ArrayList<>();
192
193 private final List<NewAttributeBands> fieldAttributeBands = new ArrayList<>();
194 private final List<NewAttributeBands> codeAttributeBands = new ArrayList<>();
195 private final List<Long> tempFieldFlags = new ArrayList<>();
196 private final List<CPNameAndType> tempFieldDesc = new ArrayList<>();
197 private final List<Long> tempMethodFlags = new ArrayList<>();
198 private final List<CPNameAndType> tempMethodDesc = new ArrayList<>();
199
200 private TempParamAnnotation tempMethodRVPA;
201 private TempParamAnnotation tempMethodRIPA;
202 private boolean anySyntheticClasses;
203 private boolean anySyntheticFields;
204
205 private boolean anySyntheticMethods;
206 private final Segment segment;
207
208 private final Map<CPClass, Set<CPClass>> classReferencesInnerClass = new HashMap<>();
209
210 private final boolean stripDebug;
211 private int index;
212 private int numMethodArgs;
213 private int[] class_InnerClasses_N;
214 private CPClass[] class_InnerClasses_RC;
215 private int[] class_InnerClasses_F;
216
217 private List<CPClass> classInnerClassesOuterRCN;
218
219 private List<CPUTF8> classInnerClassesNameRUN;
220
221 public ClassBands(final Segment segment, final int numClasses, final int effort, final boolean stripDebug) throws IOException {
222 super(effort, segment.getSegmentHeader());
223 this.stripDebug = stripDebug;
224 this.segment = segment;
225 this.cpBands = segment.getCpBands();
226 this.attrBands = segment.getAttrBands();
227 class_this = new CPClass[numClasses];
228 class_super = new CPClass[numClasses];
229 class_interface_count = new int[numClasses];
230 class_interface = new CPClass[numClasses][];
231 class_field_count = new int[numClasses];
232 class_method_count = new int[numClasses];
233 field_descr = new CPNameAndType[numClasses][];
234 field_flags = new long[numClasses][];
235 method_descr = new CPNameAndType[numClasses][];
236 method_flags = new long[numClasses][];
237 for (int i = 0; i < numClasses; i++) {
238 field_flags[i] = EMPTY_LONG_ARRAY;
239 method_flags[i] = EMPTY_LONG_ARRAY;
240 }
241
242 major_versions = new int[numClasses];
243 class_flags = new long[numClasses];
244
245 class_RVA_bands = new MetadataBandGroup("RVA", MetadataBandGroup.CONTEXT_CLASS, cpBands, segmentHeader, effort);
246 class_RIA_bands = new MetadataBandGroup("RIA", MetadataBandGroup.CONTEXT_CLASS, cpBands, segmentHeader, effort);
247 field_RVA_bands = new MetadataBandGroup("RVA", MetadataBandGroup.CONTEXT_FIELD, cpBands, segmentHeader, effort);
248 field_RIA_bands = new MetadataBandGroup("RIA", MetadataBandGroup.CONTEXT_FIELD, cpBands, segmentHeader, effort);
249 method_RVA_bands = new MetadataBandGroup("RVA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
250 method_RIA_bands = new MetadataBandGroup("RIA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
251 method_RVPA_bands = new MetadataBandGroup("RVPA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
252 method_RIPA_bands = new MetadataBandGroup("RIPA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
253 method_AD_bands = new MetadataBandGroup("AD", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
254
255 createNewAttributeBands();
256 }
257
258 public void addAnnotation(final int context, final String desc, final boolean visible, final List<String> nameRU, final List<String> tags,
259 final List<Object> values, final List<Integer> caseArrayN, final List<String> nestTypeRS, final List<String> nestNameRU,
260 final List<Integer> nestPairN) {
261 switch (context) {
262 case MetadataBandGroup.CONTEXT_CLASS:
263 if (visible) {
264 class_RVA_bands.addAnnotation(desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
265 if ((class_flags[index] & 1 << 21) != 0) {
266 class_RVA_bands.incrementAnnoN();
267 } else {
268 class_RVA_bands.newEntryInAnnoN();
269 class_flags[index] = class_flags[index] | 1 << 21;
270 }
271 } else {
272 class_RIA_bands.addAnnotation(desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
273 if ((class_flags[index] & 1 << 22) != 0) {
274 class_RIA_bands.incrementAnnoN();
275 } else {
276 class_RIA_bands.newEntryInAnnoN();
277 class_flags[index] = class_flags[index] | 1 << 22;
278 }
279 }
280 break;
281 case MetadataBandGroup.CONTEXT_FIELD:
282 if (visible) {
283 field_RVA_bands.addAnnotation(desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
284 final Long flag = tempFieldFlags.remove(tempFieldFlags.size() - 1);
285 if ((flag.intValue() & 1 << 21) != 0) {
286 field_RVA_bands.incrementAnnoN();
287 } else {
288 field_RVA_bands.newEntryInAnnoN();
289 }
290 tempFieldFlags.add(Long.valueOf(flag.intValue() | 1 << 21));
291 } else {
292 field_RIA_bands.addAnnotation(desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
293 final Long flag = tempFieldFlags.remove(tempFieldFlags.size() - 1);
294 if ((flag.intValue() & 1 << 22) != 0) {
295 field_RIA_bands.incrementAnnoN();
296 } else {
297 field_RIA_bands.newEntryInAnnoN();
298 }
299 tempFieldFlags.add(Long.valueOf(flag.intValue() | 1 << 22));
300 }
301 break;
302 case MetadataBandGroup.CONTEXT_METHOD:
303 if (visible) {
304 method_RVA_bands.addAnnotation(desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
305 final Long flag = tempMethodFlags.remove(tempMethodFlags.size() - 1);
306 if ((flag.intValue() & 1 << 21) != 0) {
307 method_RVA_bands.incrementAnnoN();
308 } else {
309 method_RVA_bands.newEntryInAnnoN();
310 }
311 tempMethodFlags.add(Long.valueOf(flag.intValue() | 1 << 21));
312 } else {
313 method_RIA_bands.addAnnotation(desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
314 final Long flag = tempMethodFlags.remove(tempMethodFlags.size() - 1);
315 if ((flag.intValue() & 1 << 22) != 0) {
316 method_RIA_bands.incrementAnnoN();
317 } else {
318 method_RIA_bands.newEntryInAnnoN();
319 }
320 tempMethodFlags.add(Long.valueOf(flag.intValue() | 1 << 22));
321 }
322 break;
323 }
324 }
325
326 public void addAnnotationDefault(final List<String> nameRU, final List<String> tags, final List<Object> values, final List<Integer> caseArrayN,
327 final List<String> nestTypeRS, final List<String> nestNameRU, final List<Integer> nestPairN) {
328 method_AD_bands.addAnnotation(null, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
329 final Long flag = tempMethodFlags.remove(tempMethodFlags.size() - 1);
330 tempMethodFlags.add(Long.valueOf(flag.longValue() | 1 << 25));
331 }
332
333 public void addClass(final int major, final int flags, final String className, final String signature, final String superName, final String[] interfaces) {
334 class_this[index] = cpBands.getCPClass(className);
335 class_super[index] = cpBands.getCPClass(superName);
336 class_interface_count[index] = interfaces.length;
337 class_interface[index] = new CPClass[interfaces.length];
338 Arrays.setAll(class_interface[index], i -> cpBands.getCPClass(interfaces[i]));
339 major_versions[index] = major;
340 class_flags[index] = flags;
341 if (!anySyntheticClasses && (flags & 1 << 12) != 0 && segment.getCurrentClassReader().hasSyntheticAttributes()) {
342 cpBands.addCPUtf8("Synthetic");
343 anySyntheticClasses = true;
344 }
345
346
347
348
349 if (signature != null) {
350 class_flags[index] |= 1 << 19;
351 classSignature.add(cpBands.getCPSignature(signature));
352 }
353 }
354
355
356
357
358
359
360 public void addClassAttribute(final NewAttribute attribute) {
361
362 final String attributeName = attribute.type;
363 for (final NewAttributeBands bands : classAttributeBands) {
364 if (bands.getAttributeName().equals(attributeName)) {
365 bands.addAttribute(attribute);
366 final int flagIndex = bands.getFlagIndex();
367 class_flags[index] |= 1 << flagIndex;
368 return;
369 }
370 }
371 throw new IllegalArgumentException("No suitable definition for " + attributeName);
372 }
373
374 public void addCode() {
375 codeHandlerCount.add(0);
376 if (!stripDebug) {
377 codeFlags.add(Long.valueOf(1 << 2));
378 codeLocalVariableTableN.add(0);
379 }
380 }
381
382
383
384
385
386
387 public void addCodeAttribute(final NewAttribute attribute) {
388 final String attributeName = attribute.type;
389 for (final NewAttributeBands bands : codeAttributeBands) {
390 if (bands.getAttributeName().equals(attributeName)) {
391 bands.addAttribute(attribute);
392 final int flagIndex = bands.getFlagIndex();
393 final Long flags = codeFlags.remove(codeFlags.size() - 1);
394 codeFlags.add(Long.valueOf(flags.longValue() | 1 << flagIndex));
395 return;
396 }
397 }
398 throw new IllegalArgumentException("No suitable definition for " + attributeName);
399 }
400
401
402
403
404
405
406
407
408 public void addEnclosingMethod(final String ownerClassName, final String name, final String signature) {
409 class_flags[index] |= 1 << 18;
410 classEnclosingMethodClass.add(cpBands.getCPClass(ownerClassName));
411 classEnclosingMethodDesc.add(name == null ? null : cpBands.getCPNameAndType(name, signature));
412 }
413
414 public void addField(int flags, final String name, final String desc, final String signature, final Object value) {
415 flags &= 0xFFFF;
416 tempFieldDesc.add(cpBands.getCPNameAndType(name, desc));
417 if (signature != null) {
418 fieldSignature.add(cpBands.getCPSignature(signature));
419 flags |= 1 << 19;
420 }
421 if ((flags & Opcodes.ACC_DEPRECATED) != 0) {
422 flags &= ~Opcodes.ACC_DEPRECATED;
423 flags |= 1 << 20;
424 }
425 if (value != null) {
426 fieldConstantValueKQ.add(cpBands.getConstant(value));
427 flags |= 1 << 17;
428 }
429 if (!anySyntheticFields && (flags & 1 << 12) != 0 && segment.getCurrentClassReader().hasSyntheticAttributes()) {
430 cpBands.addCPUtf8("Synthetic");
431 anySyntheticFields = true;
432 }
433 tempFieldFlags.add(Long.valueOf(flags));
434 }
435
436
437
438
439
440
441 public void addFieldAttribute(final NewAttribute attribute) {
442 final String attributeName = attribute.type;
443 for (final NewAttributeBands bands : fieldAttributeBands) {
444 if (bands.getAttributeName().equals(attributeName)) {
445 bands.addAttribute(attribute);
446 final int flagIndex = bands.getFlagIndex();
447 final Long flags = tempFieldFlags.remove(tempFieldFlags.size() - 1);
448 tempFieldFlags.add(Long.valueOf(flags.longValue() | 1 << flagIndex));
449 return;
450 }
451 }
452 throw new IllegalArgumentException("No suitable definition for " + attributeName);
453 }
454
455 public void addHandler(final Label start, final Label end, final Label handler, final String type) {
456 final int handlers = codeHandlerCount.remove(codeHandlerCount.size() - 1);
457 codeHandlerCount.add(handlers + 1);
458 codeHandlerStartP.add(start);
459 codeHandlerEndPO.add(end);
460 codeHandlerCatchPO.add(handler);
461 codeHandlerClass.add(type == null ? null : cpBands.getCPClass(type));
462 }
463
464 public void addLineNumber(final int line, final Label start) {
465 final Long latestCodeFlag = codeFlags.get(codeFlags.size() - 1);
466 if ((latestCodeFlag.intValue() & 1 << 1) == 0) {
467 codeFlags.remove(codeFlags.size() - 1);
468 codeFlags.add(Long.valueOf(latestCodeFlag.intValue() | 1 << 1));
469 codeLineNumberTableN.add(1);
470 } else {
471 codeLineNumberTableN.increment(codeLineNumberTableN.size() - 1);
472 }
473 codeLineNumberTableLine.add(line);
474 codeLineNumberTableBciP.add(start);
475 }
476
477 public void addLocalVariable(final String name, final String desc, final String signature, final Label start, final Label end, final int indx) {
478 if (signature != null) {
479 final Long latestCodeFlag = codeFlags.get(codeFlags.size() - 1);
480 if ((latestCodeFlag.intValue() & 1 << 3) == 0) {
481 codeFlags.remove(codeFlags.size() - 1);
482 codeFlags.add(Long.valueOf(latestCodeFlag.intValue() | 1 << 3));
483 codeLocalVariableTypeTableN.add(1);
484 } else {
485 codeLocalVariableTypeTableN.increment(codeLocalVariableTypeTableN.size() - 1);
486 }
487 codeLocalVariableTypeTableBciP.add(start);
488 codeLocalVariableTypeTableSpanO.add(end);
489 codeLocalVariableTypeTableNameRU.add(cpBands.getCPUtf8(name));
490 codeLocalVariableTypeTableTypeRS.add(cpBands.getCPSignature(signature));
491 codeLocalVariableTypeTableSlot.add(indx);
492 }
493
494 codeLocalVariableTableN.increment(codeLocalVariableTableN.size() - 1);
495 codeLocalVariableTableBciP.add(start);
496 codeLocalVariableTableSpanO.add(end);
497 codeLocalVariableTableNameRU.add(cpBands.getCPUtf8(name));
498 codeLocalVariableTableTypeRS.add(cpBands.getCPSignature(desc));
499 codeLocalVariableTableSlot.add(indx);
500 }
501
502 public void addMaxStack(final int maxStack, int maxLocals) {
503 final Long latestFlag = tempMethodFlags.remove(tempMethodFlags.size() - 1);
504 final Long newFlag = Long.valueOf(latestFlag.intValue() | 1 << 17);
505 tempMethodFlags.add(newFlag);
506 codeMaxStack.add(maxStack);
507 if ((newFlag.longValue() & 1 << 3) == 0) {
508 maxLocals--;
509 }
510 maxLocals -= numMethodArgs;
511 codeMaxLocals.add(maxLocals);
512 }
513
514 public void addMethod(int flags, final String name, final String desc, final String signature, final String[] exceptions) {
515 final CPNameAndType nt = cpBands.getCPNameAndType(name, desc);
516 tempMethodDesc.add(nt);
517 if (signature != null) {
518 methodSignature.add(cpBands.getCPSignature(signature));
519 flags |= 1 << 19;
520 }
521 if (exceptions != null) {
522 methodExceptionNumber.add(exceptions.length);
523 for (final String exception : exceptions) {
524 methodExceptionClasses.add(cpBands.getCPClass(exception));
525 }
526 flags |= 1 << 18;
527 }
528 if ((flags & Opcodes.ACC_DEPRECATED) != 0) {
529 flags &= ~Opcodes.ACC_DEPRECATED;
530 flags |= 1 << 20;
531 }
532 tempMethodFlags.add(Long.valueOf(flags));
533 numMethodArgs = countArgs(desc);
534 if (!anySyntheticMethods && (flags & 1 << 12) != 0 && segment.getCurrentClassReader().hasSyntheticAttributes()) {
535 cpBands.addCPUtf8("Synthetic");
536 anySyntheticMethods = true;
537 }
538 }
539
540
541
542
543
544
545 public void addMethodAttribute(final NewAttribute attribute) {
546 final String attributeName = attribute.type;
547 for (final NewAttributeBands bands : methodAttributeBands) {
548 if (bands.getAttributeName().equals(attributeName)) {
549 bands.addAttribute(attribute);
550 final int flagIndex = bands.getFlagIndex();
551 final Long flags = tempMethodFlags.remove(tempMethodFlags.size() - 1);
552 tempMethodFlags.add(Long.valueOf(flags.longValue() | 1 << flagIndex));
553 return;
554 }
555 }
556 throw new IllegalArgumentException("No suitable definition for " + attributeName);
557 }
558
559 public void addParameterAnnotation(final int parameter, final String desc, final boolean visible, final List<String> nameRU, final List<String> tags,
560 final List<Object> values, final List<Integer> caseArrayN, final List<String> nestTypeRS, final List<String> nestNameRU,
561 final List<Integer> nestPairN) {
562 if (visible) {
563 if (tempMethodRVPA == null) {
564 tempMethodRVPA = new TempParamAnnotation(numMethodArgs);
565 tempMethodRVPA.addParameterAnnotation(parameter, desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
566 }
567 final Long flag = tempMethodFlags.remove(tempMethodFlags.size() - 1);
568 tempMethodFlags.add(Long.valueOf(flag.longValue() | 1 << 23));
569 } else {
570 if (tempMethodRIPA == null) {
571 tempMethodRIPA = new TempParamAnnotation(numMethodArgs);
572 tempMethodRIPA.addParameterAnnotation(parameter, desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
573 }
574 final Long flag = tempMethodFlags.remove(tempMethodFlags.size() - 1);
575 tempMethodFlags.add(Long.valueOf(flag.longValue() | 1 << 24));
576 }
577 }
578
579
580
581
582
583
584 public void addSourceFile(final String source) {
585 String implicitSourceFileName = class_this[index].toString();
586 if (implicitSourceFileName.indexOf('$') != -1) {
587 implicitSourceFileName = implicitSourceFileName.substring(0, implicitSourceFileName.indexOf('$'));
588 }
589 implicitSourceFileName = implicitSourceFileName.substring(implicitSourceFileName.lastIndexOf('/') + 1) + ".java";
590 if (source.equals(implicitSourceFileName)) {
591 classSourceFile.add(null);
592 } else {
593 classSourceFile.add(cpBands.getCPUtf8(source));
594 }
595 class_flags[index] |= 1 << 17;
596 }
597
598 private void createNewAttributeBands() throws IOException {
599 for (final AttributeDefinition def : attrBands.getClassAttributeLayouts()) {
600 classAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
601 }
602 for (final AttributeDefinition def : attrBands.getMethodAttributeLayouts()) {
603 methodAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
604 }
605 for (final AttributeDefinition def : attrBands.getFieldAttributeLayouts()) {
606 fieldAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
607 }
608 for (final AttributeDefinition def : attrBands.getCodeAttributeLayouts()) {
609 codeAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
610 }
611 }
612
613 public void currentClassReferencesInnerClass(final CPClass inner) {
614 if (!(index >= class_this.length)) {
615 final CPClass currentClass = class_this[index];
616 if (currentClass != null && !currentClass.equals(inner) && !isInnerClassOf(currentClass.toString(), inner)) {
617 classReferencesInnerClass.computeIfAbsent(currentClass, c -> new HashSet<>()).add(inner);
618 }
619 }
620 }
621
622 public void doBciRenumbering(final IntList bciRenumbering, final Map<Label, Integer> labelsToOffsets) {
623 renumberBci(codeLineNumberTableBciP, bciRenumbering, labelsToOffsets);
624 renumberBci(codeLocalVariableTableBciP, bciRenumbering, labelsToOffsets);
625 renumberOffsetBci(codeLocalVariableTableBciP, codeLocalVariableTableSpanO, bciRenumbering, labelsToOffsets);
626 renumberBci(codeLocalVariableTypeTableBciP, bciRenumbering, labelsToOffsets);
627 renumberOffsetBci(codeLocalVariableTypeTableBciP, codeLocalVariableTypeTableSpanO, bciRenumbering, labelsToOffsets);
628 renumberBci(codeHandlerStartP, bciRenumbering, labelsToOffsets);
629 renumberOffsetBci(codeHandlerStartP, codeHandlerEndPO, bciRenumbering, labelsToOffsets);
630 renumberDoubleOffsetBci(codeHandlerStartP, codeHandlerEndPO, codeHandlerCatchPO, bciRenumbering, labelsToOffsets);
631
632 for (final NewAttributeBands newAttributeBandSet : classAttributeBands) {
633 newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
634 }
635 for (final NewAttributeBands newAttributeBandSet : methodAttributeBands) {
636 newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
637 }
638 for (final NewAttributeBands newAttributeBandSet : fieldAttributeBands) {
639 newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
640 }
641 for (final NewAttributeBands newAttributeBandSet : codeAttributeBands) {
642 newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
643 }
644 }
645
646
647
648
649
650
651 public void endOfClass() {
652 final int numFields = tempFieldDesc.size();
653 class_field_count[index] = numFields;
654 field_descr[index] = new CPNameAndType[numFields];
655 field_flags[index] = new long[numFields];
656 for (int i = 0; i < numFields; i++) {
657 field_descr[index][i] = tempFieldDesc.get(i);
658 field_flags[index][i] = tempFieldFlags.get(i).longValue();
659 }
660 final int numMethods = tempMethodDesc.size();
661 class_method_count[index] = numMethods;
662 method_descr[index] = new CPNameAndType[numMethods];
663 method_flags[index] = new long[numMethods];
664 for (int i = 0; i < numMethods; i++) {
665 method_descr[index][i] = tempMethodDesc.get(i);
666 method_flags[index][i] = tempMethodFlags.get(i).longValue();
667 }
668 tempFieldDesc.clear();
669 tempFieldFlags.clear();
670 tempMethodDesc.clear();
671 tempMethodFlags.clear();
672 index++;
673 }
674
675
676
677
678
679
680 public void endOfMethod() {
681 if (tempMethodRVPA != null) {
682 method_RVPA_bands.addParameterAnnotation(tempMethodRVPA.numParams, tempMethodRVPA.annoN, tempMethodRVPA.pairN, tempMethodRVPA.typeRS,
683 tempMethodRVPA.nameRU, tempMethodRVPA.tags, tempMethodRVPA.values, tempMethodRVPA.caseArrayN, tempMethodRVPA.nestTypeRS,
684 tempMethodRVPA.nestNameRU, tempMethodRVPA.nestPairN);
685 tempMethodRVPA = null;
686 }
687 if (tempMethodRIPA != null) {
688 method_RIPA_bands.addParameterAnnotation(tempMethodRIPA.numParams, tempMethodRIPA.annoN, tempMethodRIPA.pairN, tempMethodRIPA.typeRS,
689 tempMethodRIPA.nameRU, tempMethodRIPA.tags, tempMethodRIPA.values, tempMethodRIPA.caseArrayN, tempMethodRIPA.nestTypeRS,
690 tempMethodRIPA.nestNameRU, tempMethodRIPA.nestPairN);
691 tempMethodRIPA = null;
692 }
693 if (codeFlags.size() > 0) {
694 final long latestCodeFlag = codeFlags.get(codeFlags.size() - 1).longValue();
695 final int latestLocalVariableTableN = codeLocalVariableTableN.get(codeLocalVariableTableN.size() - 1);
696 if (latestCodeFlag == 1 << 2 && latestLocalVariableTableN == 0) {
697 codeLocalVariableTableN.remove(codeLocalVariableTableN.size() - 1);
698 codeFlags.remove(codeFlags.size() - 1);
699 codeFlags.add(Long.valueOf(0));
700 }
701 }
702 }
703
704
705
706
707
708 public void finaliseBands() {
709 final int defaultMajorVersion = segmentHeader.getDefaultMajorVersion();
710 for (int i = 0; i < class_flags.length; i++) {
711 final int major = major_versions[i];
712 if (major != defaultMajorVersion) {
713 class_flags[i] |= 1 << 24;
714 classFileVersionMajor.add(major);
715 classFileVersionMinor.add(0);
716 }
717 }
718
719 codeHeaders = new int[codeHandlerCount.size()];
720 int removed = 0;
721 for (int i = 0; i < codeHeaders.length; i++) {
722 final int numHandlers = codeHandlerCount.get(i - removed);
723 final int maxLocals = codeMaxLocals.get(i - removed);
724 final int maxStack = codeMaxStack.get(i - removed);
725 switch (numHandlers) {
726 case 0: {
727 final int header = maxLocals * 12 + maxStack + 1;
728 if (header < 145 && maxStack < 12) {
729 codeHeaders[i] = header;
730 }
731 break;
732 }
733 case 1: {
734 final int header = maxLocals * 8 + maxStack + 145;
735 if (header < 209 && maxStack < 8) {
736 codeHeaders[i] = header;
737 }
738 break;
739 }
740 case 2: {
741 final int header = maxLocals * 7 + maxStack + 209;
742 if (header < 256 && maxStack < 7) {
743 codeHeaders[i] = header;
744 }
745 break;
746 }
747 default:
748 break;
749 }
750 if (codeHeaders[i] != 0) {
751
752
753 codeHandlerCount.remove(i - removed);
754 codeMaxLocals.remove(i - removed);
755 codeMaxStack.remove(i - removed);
756 removed++;
757 } else if (!segment.getSegmentHeader().have_all_code_flags()) {
758 codeFlags.add(Long.valueOf(0));
759 }
760 }
761
762
763 final IntList innerClassesN = new IntList();
764 final List<IcTuple> icLocal = new ArrayList<>();
765 for (int i = 0; i < class_this.length; i++) {
766 final CPClass cpClass = class_this[i];
767 final Set<CPClass> referencedInnerClasses = classReferencesInnerClass.get(cpClass);
768 if (referencedInnerClasses != null) {
769 int innerN = 0;
770 final List<IcTuple> innerClasses = segment.getIcBands().getInnerClassesForOuter(cpClass.toString());
771 if (innerClasses != null) {
772 for (final IcTuple element : innerClasses) {
773 referencedInnerClasses.remove(element.C);
774 }
775 }
776 for (final CPClass inner : referencedInnerClasses) {
777 final IcTuple icTuple = segment.getIcBands().getIcTuple(inner);
778 if (icTuple != null && !icTuple.isAnonymous()) {
779
780 icLocal.add(icTuple);
781 innerN++;
782 }
783 }
784 if (innerN != 0) {
785 innerClassesN.add(innerN);
786 class_flags[i] |= 1 << 23;
787 }
788 }
789 }
790 class_InnerClasses_N = innerClassesN.toArray();
791 class_InnerClasses_RC = new CPClass[icLocal.size()];
792 class_InnerClasses_F = new int[icLocal.size()];
793 classInnerClassesOuterRCN = new ArrayList<>();
794 classInnerClassesNameRUN = new ArrayList<>();
795 for (int i = 0; i < class_InnerClasses_RC.length; i++) {
796 final IcTuple icTuple = icLocal.get(i);
797 class_InnerClasses_RC[i] = icTuple.C;
798 if (icTuple.C2 == null && icTuple.N == null) {
799 class_InnerClasses_F[i] = 0;
800 } else {
801 if (icTuple.F == 0) {
802 class_InnerClasses_F[i] = 0x00010000;
803 } else {
804 class_InnerClasses_F[i] = icTuple.F;
805 }
806 classInnerClassesOuterRCN.add(icTuple.C2);
807 classInnerClassesNameRUN.add(icTuple.N);
808 }
809 }
810
811 final IntList classAttrCalls = new IntList();
812 final IntList fieldAttrCalls = new IntList();
813 final IntList methodAttrCalls = new IntList();
814 final IntList codeAttrCalls = new IntList();
815
816 if (class_RVA_bands.hasContent()) {
817 classAttrCalls.add(class_RVA_bands.numBackwardsCalls());
818 }
819 if (class_RIA_bands.hasContent()) {
820 classAttrCalls.add(class_RIA_bands.numBackwardsCalls());
821 }
822 if (field_RVA_bands.hasContent()) {
823 fieldAttrCalls.add(field_RVA_bands.numBackwardsCalls());
824 }
825 if (field_RIA_bands.hasContent()) {
826 fieldAttrCalls.add(field_RIA_bands.numBackwardsCalls());
827 }
828 if (method_RVA_bands.hasContent()) {
829 methodAttrCalls.add(method_RVA_bands.numBackwardsCalls());
830 }
831 if (method_RIA_bands.hasContent()) {
832 methodAttrCalls.add(method_RIA_bands.numBackwardsCalls());
833 }
834 if (method_RVPA_bands.hasContent()) {
835 methodAttrCalls.add(method_RVPA_bands.numBackwardsCalls());
836 }
837 if (method_RIPA_bands.hasContent()) {
838 methodAttrCalls.add(method_RIPA_bands.numBackwardsCalls());
839 }
840 if (method_AD_bands.hasContent()) {
841 methodAttrCalls.add(method_AD_bands.numBackwardsCalls());
842 }
843
844
845 final Comparator<NewAttributeBands> comparator = (arg0, arg1) -> arg0.getFlagIndex() - arg1.getFlagIndex();
846 classAttributeBands.sort(comparator);
847 methodAttributeBands.sort(comparator);
848 fieldAttributeBands.sort(comparator);
849 codeAttributeBands.sort(comparator);
850
851 for (final NewAttributeBands bands : classAttributeBands) {
852 if (bands.isUsedAtLeastOnce()) {
853 for (final int backwardsCallCount : bands.numBackwardsCalls()) {
854 classAttrCalls.add(backwardsCallCount);
855 }
856 }
857 }
858 for (final NewAttributeBands bands : methodAttributeBands) {
859 if (bands.isUsedAtLeastOnce()) {
860 for (final int backwardsCallCount : bands.numBackwardsCalls()) {
861 methodAttrCalls.add(backwardsCallCount);
862 }
863 }
864 }
865 for (final NewAttributeBands bands : fieldAttributeBands) {
866 if (bands.isUsedAtLeastOnce()) {
867 for (final int backwardsCallCount : bands.numBackwardsCalls()) {
868 fieldAttrCalls.add(backwardsCallCount);
869 }
870 }
871 }
872 for (final NewAttributeBands bands : codeAttributeBands) {
873 if (bands.isUsedAtLeastOnce()) {
874 for (final int backwardsCallCount : bands.numBackwardsCalls()) {
875 codeAttrCalls.add(backwardsCallCount);
876 }
877 }
878 }
879
880 class_attr_calls = classAttrCalls.toArray();
881 field_attr_calls = fieldAttrCalls.toArray();
882 method_attr_calls = methodAttrCalls.toArray();
883 code_attr_calls = codeAttrCalls.toArray();
884 }
885
886 private int[] getInts(final CPClass[] cpClasses) {
887 final int[] ints = new int[cpClasses.length];
888 for (int i = 0; i < ints.length; i++) {
889 if (cpClasses[i] != null) {
890 ints[i] = cpClasses[i].getIndex();
891 }
892 }
893 return ints;
894 }
895
896
897
898
899
900
901 public boolean isAnySyntheticClasses() {
902 return anySyntheticClasses;
903 }
904
905
906
907
908
909
910 public boolean isAnySyntheticFields() {
911 return anySyntheticFields;
912 }
913
914
915
916
917
918
919 public boolean isAnySyntheticMethods() {
920 return anySyntheticMethods;
921 }
922
923 private boolean isInnerClass(final String possibleInner) {
924 return possibleInner.indexOf('$') != -1;
925 }
926
927 private boolean isInnerClassOf(final String possibleInner, final CPClass possibleOuter) {
928 if (isInnerClass(possibleInner)) {
929 final String superClassName = possibleInner.substring(0, possibleInner.lastIndexOf('$'));
930 if (superClassName.equals(possibleOuter.toString())) {
931 return true;
932 }
933 return isInnerClassOf(superClassName, possibleOuter);
934 }
935 return false;
936 }
937
938
939
940
941
942
943 public int numClassesProcessed() {
944 return index;
945 }
946
947 @Override
948 public void pack(final OutputStream out) throws IOException, Pack200Exception {
949 PackingUtils.log("Writing class bands...");
950
951 byte[] encodedBand = encodeBandInt("class_this", getInts(class_this), Codec.DELTA5);
952 out.write(encodedBand);
953 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_this[" + class_this.length + "]");
954
955 encodedBand = encodeBandInt("class_super", getInts(class_super), Codec.DELTA5);
956 out.write(encodedBand);
957 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_super[" + class_super.length + "]");
958
959 encodedBand = encodeBandInt("class_interface_count", class_interface_count, Codec.DELTA5);
960 out.write(encodedBand);
961 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_interface_count[" + class_interface_count.length + "]");
962
963 final int totalInterfaces = sum(class_interface_count);
964 final int[] classInterface = new int[totalInterfaces];
965 int k = 0;
966 for (final CPClass[] element : class_interface) {
967 if (element != null) {
968 for (final CPClass cpClass : element) {
969 classInterface[k] = cpClass.getIndex();
970 k++;
971 }
972 }
973 }
974
975 encodedBand = encodeBandInt("class_interface", classInterface, Codec.DELTA5);
976 out.write(encodedBand);
977 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_interface[" + classInterface.length + "]");
978
979 encodedBand = encodeBandInt("class_field_count", class_field_count, Codec.DELTA5);
980 out.write(encodedBand);
981 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_field_count[" + class_field_count.length + "]");
982
983 encodedBand = encodeBandInt("class_method_count", class_method_count, Codec.DELTA5);
984 out.write(encodedBand);
985 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_method_count[" + class_method_count.length + "]");
986
987 final int totalFields = sum(class_field_count);
988 final int[] fieldDescr = new int[totalFields];
989 k = 0;
990 for (int i = 0; i < index; i++) {
991 for (int j = 0; j < field_descr[i].length; j++) {
992 final CPNameAndType descr = field_descr[i][j];
993 fieldDescr[k] = descr.getIndex();
994 k++;
995 }
996 }
997
998 encodedBand = encodeBandInt("field_descr", fieldDescr, Codec.DELTA5);
999 out.write(encodedBand);
1000 PackingUtils.log("Wrote " + encodedBand.length + " bytes from field_descr[" + fieldDescr.length + "]");
1001
1002 writeFieldAttributeBands(out);
1003
1004 final int totalMethods = sum(class_method_count);
1005 final int[] methodDescr = new int[totalMethods];
1006 k = 0;
1007 for (int i = 0; i < index; i++) {
1008 for (int j = 0; j < method_descr[i].length; j++) {
1009 final CPNameAndType descr = method_descr[i][j];
1010 methodDescr[k] = descr.getIndex();
1011 k++;
1012 }
1013 }
1014
1015 encodedBand = encodeBandInt("method_descr", methodDescr, Codec.MDELTA5);
1016 out.write(encodedBand);
1017 PackingUtils.log("Wrote " + encodedBand.length + " bytes from method_descr[" + methodDescr.length + "]");
1018
1019 writeMethodAttributeBands(out);
1020 writeClassAttributeBands(out);
1021 writeCodeBands(out);
1022 }
1023
1024
1025
1026
1027 public void removeCurrentClass() {
1028
1029
1030 if ((class_flags[index] & 1 << 17) != 0) {
1031 classSourceFile.remove(classSourceFile.size() - 1);
1032 }
1033 if ((class_flags[index] & 1 << 18) != 0) {
1034 classEnclosingMethodClass.remove(classEnclosingMethodClass.size() - 1);
1035 classEnclosingMethodDesc.remove(classEnclosingMethodDesc.size() - 1);
1036 }
1037 if ((class_flags[index] & 1 << 19) != 0) {
1038 classSignature.remove(classSignature.size() - 1);
1039 }
1040 if ((class_flags[index] & 1 << 21) != 0) {
1041 class_RVA_bands.removeLatest();
1042 }
1043 if ((class_flags[index] & 1 << 22) != 0) {
1044 class_RIA_bands.removeLatest();
1045 }
1046 for (final Long flagsL : tempFieldFlags) {
1047 final long flags = flagsL.longValue();
1048 if ((flags & 1 << 19) != 0) {
1049 fieldSignature.remove(fieldSignature.size() - 1);
1050 }
1051 if ((flags & 1 << 17) != 0) {
1052 fieldConstantValueKQ.remove(fieldConstantValueKQ.size() - 1);
1053 }
1054 if ((flags & 1 << 21) != 0) {
1055 field_RVA_bands.removeLatest();
1056 }
1057 if ((flags & 1 << 22) != 0) {
1058 field_RIA_bands.removeLatest();
1059 }
1060 }
1061 for (final Long flagsL : tempMethodFlags) {
1062 final long flags = flagsL.longValue();
1063 if ((flags & 1 << 19) != 0) {
1064 methodSignature.remove(methodSignature.size() - 1);
1065 }
1066 if ((flags & 1 << 18) != 0) {
1067 final int exceptions = methodExceptionNumber.remove(methodExceptionNumber.size() - 1);
1068 for (int i = 0; i < exceptions; i++) {
1069 methodExceptionClasses.remove(methodExceptionClasses.size() - 1);
1070 }
1071 }
1072 if ((flags & 1 << 17) != 0) {
1073 codeMaxLocals.remove(codeMaxLocals.size() - 1);
1074 codeMaxStack.remove(codeMaxStack.size() - 1);
1075 final int handlers = codeHandlerCount.remove(codeHandlerCount.size() - 1);
1076 for (int i = 0; i < handlers; i++) {
1077 final int index = codeHandlerStartP.size() - 1;
1078 codeHandlerStartP.remove(index);
1079 codeHandlerEndPO.remove(index);
1080 codeHandlerCatchPO.remove(index);
1081 codeHandlerClass.remove(index);
1082 }
1083 if (!stripDebug) {
1084 final long cdeFlags = codeFlags.remove(codeFlags.size() - 1).longValue();
1085 final int numLocalVariables = codeLocalVariableTableN.remove(codeLocalVariableTableN.size() - 1);
1086 for (int i = 0; i < numLocalVariables; i++) {
1087 final int location = codeLocalVariableTableBciP.size() - 1;
1088 codeLocalVariableTableBciP.remove(location);
1089 codeLocalVariableTableSpanO.remove(location);
1090 codeLocalVariableTableNameRU.remove(location);
1091 codeLocalVariableTableTypeRS.remove(location);
1092 codeLocalVariableTableSlot.remove(location);
1093 }
1094 if ((cdeFlags & 1 << 3) != 0) {
1095 final int numLocalVariablesInTypeTable = codeLocalVariableTypeTableN.remove(codeLocalVariableTypeTableN.size() - 1);
1096 for (int i = 0; i < numLocalVariablesInTypeTable; i++) {
1097 final int location = codeLocalVariableTypeTableBciP.size() - 1;
1098 codeLocalVariableTypeTableBciP.remove(location);
1099 codeLocalVariableTypeTableSpanO.remove(location);
1100 codeLocalVariableTypeTableNameRU.remove(location);
1101 codeLocalVariableTypeTableTypeRS.remove(location);
1102 codeLocalVariableTypeTableSlot.remove(location);
1103 }
1104 }
1105 if ((cdeFlags & 1 << 1) != 0) {
1106 final int numLineNumbers = codeLineNumberTableN.remove(codeLineNumberTableN.size() - 1);
1107 for (int i = 0; i < numLineNumbers; i++) {
1108 final int location = codeLineNumberTableBciP.size() - 1;
1109 codeLineNumberTableBciP.remove(location);
1110 codeLineNumberTableLine.remove(location);
1111 }
1112 }
1113 }
1114 }
1115 if ((flags & 1 << 21) != 0) {
1116 method_RVA_bands.removeLatest();
1117 }
1118 if ((flags & 1 << 22) != 0) {
1119 method_RIA_bands.removeLatest();
1120 }
1121 if ((flags & 1 << 23) != 0) {
1122 method_RVPA_bands.removeLatest();
1123 }
1124 if ((flags & 1 << 24) != 0) {
1125 method_RIPA_bands.removeLatest();
1126 }
1127 if ((flags & 1 << 25) != 0) {
1128 method_AD_bands.removeLatest();
1129 }
1130 }
1131 class_this[index] = null;
1132 class_super[index] = null;
1133 class_interface_count[index] = 0;
1134 class_interface[index] = null;
1135 major_versions[index] = 0;
1136 class_flags[index] = 0;
1137 tempFieldDesc.clear();
1138 tempFieldFlags.clear();
1139 tempMethodDesc.clear();
1140 tempMethodFlags.clear();
1141 if (index > 0) {
1142 index--;
1143 }
1144 }
1145
1146 private void renumberBci(final List<Integer> list, final IntList bciRenumbering, final Map<Label, Integer> labelsToOffsets) {
1147 for (int i = list.size() - 1; i >= 0; i--) {
1148 final Object label = list.get(i);
1149 if (label instanceof Integer) {
1150 break;
1151 }
1152 if (label instanceof Label) {
1153 list.remove(i);
1154 final Integer bytecodeIndex = labelsToOffsets.get(label);
1155 list.add(i, Integer.valueOf(bciRenumbering.get(bytecodeIndex.intValue())));
1156 }
1157 }
1158 }
1159
1160 private void renumberDoubleOffsetBci(final List<Integer> relative, final List<Integer> firstOffset, final List<Object> list, final IntList bciRenumbering,
1161 final Map<Label, Integer> labelsToOffsets) {
1162
1163 for (int i = list.size() - 1; i >= 0; i--) {
1164 final Object label = list.get(i);
1165 if (label instanceof Integer) {
1166 break;
1167 }
1168 if (label instanceof Label) {
1169 list.remove(i);
1170 final Integer bytecodeIndex = labelsToOffsets.get(label);
1171 final Integer renumberedOffset = Integer
1172 .valueOf(bciRenumbering.get(bytecodeIndex.intValue()) - relative.get(i).intValue() - firstOffset.get(i).intValue());
1173 list.add(i, renumberedOffset);
1174 }
1175 }
1176 }
1177
1178 private void renumberOffsetBci(final List<Integer> relative, final List<Integer> list, final IntList bciRenumbering,
1179 final Map<Label, Integer> labelsToOffsets) {
1180 for (int i = list.size() - 1; i >= 0; i--) {
1181 final Object label = list.get(i);
1182 if (label instanceof Integer) {
1183 break;
1184 }
1185 if (label instanceof Label) {
1186 list.remove(i);
1187 final Integer bytecodeIndex = labelsToOffsets.get(label);
1188 final Integer renumberedOffset = Integer.valueOf(bciRenumbering.get(bytecodeIndex.intValue()) - relative.get(i).intValue());
1189 list.add(i, renumberedOffset);
1190 }
1191 }
1192 }
1193
1194 private int sum(final int[] ints) {
1195 int sum = 0;
1196 for (final int j : ints) {
1197 sum += j;
1198 }
1199 return sum;
1200 }
1201
1202 private void writeClassAttributeBands(final OutputStream out) throws IOException, Pack200Exception {
1203 byte[] encodedBand = encodeFlags("class_flags", class_flags, Codec.UNSIGNED5, Codec.UNSIGNED5, segmentHeader.have_class_flags_hi());
1204 out.write(encodedBand);
1205 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_flags[" + class_flags.length + "]");
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215 encodedBand = encodeBandInt("class_attr_calls", class_attr_calls, Codec.UNSIGNED5);
1216 out.write(encodedBand);
1217 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_attr_calls[" + class_attr_calls.length + "]");
1218
1219 encodedBand = encodeBandInt("classSourceFile", cpEntryOrNullListToArray(classSourceFile), Codec.UNSIGNED5);
1220 out.write(encodedBand);
1221 PackingUtils.log("Wrote " + encodedBand.length + " bytes from classSourceFile[" + classSourceFile.size() + "]");
1222
1223 encodedBand = encodeBandInt("class_enclosing_method_RC", cpEntryListToArray(classEnclosingMethodClass), Codec.UNSIGNED5);
1224 out.write(encodedBand);
1225 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_enclosing_method_RC[" + classEnclosingMethodClass.size() + "]");
1226
1227 encodedBand = encodeBandInt("class_EnclosingMethod_RDN", cpEntryOrNullListToArray(classEnclosingMethodDesc), Codec.UNSIGNED5);
1228 out.write(encodedBand);
1229 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_EnclosingMethod_RDN[" + classEnclosingMethodDesc.size() + "]");
1230
1231 encodedBand = encodeBandInt("class_Signature_RS", cpEntryListToArray(classSignature), Codec.UNSIGNED5);
1232 out.write(encodedBand);
1233 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_Signature_RS[" + classSignature.size() + "]");
1234
1235 class_RVA_bands.pack(out);
1236 class_RIA_bands.pack(out);
1237
1238 encodedBand = encodeBandInt("class_InnerClasses_N", class_InnerClasses_N, Codec.UNSIGNED5);
1239 out.write(encodedBand);
1240 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_InnerClasses_N[" + class_InnerClasses_N.length + "]");
1241
1242 encodedBand = encodeBandInt("class_InnerClasses_RC", getInts(class_InnerClasses_RC), Codec.UNSIGNED5);
1243 out.write(encodedBand);
1244 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_InnerClasses_RC[" + class_InnerClasses_RC.length + "]");
1245
1246 encodedBand = encodeBandInt("class_InnerClasses_F", class_InnerClasses_F, Codec.UNSIGNED5);
1247 out.write(encodedBand);
1248 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_InnerClasses_F[" + class_InnerClasses_F.length + "]");
1249
1250 encodedBand = encodeBandInt("class_InnerClasses_outer_RCN", cpEntryOrNullListToArray(classInnerClassesOuterRCN), Codec.UNSIGNED5);
1251 out.write(encodedBand);
1252 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_InnerClasses_outer_RCN[" + classInnerClassesOuterRCN.size() + "]");
1253
1254 encodedBand = encodeBandInt("class_InnerClasses_name_RUN", cpEntryOrNullListToArray(classInnerClassesNameRUN), Codec.UNSIGNED5);
1255 out.write(encodedBand);
1256 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_InnerClasses_name_RUN[" + classInnerClassesNameRUN.size() + "]");
1257
1258 encodedBand = encodeBandInt("classFileVersionMinor", classFileVersionMinor.toArray(), Codec.UNSIGNED5);
1259 out.write(encodedBand);
1260 PackingUtils.log("Wrote " + encodedBand.length + " bytes from classFileVersionMinor[" + classFileVersionMinor.size() + "]");
1261
1262 encodedBand = encodeBandInt("classFileVersionMajor", classFileVersionMajor.toArray(), Codec.UNSIGNED5);
1263 out.write(encodedBand);
1264 PackingUtils.log("Wrote " + encodedBand.length + " bytes from classFileVersionMajor[" + classFileVersionMajor.size() + "]");
1265
1266 for (final NewAttributeBands classAttributeBand : classAttributeBands) {
1267 classAttributeBand.pack(out);
1268 }
1269 }
1270
1271 private void writeCodeAttributeBands(final OutputStream out) throws IOException, Pack200Exception {
1272 byte[] encodedBand = encodeFlags("codeFlags", longListToArray(codeFlags), Codec.UNSIGNED5, Codec.UNSIGNED5, segmentHeader.have_code_flags_hi());
1273 out.write(encodedBand);
1274 PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeFlags[" + codeFlags.size() + "]");
1275
1276
1277
1278 encodedBand = encodeBandInt("code_attr_calls", code_attr_calls, Codec.UNSIGNED5);
1279 out.write(encodedBand);
1280 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_attr_calls[" + code_attr_calls.length + "]");
1281
1282 encodedBand = encodeBandInt("code_LineNumberTable_N", codeLineNumberTableN.toArray(), Codec.UNSIGNED5);
1283 out.write(encodedBand);
1284 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LineNumberTable_N[" + codeLineNumberTableN.size() + "]");
1285
1286 encodedBand = encodeBandInt("code_LineNumberTable_bci_P", integerListToArray(codeLineNumberTableBciP), Codec.BCI5);
1287 out.write(encodedBand);
1288 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LineNumberTable_bci_P[" + codeLineNumberTableBciP.size() + "]");
1289
1290 encodedBand = encodeBandInt("code_LineNumberTable_line", codeLineNumberTableLine.toArray(), Codec.UNSIGNED5);
1291 out.write(encodedBand);
1292 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LineNumberTable_line[" + codeLineNumberTableLine.size() + "]");
1293
1294 encodedBand = encodeBandInt("code_LocalVariableTable_N", codeLocalVariableTableN.toArray(), Codec.UNSIGNED5);
1295 out.write(encodedBand);
1296 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_N[" + codeLocalVariableTableN.size() + "]");
1297
1298 encodedBand = encodeBandInt("code_LocalVariableTable_bci_P", integerListToArray(codeLocalVariableTableBciP), Codec.BCI5);
1299 out.write(encodedBand);
1300 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_bci_P[" + codeLocalVariableTableBciP.size() + "]");
1301
1302 encodedBand = encodeBandInt("code_LocalVariableTable_span_O", integerListToArray(codeLocalVariableTableSpanO), Codec.BRANCH5);
1303 out.write(encodedBand);
1304 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_span_O[" + codeLocalVariableTableSpanO.size() + "]");
1305
1306 encodedBand = encodeBandInt("code_LocalVariableTable_name_RU", cpEntryListToArray(codeLocalVariableTableNameRU), Codec.UNSIGNED5);
1307 out.write(encodedBand);
1308 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_name_RU[" + codeLocalVariableTableNameRU.size() + "]");
1309
1310 encodedBand = encodeBandInt("code_LocalVariableTable_type_RS", cpEntryListToArray(codeLocalVariableTableTypeRS), Codec.UNSIGNED5);
1311 out.write(encodedBand);
1312 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_type_RS[" + codeLocalVariableTableTypeRS.size() + "]");
1313
1314 encodedBand = encodeBandInt("code_LocalVariableTable_slot", codeLocalVariableTableSlot.toArray(), Codec.UNSIGNED5);
1315 out.write(encodedBand);
1316 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_slot[" + codeLocalVariableTableSlot.size() + "]");
1317
1318 encodedBand = encodeBandInt("code_LocalVariableTypeTable_N", codeLocalVariableTypeTableN.toArray(), Codec.UNSIGNED5);
1319 out.write(encodedBand);
1320 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_N[" + codeLocalVariableTypeTableN.size() + "]");
1321
1322 encodedBand = encodeBandInt("code_LocalVariableTypeTable_bci_P", integerListToArray(codeLocalVariableTypeTableBciP), Codec.BCI5);
1323 out.write(encodedBand);
1324 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_bci_P[" + codeLocalVariableTypeTableBciP.size() + "]");
1325
1326 encodedBand = encodeBandInt("code_LocalVariableTypeTable_span_O", integerListToArray(codeLocalVariableTypeTableSpanO), Codec.BRANCH5);
1327 out.write(encodedBand);
1328 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_span_O[" + codeLocalVariableTypeTableSpanO.size() + "]");
1329
1330 encodedBand = encodeBandInt("code_LocalVariableTypeTable_name_RU", cpEntryListToArray(codeLocalVariableTypeTableNameRU), Codec.UNSIGNED5);
1331 out.write(encodedBand);
1332 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_name_RU[" + codeLocalVariableTypeTableNameRU.size() + "]");
1333
1334 encodedBand = encodeBandInt("code_LocalVariableTypeTable_type_RS", cpEntryListToArray(codeLocalVariableTypeTableTypeRS), Codec.UNSIGNED5);
1335 out.write(encodedBand);
1336 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_type_RS[" + codeLocalVariableTypeTableTypeRS.size() + "]");
1337
1338 encodedBand = encodeBandInt("code_LocalVariableTypeTable_slot", codeLocalVariableTypeTableSlot.toArray(), Codec.UNSIGNED5);
1339 out.write(encodedBand);
1340 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_slot[" + codeLocalVariableTypeTableSlot.size() + "]");
1341
1342 for (final NewAttributeBands bands : codeAttributeBands) {
1343 bands.pack(out);
1344 }
1345 }
1346
1347 private void writeCodeBands(final OutputStream out) throws IOException, Pack200Exception {
1348 byte[] encodedBand = encodeBandInt("codeHeaders", codeHeaders, Codec.BYTE1);
1349 out.write(encodedBand);
1350 PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeHeaders[" + codeHeaders.length + "]");
1351
1352 encodedBand = encodeBandInt("codeMaxStack", codeMaxStack.toArray(), Codec.UNSIGNED5);
1353 out.write(encodedBand);
1354 PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeMaxStack[" + codeMaxStack.size() + "]");
1355
1356 encodedBand = encodeBandInt("codeMaxLocals", codeMaxLocals.toArray(), Codec.UNSIGNED5);
1357 out.write(encodedBand);
1358 PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeMaxLocals[" + codeMaxLocals.size() + "]");
1359
1360 encodedBand = encodeBandInt("codeHandlerCount", codeHandlerCount.toArray(), Codec.UNSIGNED5);
1361 out.write(encodedBand);
1362 PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeHandlerCount[" + codeHandlerCount.size() + "]");
1363
1364 encodedBand = encodeBandInt("codeHandlerStartP", integerListToArray(codeHandlerStartP), Codec.BCI5);
1365 out.write(encodedBand);
1366 PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeHandlerStartP[" + codeHandlerStartP.size() + "]");
1367
1368 encodedBand = encodeBandInt("codeHandlerEndPO", integerListToArray(codeHandlerEndPO), Codec.BRANCH5);
1369 out.write(encodedBand);
1370 PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeHandlerEndPO[" + codeHandlerEndPO.size() + "]");
1371
1372 encodedBand = encodeBandInt("codeHandlerCatchPO", integerListToArray(codeHandlerCatchPO), Codec.BRANCH5);
1373 out.write(encodedBand);
1374 PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeHandlerCatchPO[" + codeHandlerCatchPO.size() + "]");
1375
1376 encodedBand = encodeBandInt("codeHandlerClass", cpEntryOrNullListToArray(codeHandlerClass), Codec.UNSIGNED5);
1377 out.write(encodedBand);
1378 PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeHandlerClass[" + codeHandlerClass.size() + "]");
1379
1380 writeCodeAttributeBands(out);
1381 }
1382
1383 private void writeFieldAttributeBands(final OutputStream out) throws IOException, Pack200Exception {
1384 byte[] encodedBand = encodeFlags("field_flags", field_flags, Codec.UNSIGNED5, Codec.UNSIGNED5, segmentHeader.have_field_flags_hi());
1385 out.write(encodedBand);
1386 PackingUtils.log("Wrote " + encodedBand.length + " bytes from field_flags[" + field_flags.length + "]");
1387
1388
1389
1390 encodedBand = encodeBandInt("field_attr_calls", field_attr_calls, Codec.UNSIGNED5);
1391 out.write(encodedBand);
1392 PackingUtils.log("Wrote " + encodedBand.length + " bytes from field_attr_calls[" + field_attr_calls.length + "]");
1393
1394 encodedBand = encodeBandInt("fieldConstantValueKQ", cpEntryListToArray(fieldConstantValueKQ), Codec.UNSIGNED5);
1395 out.write(encodedBand);
1396 PackingUtils.log("Wrote " + encodedBand.length + " bytes from fieldConstantValueKQ[" + fieldConstantValueKQ.size() + "]");
1397
1398 encodedBand = encodeBandInt("fieldSignature", cpEntryListToArray(fieldSignature), Codec.UNSIGNED5);
1399 out.write(encodedBand);
1400 PackingUtils.log("Wrote " + encodedBand.length + " bytes from fieldSignature[" + fieldSignature.size() + "]");
1401
1402 field_RVA_bands.pack(out);
1403 field_RIA_bands.pack(out);
1404 for (final NewAttributeBands bands : fieldAttributeBands) {
1405 bands.pack(out);
1406 }
1407 }
1408
1409 private void writeMethodAttributeBands(final OutputStream out) throws IOException, Pack200Exception {
1410 byte[] encodedBand = encodeFlags("method_flags", method_flags, Codec.UNSIGNED5, Codec.UNSIGNED5, segmentHeader.have_method_flags_hi());
1411 out.write(encodedBand);
1412 PackingUtils.log("Wrote " + encodedBand.length + " bytes from method_flags[" + method_flags.length + "]");
1413
1414
1415
1416 encodedBand = encodeBandInt("method_attr_calls", method_attr_calls, Codec.UNSIGNED5);
1417 out.write(encodedBand);
1418 PackingUtils.log("Wrote " + encodedBand.length + " bytes from method_attr_calls[" + method_attr_calls.length + "]");
1419
1420 encodedBand = encodeBandInt("methodExceptionNumber", methodExceptionNumber.toArray(), Codec.UNSIGNED5);
1421 out.write(encodedBand);
1422 PackingUtils.log("Wrote " + encodedBand.length + " bytes from methodExceptionNumber[" + methodExceptionNumber.size() + "]");
1423
1424 encodedBand = encodeBandInt("methodExceptionClasses", cpEntryListToArray(methodExceptionClasses), Codec.UNSIGNED5);
1425 out.write(encodedBand);
1426 PackingUtils.log("Wrote " + encodedBand.length + " bytes from methodExceptionClasses[" + methodExceptionClasses.size() + "]");
1427
1428 encodedBand = encodeBandInt("methodSignature", cpEntryListToArray(methodSignature), Codec.UNSIGNED5);
1429 out.write(encodedBand);
1430 PackingUtils.log("Wrote " + encodedBand.length + " bytes from methodSignature[" + methodSignature.size() + "]");
1431
1432 method_RVA_bands.pack(out);
1433 method_RIA_bands.pack(out);
1434 method_RVPA_bands.pack(out);
1435 method_RIPA_bands.pack(out);
1436 method_AD_bands.pack(out);
1437 for (final NewAttributeBands bands : methodAttributeBands) {
1438 bands.pack(out);
1439 }
1440 }
1441 }