You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1616 lines
72 KiB
1616 lines
72 KiB
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
* (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package org.apache.harmony.pack200;
|
|
|
|
import java.io.IOException;
|
|
import java.io.OutputStream;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.Comparator;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import org.apache.harmony.pack200.AttributeDefinitionBands.AttributeDefinition;
|
|
import org.apache.harmony.pack200.IcBands.IcTuple;
|
|
import org.objectweb.asm.Label;
|
|
import org.objectweb.asm.Opcodes;
|
|
|
|
/**
|
|
* Class bands (corresponds to the <code>class_bands</code> set of bands in the
|
|
* pack200 specification)
|
|
*/
|
|
public class ClassBands extends BandSet {
|
|
|
|
private final CpBands cpBands;
|
|
private final AttributeDefinitionBands attrBands;
|
|
|
|
private final CPClass[] class_this;
|
|
private final CPClass[] class_super;
|
|
private final CPClass[][] class_interface;
|
|
private final int[] class_interface_count;
|
|
|
|
private final int[] major_versions;
|
|
|
|
private final long[] class_flags;
|
|
private int[] class_attr_calls;
|
|
private final List classSourceFile = new ArrayList();
|
|
private final List classEnclosingMethodClass = new ArrayList();
|
|
private final List classEnclosingMethodDesc = new ArrayList();
|
|
private final List classSignature = new ArrayList();
|
|
|
|
private final IntList classFileVersionMinor = new IntList();
|
|
private final IntList classFileVersionMajor = new IntList();
|
|
|
|
private final int[] class_field_count;
|
|
private final CPNameAndType[][] field_descr;
|
|
private final long[][] field_flags;
|
|
private int[] field_attr_calls;
|
|
private final List fieldConstantValueKQ = new ArrayList();
|
|
private final List fieldSignature = new ArrayList();
|
|
|
|
private final int[] class_method_count;
|
|
private final CPNameAndType[][] method_descr;
|
|
private final long[][] method_flags;
|
|
private int[] method_attr_calls;
|
|
private final List methodSignature = new ArrayList();
|
|
private final IntList methodExceptionNumber = new IntList();
|
|
private final List methodExceptionClasses = new ArrayList();
|
|
|
|
private int[] codeHeaders;
|
|
private final IntList codeMaxStack = new IntList();
|
|
private final IntList codeMaxLocals = new IntList();
|
|
private final IntList codeHandlerCount = new IntList();
|
|
private final List codeHandlerStartP = new ArrayList();
|
|
private final List codeHandlerEndPO = new ArrayList();
|
|
private final List codeHandlerCatchPO = new ArrayList();
|
|
private final List codeHandlerClass = new ArrayList();
|
|
private final List codeFlags = new ArrayList();
|
|
private int[] code_attr_calls;
|
|
private final IntList codeLineNumberTableN = new IntList();
|
|
private final List codeLineNumberTableBciP = new ArrayList();
|
|
private final IntList codeLineNumberTableLine = new IntList();
|
|
private final IntList codeLocalVariableTableN = new IntList();
|
|
private final List codeLocalVariableTableBciP = new ArrayList();
|
|
private final List codeLocalVariableTableSpanO = new ArrayList();
|
|
private final List codeLocalVariableTableNameRU = new ArrayList();
|
|
private final List codeLocalVariableTableTypeRS = new ArrayList();
|
|
private final IntList codeLocalVariableTableSlot = new IntList();
|
|
private final IntList codeLocalVariableTypeTableN = new IntList();
|
|
private final List codeLocalVariableTypeTableBciP = new ArrayList();
|
|
private final List codeLocalVariableTypeTableSpanO = new ArrayList();
|
|
private final List codeLocalVariableTypeTableNameRU = new ArrayList();
|
|
private final List codeLocalVariableTypeTableTypeRS = new ArrayList();
|
|
private final IntList codeLocalVariableTypeTableSlot = new IntList();
|
|
|
|
private final MetadataBandGroup class_RVA_bands;
|
|
private final MetadataBandGroup class_RIA_bands;
|
|
private final MetadataBandGroup field_RVA_bands;
|
|
private final MetadataBandGroup field_RIA_bands;
|
|
private final MetadataBandGroup method_RVA_bands;
|
|
private final MetadataBandGroup method_RIA_bands;
|
|
private final MetadataBandGroup method_RVPA_bands;
|
|
private final MetadataBandGroup method_RIPA_bands;
|
|
private final MetadataBandGroup method_AD_bands;
|
|
|
|
private final List classAttributeBands = new ArrayList();
|
|
private final List methodAttributeBands = new ArrayList();
|
|
private final List fieldAttributeBands = new ArrayList();
|
|
private final List codeAttributeBands = new ArrayList();
|
|
|
|
private final List tempFieldFlags = new ArrayList();
|
|
private final List tempFieldDesc = new ArrayList();
|
|
private final List tempMethodFlags = new ArrayList();
|
|
private final List tempMethodDesc = new ArrayList();
|
|
private TempParamAnnotation tempMethodRVPA;
|
|
private TempParamAnnotation tempMethodRIPA;
|
|
|
|
private boolean anySyntheticClasses = false;
|
|
private boolean anySyntheticFields = false;
|
|
private boolean anySyntheticMethods = false;
|
|
private final Segment segment;
|
|
|
|
private final Map classReferencesInnerClass = new HashMap();
|
|
private final boolean stripDebug;
|
|
|
|
private int index = 0;
|
|
|
|
private int numMethodArgs = 0;
|
|
private int[] class_InnerClasses_N;
|
|
private CPClass[] class_InnerClasses_RC;
|
|
private int[] class_InnerClasses_F;
|
|
private List classInnerClassesOuterRCN;
|
|
private List classInnerClassesNameRUN;
|
|
|
|
public ClassBands(Segment segment, int numClasses, int effort, boolean stripDebug) throws IOException {
|
|
super(effort, segment.getSegmentHeader());
|
|
this.stripDebug = stripDebug;
|
|
this.segment = segment;
|
|
this.cpBands = segment.getCpBands();
|
|
this.attrBands = segment.getAttrBands();
|
|
class_this = new CPClass[numClasses];
|
|
class_super = new CPClass[numClasses];
|
|
class_interface_count = new int[numClasses];
|
|
class_interface = new CPClass[numClasses][];
|
|
class_field_count = new int[numClasses];
|
|
class_method_count = new int[numClasses];
|
|
field_descr = new CPNameAndType[numClasses][];
|
|
field_flags = new long[numClasses][];
|
|
method_descr = new CPNameAndType[numClasses][];
|
|
method_flags = new long[numClasses][];
|
|
for (int i = 0; i < numClasses; i++) {
|
|
field_flags[i] = new long[0];
|
|
method_flags[i] = new long[0];
|
|
}
|
|
// minor_versions = new int[numClasses];
|
|
major_versions = new int[numClasses];
|
|
class_flags = new long[numClasses];
|
|
|
|
class_RVA_bands = new MetadataBandGroup("RVA", MetadataBandGroup.CONTEXT_CLASS, cpBands, segmentHeader, effort);
|
|
class_RIA_bands = new MetadataBandGroup("RIA", MetadataBandGroup.CONTEXT_CLASS, cpBands, segmentHeader, effort);
|
|
field_RVA_bands = new MetadataBandGroup("RVA", MetadataBandGroup.CONTEXT_FIELD, cpBands, segmentHeader, effort);
|
|
field_RIA_bands = new MetadataBandGroup("RIA", MetadataBandGroup.CONTEXT_FIELD, cpBands, segmentHeader, effort);
|
|
method_RVA_bands = new MetadataBandGroup("RVA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
|
|
method_RIA_bands = new MetadataBandGroup("RIA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
|
|
method_RVPA_bands = new MetadataBandGroup("RVPA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
|
|
method_RIPA_bands = new MetadataBandGroup("RIPA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
|
|
method_AD_bands = new MetadataBandGroup("AD", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
|
|
|
|
createNewAttributeBands();
|
|
}
|
|
|
|
private void createNewAttributeBands() throws IOException {
|
|
List classAttributeLayouts = attrBands.getClassAttributeLayouts();
|
|
for (Iterator iterator = classAttributeLayouts.iterator(); iterator.hasNext();) {
|
|
AttributeDefinition def = (AttributeDefinition) iterator.next();
|
|
classAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
|
|
}
|
|
List methodAttributeLayouts = attrBands.getMethodAttributeLayouts();
|
|
for (Iterator iterator = methodAttributeLayouts.iterator(); iterator.hasNext();) {
|
|
AttributeDefinition def = (AttributeDefinition) iterator.next();
|
|
methodAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
|
|
}
|
|
List fieldAttributeLayouts = attrBands.getFieldAttributeLayouts();
|
|
for (Iterator iterator = fieldAttributeLayouts.iterator(); iterator.hasNext();) {
|
|
AttributeDefinition def = (AttributeDefinition) iterator.next();
|
|
fieldAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
|
|
}
|
|
List codeAttributeLayouts = attrBands.getCodeAttributeLayouts();
|
|
for (Iterator iterator = codeAttributeLayouts.iterator(); iterator.hasNext();) {
|
|
AttributeDefinition def = (AttributeDefinition) iterator.next();
|
|
codeAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
|
|
}
|
|
}
|
|
|
|
public void addClass(int major, int flags, String className,
|
|
String signature, String superName, String[] interfaces) {
|
|
class_this[index] = cpBands.getCPClass(className);
|
|
class_super[index] = cpBands.getCPClass(superName);
|
|
class_interface_count[index] = interfaces.length;
|
|
class_interface[index] = new CPClass[interfaces.length];
|
|
for (int i = 0; i < interfaces.length; i++) {
|
|
class_interface[index][i] = cpBands.getCPClass(interfaces[i]);
|
|
}
|
|
major_versions[index] = major;
|
|
class_flags[index] = flags;
|
|
if(!anySyntheticClasses && ((flags & (1 << 12)) != 0) && segment.getCurrentClassReader().hasSyntheticAttributes()) {
|
|
cpBands.addCPUtf8("Synthetic");
|
|
anySyntheticClasses = true;
|
|
}
|
|
if((flags & Opcodes.ACC_DEPRECATED) != 0) { // ASM uses (1<<17) flag for deprecated
|
|
flags = flags & ~Opcodes.ACC_DEPRECATED;
|
|
flags = flags | (1<<20);
|
|
}
|
|
if(signature != null) {
|
|
class_flags[index] |= (1 << 19);
|
|
classSignature.add(cpBands.getCPSignature(signature));
|
|
}
|
|
}
|
|
|
|
public void currentClassReferencesInnerClass(CPClass inner) {
|
|
if(!(index >= class_this.length)) {
|
|
CPClass currentClass = class_this[index];
|
|
if(currentClass != null && !currentClass.equals(inner) && !isInnerClassOf(currentClass.toString(), inner)) {
|
|
Set referencedInnerClasses = (Set)classReferencesInnerClass.get(currentClass);
|
|
if(referencedInnerClasses == null) {
|
|
referencedInnerClasses = new HashSet();
|
|
classReferencesInnerClass.put(currentClass, referencedInnerClasses);
|
|
}
|
|
referencedInnerClasses.add(inner);
|
|
}
|
|
}
|
|
}
|
|
|
|
private boolean isInnerClassOf(String possibleInner, CPClass possibleOuter) {
|
|
if(isInnerClass(possibleInner)) {
|
|
String superClassName = possibleInner.substring(0, possibleInner.lastIndexOf('$'));
|
|
if(superClassName.equals(possibleOuter.toString())) {
|
|
return true;
|
|
} else { // do this recursively
|
|
return isInnerClassOf(superClassName, possibleOuter);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private boolean isInnerClass(String possibleInner) {
|
|
return possibleInner.indexOf('$') != -1;
|
|
}
|
|
|
|
public void addField(int flags, String name, String desc, String signature,
|
|
Object value) {
|
|
flags = flags & 0xFFFF;
|
|
tempFieldDesc.add(cpBands.getCPNameAndType(name, desc));
|
|
if (signature != null) {
|
|
fieldSignature.add(cpBands.getCPSignature(signature));
|
|
flags |= (1 << 19);
|
|
}
|
|
if((flags & Opcodes.ACC_DEPRECATED) != 0) { // ASM uses (1<<17) flag for deprecated
|
|
flags = flags & ~Opcodes.ACC_DEPRECATED;
|
|
flags = flags | (1<<20);
|
|
}
|
|
if (value != null) {
|
|
fieldConstantValueKQ.add(cpBands.getConstant(value));
|
|
flags |= (1 << 17);
|
|
}
|
|
if(!anySyntheticFields && ((flags & (1 << 12)) != 0) && segment.getCurrentClassReader().hasSyntheticAttributes()) {
|
|
cpBands.addCPUtf8("Synthetic");
|
|
anySyntheticFields = true;
|
|
}
|
|
tempFieldFlags.add(new Long(flags));
|
|
}
|
|
|
|
/**
|
|
* All input classes for the segment have now been read in, so this method
|
|
* is called so that this class can calculate/complete anything it could not
|
|
* do while classes were being read.
|
|
*/
|
|
public void finaliseBands() {
|
|
int defaultMajorVersion = segmentHeader.getDefaultMajorVersion();
|
|
for (int i = 0; i < class_flags.length; i++) {
|
|
int major = major_versions[i];
|
|
if (major != defaultMajorVersion) {
|
|
class_flags[i] |= 1 << 24;
|
|
classFileVersionMajor.add(major);
|
|
classFileVersionMinor.add(0);
|
|
}
|
|
}
|
|
// Calculate code headers
|
|
codeHeaders = new int[codeHandlerCount.size()];
|
|
int removed = 0;
|
|
for (int i = 0; i < codeHeaders.length; i++) {
|
|
int numHandlers = codeHandlerCount.get(i - removed);
|
|
int maxLocals = codeMaxLocals.get(i - removed);
|
|
int maxStack = codeMaxStack.get(i - removed);
|
|
if (numHandlers == 0) {
|
|
int header = maxLocals * 12 + maxStack + 1;
|
|
if (header < 145 && maxStack < 12) {
|
|
codeHeaders[i] = header;
|
|
}
|
|
} else if (numHandlers == 1) {
|
|
int header = maxLocals * 8 + maxStack + 145;
|
|
if (header < 209 && maxStack < 8) {
|
|
codeHeaders[i] = header;
|
|
}
|
|
} else if (numHandlers == 2) {
|
|
int header = maxLocals * 7 + maxStack + 209;
|
|
if (header < 256 && maxStack < 7) {
|
|
codeHeaders[i] = header;
|
|
}
|
|
}
|
|
if (codeHeaders[i] != 0) { // Remove the redundant values from
|
|
// codeHandlerCount, codeMaxLocals and
|
|
// codeMaxStack
|
|
codeHandlerCount.remove(i - removed);
|
|
codeMaxLocals.remove(i - removed);
|
|
codeMaxStack.remove(i - removed);
|
|
removed++;
|
|
} else if (!segment.getSegmentHeader().have_all_code_flags()) {
|
|
codeFlags.add(new Long(0));
|
|
}
|
|
}
|
|
|
|
// Compute any required IcLocals
|
|
IntList innerClassesN = new IntList();
|
|
List icLocal = new ArrayList();
|
|
for (int i = 0; i < class_this.length; i++) {
|
|
CPClass cpClass = class_this[i];
|
|
Set referencedInnerClasses = (Set) classReferencesInnerClass.get(cpClass);
|
|
if(referencedInnerClasses != null) {
|
|
int innerN = 0;
|
|
List innerClasses = segment.getIcBands().getInnerClassesForOuter(cpClass.toString());
|
|
if(innerClasses != null) {
|
|
for (Iterator iterator2 = innerClasses.iterator(); iterator2
|
|
.hasNext();) {
|
|
referencedInnerClasses.remove(((IcTuple)iterator2.next()).C);
|
|
}
|
|
}
|
|
for (Iterator iterator2 = referencedInnerClasses.iterator(); iterator2
|
|
.hasNext();) {
|
|
CPClass inner = (CPClass) iterator2.next();
|
|
IcTuple icTuple = segment.getIcBands().getIcTuple(inner);
|
|
if(icTuple != null && ! icTuple.isAnonymous()) {
|
|
// should transmit an icLocal entry
|
|
icLocal.add(icTuple);
|
|
innerN++;
|
|
}
|
|
}
|
|
if(innerN != 0) {
|
|
innerClassesN.add(innerN);
|
|
class_flags[i] |= (1 << 23);
|
|
}
|
|
}
|
|
}
|
|
class_InnerClasses_N = innerClassesN.toArray();
|
|
class_InnerClasses_RC = new CPClass[icLocal.size()];
|
|
class_InnerClasses_F = new int[icLocal.size()];
|
|
classInnerClassesOuterRCN = new ArrayList();
|
|
classInnerClassesNameRUN = new ArrayList();
|
|
for (int i = 0; i < class_InnerClasses_RC.length; i++) {
|
|
IcTuple icTuple = (IcTuple) icLocal.get(i);
|
|
class_InnerClasses_RC[i] = (icTuple.C);
|
|
if(icTuple.C2 == null && icTuple.N == null) {
|
|
class_InnerClasses_F[i] = 0;
|
|
} else {
|
|
if (icTuple.F == 0) {
|
|
class_InnerClasses_F[i] = 0x00010000;
|
|
} else {
|
|
class_InnerClasses_F[i] = icTuple.F;
|
|
}
|
|
classInnerClassesOuterRCN.add(icTuple.C2);
|
|
classInnerClassesNameRUN.add(icTuple.N);
|
|
}
|
|
}
|
|
// Calculate any backwards calls from metadata bands
|
|
IntList classAttrCalls = new IntList();
|
|
IntList fieldAttrCalls = new IntList();
|
|
IntList methodAttrCalls = new IntList();
|
|
IntList codeAttrCalls = new IntList();
|
|
|
|
if(class_RVA_bands.hasContent()) {
|
|
classAttrCalls.add(class_RVA_bands.numBackwardsCalls());
|
|
}
|
|
if(class_RIA_bands.hasContent()) {
|
|
classAttrCalls.add(class_RIA_bands.numBackwardsCalls());
|
|
}
|
|
if(field_RVA_bands.hasContent()) {
|
|
fieldAttrCalls.add(field_RVA_bands.numBackwardsCalls());
|
|
}
|
|
if(field_RIA_bands.hasContent()) {
|
|
fieldAttrCalls.add(field_RIA_bands.numBackwardsCalls());
|
|
}
|
|
if(method_RVA_bands.hasContent()) {
|
|
methodAttrCalls.add(method_RVA_bands.numBackwardsCalls());
|
|
}
|
|
if(method_RIA_bands.hasContent()) {
|
|
methodAttrCalls.add(method_RIA_bands.numBackwardsCalls());
|
|
}
|
|
if(method_RVPA_bands.hasContent()) {
|
|
methodAttrCalls.add(method_RVPA_bands.numBackwardsCalls());
|
|
}
|
|
if(method_RIPA_bands.hasContent()) {
|
|
methodAttrCalls.add(method_RIPA_bands.numBackwardsCalls());
|
|
}
|
|
if(method_AD_bands.hasContent()) {
|
|
methodAttrCalls.add(method_AD_bands.numBackwardsCalls());
|
|
}
|
|
|
|
// Sort non-predefined attribute bands
|
|
Comparator comparator = new Comparator() {
|
|
public int compare(Object arg0, Object arg1) {
|
|
NewAttributeBands bands0 = (NewAttributeBands)arg0;
|
|
NewAttributeBands bands1 = (NewAttributeBands)arg1;
|
|
return bands0.getFlagIndex() - bands1.getFlagIndex();
|
|
}
|
|
};
|
|
Collections.sort(classAttributeBands, comparator);
|
|
Collections.sort(methodAttributeBands, comparator);
|
|
Collections.sort(fieldAttributeBands, comparator);
|
|
Collections.sort(codeAttributeBands, comparator);
|
|
|
|
for (Iterator iterator = classAttributeBands.iterator(); iterator.hasNext();) {
|
|
NewAttributeBands bands = (NewAttributeBands) iterator.next();
|
|
if(bands.isUsedAtLeastOnce()) {
|
|
int[] backwardsCallCounts = bands.numBackwardsCalls();
|
|
for (int i = 0; i < backwardsCallCounts.length; i++) {
|
|
classAttrCalls.add(backwardsCallCounts[i]);
|
|
}
|
|
}
|
|
}
|
|
for (Iterator iterator = methodAttributeBands.iterator(); iterator.hasNext();) {
|
|
NewAttributeBands bands = (NewAttributeBands) iterator.next();
|
|
if(bands.isUsedAtLeastOnce()) {
|
|
int[] backwardsCallCounts = bands.numBackwardsCalls();
|
|
for (int i = 0; i < backwardsCallCounts.length; i++) {
|
|
methodAttrCalls.add(backwardsCallCounts[i]);
|
|
}
|
|
}
|
|
}
|
|
for (Iterator iterator = fieldAttributeBands.iterator(); iterator.hasNext();) {
|
|
NewAttributeBands bands = (NewAttributeBands) iterator.next();
|
|
if(bands.isUsedAtLeastOnce()) {
|
|
int[] backwardsCallCounts = bands.numBackwardsCalls();
|
|
for (int i = 0; i < backwardsCallCounts.length; i++) {
|
|
fieldAttrCalls.add(backwardsCallCounts[i]);
|
|
}
|
|
}
|
|
}
|
|
for (Iterator iterator = codeAttributeBands.iterator(); iterator.hasNext();) {
|
|
NewAttributeBands bands = (NewAttributeBands) iterator.next();
|
|
if(bands.isUsedAtLeastOnce()) {
|
|
int[] backwardsCallCounts = bands.numBackwardsCalls();
|
|
for (int i = 0; i < backwardsCallCounts.length; i++) {
|
|
codeAttrCalls.add(backwardsCallCounts[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
class_attr_calls = classAttrCalls.toArray();
|
|
field_attr_calls = fieldAttrCalls.toArray();
|
|
method_attr_calls = methodAttrCalls.toArray();
|
|
code_attr_calls = codeAttrCalls.toArray();
|
|
}
|
|
|
|
public void pack(OutputStream out) throws IOException, Pack200Exception {
|
|
PackingUtils.log("Writing class bands...");
|
|
|
|
byte[] encodedBand = encodeBandInt("class_this", getInts(class_this),
|
|
Codec.DELTA5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from class_this[" + class_this.length + "]");
|
|
|
|
encodedBand = encodeBandInt("class_super", getInts(class_super),
|
|
Codec.DELTA5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from class_super[" + class_super.length + "]");
|
|
|
|
encodedBand = encodeBandInt("class_interface_count",
|
|
class_interface_count, Codec.DELTA5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from class_interface_count["
|
|
+ class_interface_count.length + "]");
|
|
|
|
int totalInterfaces = sum(class_interface_count);
|
|
int[] classInterface = new int[totalInterfaces];
|
|
int k = 0;
|
|
for (int i = 0; i < class_interface.length; i++) {
|
|
if (class_interface[i] != null) {
|
|
for (int j = 0; j < class_interface[i].length; j++) {
|
|
CPClass cpClass = class_interface[i][j];
|
|
classInterface[k] = cpClass.getIndex();
|
|
k++;
|
|
}
|
|
}
|
|
}
|
|
|
|
encodedBand = encodeBandInt("class_interface", classInterface,
|
|
Codec.DELTA5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from class_interface[" + classInterface.length + "]");
|
|
|
|
encodedBand = encodeBandInt("class_field_count", class_field_count,
|
|
Codec.DELTA5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from class_field_count[" + class_field_count.length
|
|
+ "]");
|
|
|
|
encodedBand = encodeBandInt("class_method_count", class_method_count,
|
|
Codec.DELTA5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from class_method_count[" + class_method_count.length
|
|
+ "]");
|
|
|
|
int totalFields = sum(class_field_count);
|
|
int[] fieldDescr = new int[totalFields];
|
|
k = 0;
|
|
for (int i = 0; i < index; i++) {
|
|
for (int j = 0; j < field_descr[i].length; j++) {
|
|
CPNameAndType descr = field_descr[i][j];
|
|
fieldDescr[k] = descr.getIndex();
|
|
k++;
|
|
}
|
|
}
|
|
|
|
encodedBand = encodeBandInt("field_descr", fieldDescr, Codec.DELTA5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from field_descr[" + fieldDescr.length + "]");
|
|
|
|
writeFieldAttributeBands(out);
|
|
|
|
int totalMethods = sum(class_method_count);
|
|
int[] methodDescr = new int[totalMethods];
|
|
k = 0;
|
|
for (int i = 0; i < index; i++) {
|
|
for (int j = 0; j < method_descr[i].length; j++) {
|
|
CPNameAndType descr = method_descr[i][j];
|
|
methodDescr[k] = descr.getIndex();
|
|
k++;
|
|
}
|
|
}
|
|
|
|
encodedBand = encodeBandInt("method_descr", methodDescr, Codec.MDELTA5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from method_descr[" + methodDescr.length + "]");
|
|
|
|
writeMethodAttributeBands(out);
|
|
writeClassAttributeBands(out);
|
|
writeCodeBands(out);
|
|
}
|
|
|
|
private int sum(int[] ints) {
|
|
int sum = 0;
|
|
for (int i = 0; i < ints.length; i++) {
|
|
sum += ints[i];
|
|
}
|
|
return sum;
|
|
}
|
|
|
|
private void writeFieldAttributeBands(OutputStream out) throws IOException,
|
|
Pack200Exception {
|
|
byte[] encodedBand = encodeFlags("field_flags", field_flags,
|
|
Codec.UNSIGNED5, Codec.UNSIGNED5, segmentHeader
|
|
.have_field_flags_hi());
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from field_flags[" + field_flags.length + "]");
|
|
|
|
// *field_attr_count :UNSIGNED5 [COUNT(1<<16,...)]
|
|
// *field_attr_indexes :UNSIGNED5 [SUM(*field_attr_count)]
|
|
encodedBand = encodeBandInt("field_attr_calls", field_attr_calls,
|
|
Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from field_attr_calls[" + field_attr_calls.length
|
|
+ "]");
|
|
|
|
encodedBand = encodeBandInt("fieldConstantValueKQ",
|
|
cpEntryListToArray(fieldConstantValueKQ), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from fieldConstantValueKQ["
|
|
+ fieldConstantValueKQ.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("fieldSignature",
|
|
cpEntryListToArray(fieldSignature), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from fieldSignature[" + fieldSignature.size() + "]");
|
|
|
|
field_RVA_bands.pack(out);
|
|
field_RIA_bands.pack(out);
|
|
for (Iterator iterator = fieldAttributeBands.iterator(); iterator
|
|
.hasNext();) {
|
|
NewAttributeBands bands = (NewAttributeBands) iterator.next();
|
|
bands.pack(out);
|
|
}
|
|
}
|
|
|
|
private void writeMethodAttributeBands(OutputStream out)
|
|
throws IOException, Pack200Exception {
|
|
byte[] encodedBand = encodeFlags("method_flags", method_flags,
|
|
Codec.UNSIGNED5, Codec.UNSIGNED5, segmentHeader
|
|
.have_method_flags_hi());
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from method_flags[" + method_flags.length + "]");
|
|
|
|
// *method_attr_count :UNSIGNED5 [COUNT(1<<16,...)]
|
|
// *method_attr_indexes :UNSIGNED5 [SUM(*method_attr_count)]
|
|
encodedBand = encodeBandInt("method_attr_calls", method_attr_calls,
|
|
Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from method_attr_calls[" + method_attr_calls.length
|
|
+ "]");
|
|
|
|
encodedBand = encodeBandInt("methodExceptionNumber",
|
|
methodExceptionNumber.toArray(), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from methodExceptionNumber["
|
|
+ methodExceptionNumber.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("methodExceptionClasses",
|
|
cpEntryListToArray(methodExceptionClasses), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from methodExceptionClasses["
|
|
+ methodExceptionClasses.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("methodSignature",
|
|
cpEntryListToArray(methodSignature), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils
|
|
.log("Wrote " + encodedBand.length
|
|
+ " bytes from methodSignature["
|
|
+ methodSignature.size() + "]");
|
|
|
|
method_RVA_bands.pack(out);
|
|
method_RIA_bands.pack(out);
|
|
method_RVPA_bands.pack(out);
|
|
method_RIPA_bands.pack(out);
|
|
method_AD_bands.pack(out);
|
|
for (Iterator iterator = methodAttributeBands.iterator(); iterator
|
|
.hasNext();) {
|
|
NewAttributeBands bands = (NewAttributeBands) iterator.next();
|
|
bands.pack(out);
|
|
}
|
|
}
|
|
|
|
private void writeClassAttributeBands(OutputStream out) throws IOException,
|
|
Pack200Exception {
|
|
byte[] encodedBand = encodeFlags("class_flags", class_flags,
|
|
Codec.UNSIGNED5, Codec.UNSIGNED5, segmentHeader
|
|
.have_class_flags_hi());
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from class_flags[" + class_flags.length + "]");
|
|
|
|
// These bands are not needed, but could be used to reduce the size of
|
|
// the archive if there are enough different non-standard attributes
|
|
// defined that segmentHeader.have_class_flags_hi() is true. The same
|
|
// applies to method_attr_count, field_attr_count, code_attr_count etc.
|
|
|
|
// *class_attr_count :UNSIGNED5 [COUNT(1<<16,...)]
|
|
// *class_attr_indexes :UNSIGNED5 [SUM(*class_attr_count)]
|
|
|
|
encodedBand = encodeBandInt("class_attr_calls", class_attr_calls,
|
|
Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from class_attr_calls[" + class_attr_calls.length
|
|
+ "]");
|
|
|
|
encodedBand = encodeBandInt("classSourceFile",
|
|
cpEntryOrNullListToArray(classSourceFile), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils
|
|
.log("Wrote " + encodedBand.length
|
|
+ " bytes from classSourceFile["
|
|
+ classSourceFile.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("class_enclosing_method_RC",
|
|
cpEntryListToArray(classEnclosingMethodClass), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from class_enclosing_method_RC["
|
|
+ classEnclosingMethodClass.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("class_EnclosingMethod_RDN",
|
|
cpEntryOrNullListToArray(classEnclosingMethodDesc),
|
|
Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from class_EnclosingMethod_RDN["
|
|
+ classEnclosingMethodDesc.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("class_Signature_RS",
|
|
cpEntryListToArray(classSignature), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from class_Signature_RS[" + classSignature.size()
|
|
+ "]");
|
|
|
|
class_RVA_bands.pack(out);
|
|
class_RIA_bands.pack(out);
|
|
|
|
encodedBand = encodeBandInt("class_InnerClasses_N",
|
|
class_InnerClasses_N, Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from class_InnerClasses_N["
|
|
+ class_InnerClasses_N.length + "]");
|
|
|
|
encodedBand = encodeBandInt("class_InnerClasses_RC",
|
|
getInts(class_InnerClasses_RC), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from class_InnerClasses_RC["
|
|
+ class_InnerClasses_RC.length + "]");
|
|
|
|
encodedBand = encodeBandInt("class_InnerClasses_F",
|
|
class_InnerClasses_F, Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from class_InnerClasses_F["
|
|
+ class_InnerClasses_F.length + "]");
|
|
|
|
encodedBand = encodeBandInt("class_InnerClasses_outer_RCN",
|
|
cpEntryOrNullListToArray(classInnerClassesOuterRCN),
|
|
Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from class_InnerClasses_outer_RCN["
|
|
+ classInnerClassesOuterRCN.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("class_InnerClasses_name_RUN",
|
|
cpEntryOrNullListToArray(classInnerClassesNameRUN),
|
|
Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from class_InnerClasses_name_RUN["
|
|
+ classInnerClassesNameRUN.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("classFileVersionMinor",
|
|
classFileVersionMinor.toArray(), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from classFileVersionMinor["
|
|
+ classFileVersionMinor.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("classFileVersionMajor",
|
|
classFileVersionMajor.toArray(), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from classFileVersionMajor["
|
|
+ classFileVersionMajor.size() + "]");
|
|
|
|
for (Iterator iterator = classAttributeBands.iterator(); iterator
|
|
.hasNext();) {
|
|
NewAttributeBands bands = (NewAttributeBands) iterator.next();
|
|
bands.pack(out);
|
|
}
|
|
}
|
|
|
|
private int[] getInts(CPClass[] cpClasses) {
|
|
int[] ints = new int[cpClasses.length];
|
|
for (int i = 0; i < ints.length; i++) {
|
|
if(cpClasses[i] != null) {
|
|
ints[i] = cpClasses[i].getIndex();
|
|
}
|
|
}
|
|
return ints;
|
|
}
|
|
|
|
private void writeCodeBands(OutputStream out) throws IOException,
|
|
Pack200Exception {
|
|
byte[] encodedBand = encodeBandInt("codeHeaders", codeHeaders,
|
|
Codec.BYTE1);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from codeHeaders[" + codeHeaders.length + "]");
|
|
|
|
encodedBand = encodeBandInt("codeMaxStack", codeMaxStack.toArray(),
|
|
Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from codeMaxStack[" + codeMaxStack.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("codeMaxLocals", codeMaxLocals.toArray(),
|
|
Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from codeMaxLocals[" + codeMaxLocals.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("codeHandlerCount", codeHandlerCount
|
|
.toArray(), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from codeHandlerCount[" + codeHandlerCount.size()
|
|
+ "]");
|
|
|
|
encodedBand = encodeBandInt("codeHandlerStartP",
|
|
integerListToArray(codeHandlerStartP), Codec.BCI5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from codeHandlerStartP[" + codeHandlerStartP.size()
|
|
+ "]");
|
|
|
|
encodedBand = encodeBandInt("codeHandlerEndPO",
|
|
integerListToArray(codeHandlerEndPO), Codec.BRANCH5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from codeHandlerEndPO[" + codeHandlerEndPO.size()
|
|
+ "]");
|
|
|
|
encodedBand = encodeBandInt("codeHandlerCatchPO",
|
|
integerListToArray(codeHandlerCatchPO), Codec.BRANCH5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from codeHandlerCatchPO[" + codeHandlerCatchPO.size()
|
|
+ "]");
|
|
|
|
encodedBand = encodeBandInt("codeHandlerClass",
|
|
cpEntryOrNullListToArray(codeHandlerClass), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from codeHandlerClass[" + codeHandlerClass.size()
|
|
+ "]");
|
|
|
|
writeCodeAttributeBands(out);
|
|
}
|
|
|
|
private void writeCodeAttributeBands(OutputStream out) throws IOException,
|
|
Pack200Exception {
|
|
byte[] encodedBand = encodeFlags("codeFlags",
|
|
longListToArray(codeFlags), Codec.UNSIGNED5, Codec.UNSIGNED5,
|
|
segmentHeader.have_code_flags_hi());
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from codeFlags[" + codeFlags.size() + "]");
|
|
|
|
// *code_attr_count :UNSIGNED5 [COUNT(1<<16,...)]
|
|
// *code_attr_indexes :UNSIGNED5 [SUM(*code_attr_count)]
|
|
encodedBand = encodeBandInt("code_attr_calls", code_attr_calls,
|
|
Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils
|
|
.log("Wrote " + encodedBand.length
|
|
+ " bytes from code_attr_calls["
|
|
+ code_attr_calls.length + "]");
|
|
|
|
encodedBand = encodeBandInt("code_LineNumberTable_N",
|
|
codeLineNumberTableN.toArray(), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from code_LineNumberTable_N["
|
|
+ codeLineNumberTableN.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("code_LineNumberTable_bci_P",
|
|
integerListToArray(codeLineNumberTableBciP), Codec.BCI5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from code_LineNumberTable_bci_P["
|
|
+ codeLineNumberTableBciP.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("code_LineNumberTable_line",
|
|
codeLineNumberTableLine.toArray(), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from code_LineNumberTable_line["
|
|
+ codeLineNumberTableLine.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("code_LocalVariableTable_N",
|
|
codeLocalVariableTableN.toArray(), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from code_LocalVariableTable_N["
|
|
+ codeLocalVariableTableN.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("code_LocalVariableTable_bci_P",
|
|
integerListToArray(codeLocalVariableTableBciP), Codec.BCI5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from code_LocalVariableTable_bci_P["
|
|
+ codeLocalVariableTableBciP.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("code_LocalVariableTable_span_O",
|
|
integerListToArray(codeLocalVariableTableSpanO), Codec.BRANCH5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from code_LocalVariableTable_span_O["
|
|
+ codeLocalVariableTableSpanO.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("code_LocalVariableTable_name_RU",
|
|
cpEntryListToArray(codeLocalVariableTableNameRU),
|
|
Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from code_LocalVariableTable_name_RU["
|
|
+ codeLocalVariableTableNameRU.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("code_LocalVariableTable_type_RS",
|
|
cpEntryListToArray(codeLocalVariableTableTypeRS),
|
|
Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from code_LocalVariableTable_type_RS["
|
|
+ codeLocalVariableTableTypeRS.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("code_LocalVariableTable_slot",
|
|
codeLocalVariableTableSlot.toArray(), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from code_LocalVariableTable_slot["
|
|
+ codeLocalVariableTableSlot.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("code_LocalVariableTypeTable_N",
|
|
codeLocalVariableTypeTableN.toArray(), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from code_LocalVariableTypeTable_N["
|
|
+ codeLocalVariableTypeTableN.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("code_LocalVariableTypeTable_bci_P",
|
|
integerListToArray(codeLocalVariableTypeTableBciP), Codec.BCI5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from code_LocalVariableTypeTable_bci_P["
|
|
+ codeLocalVariableTypeTableBciP.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("code_LocalVariableTypeTable_span_O",
|
|
integerListToArray(codeLocalVariableTypeTableSpanO), Codec.BRANCH5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from code_LocalVariableTypeTable_span_O["
|
|
+ codeLocalVariableTypeTableSpanO.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("code_LocalVariableTypeTable_name_RU",
|
|
cpEntryListToArray(codeLocalVariableTypeTableNameRU),
|
|
Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from code_LocalVariableTypeTable_name_RU["
|
|
+ codeLocalVariableTypeTableNameRU.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("code_LocalVariableTypeTable_type_RS",
|
|
cpEntryListToArray(codeLocalVariableTypeTableTypeRS),
|
|
Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from code_LocalVariableTypeTable_type_RS["
|
|
+ codeLocalVariableTypeTableTypeRS.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("code_LocalVariableTypeTable_slot",
|
|
codeLocalVariableTypeTableSlot.toArray(), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from code_LocalVariableTypeTable_slot["
|
|
+ codeLocalVariableTypeTableSlot.size() + "]");
|
|
|
|
for (Iterator iterator = codeAttributeBands.iterator(); iterator.hasNext();) {
|
|
NewAttributeBands bands = (NewAttributeBands) iterator.next();
|
|
bands.pack(out);
|
|
}
|
|
}
|
|
|
|
public void addMethod(int flags, String name, String desc,
|
|
String signature, String[] exceptions) {
|
|
CPNameAndType nt = cpBands.getCPNameAndType(name, desc);
|
|
tempMethodDesc.add(nt);
|
|
if (signature != null) {
|
|
methodSignature.add(cpBands.getCPSignature(signature));
|
|
flags |= (1 << 19);
|
|
}
|
|
if (exceptions != null) {
|
|
methodExceptionNumber.add(exceptions.length);
|
|
for (int i = 0; i < exceptions.length; i++) {
|
|
methodExceptionClasses.add(cpBands.getCPClass(exceptions[i]));
|
|
}
|
|
flags |= (1 << 18);
|
|
}
|
|
if((flags & Opcodes.ACC_DEPRECATED) != 0) { // ASM uses (1<<17) flag for deprecated
|
|
flags = flags & ~Opcodes.ACC_DEPRECATED;
|
|
flags = flags | (1<<20);
|
|
}
|
|
tempMethodFlags.add(new Long(flags));
|
|
numMethodArgs = countArgs(desc);
|
|
if(!anySyntheticMethods && ((flags & (1 << 12)) != 0) && segment.getCurrentClassReader().hasSyntheticAttributes()) {
|
|
cpBands.addCPUtf8("Synthetic");
|
|
anySyntheticMethods = true;
|
|
}
|
|
}
|
|
|
|
public void endOfMethod() {
|
|
if (tempMethodRVPA != null) {
|
|
method_RVPA_bands.addParameterAnnotation(tempMethodRVPA.numParams,
|
|
tempMethodRVPA.annoN, tempMethodRVPA.pairN,
|
|
tempMethodRVPA.typeRS, tempMethodRVPA.nameRU,
|
|
tempMethodRVPA.t, tempMethodRVPA.values,
|
|
tempMethodRVPA.caseArrayN, tempMethodRVPA.nestTypeRS,
|
|
tempMethodRVPA.nestNameRU, tempMethodRVPA.nestPairN);
|
|
tempMethodRVPA = null;
|
|
}
|
|
if (tempMethodRIPA != null) {
|
|
method_RIPA_bands.addParameterAnnotation(tempMethodRIPA.numParams,
|
|
tempMethodRIPA.annoN, tempMethodRIPA.pairN,
|
|
tempMethodRIPA.typeRS, tempMethodRIPA.nameRU,
|
|
tempMethodRIPA.t, tempMethodRIPA.values,
|
|
tempMethodRIPA.caseArrayN, tempMethodRIPA.nestTypeRS,
|
|
tempMethodRIPA.nestNameRU, tempMethodRIPA.nestPairN);
|
|
tempMethodRIPA = null;
|
|
}
|
|
if(codeFlags.size() > 0) {
|
|
long latestCodeFlag = ((Long)codeFlags.get(codeFlags.size() - 1)).longValue();
|
|
int latestLocalVariableTableN = codeLocalVariableTableN.get(codeLocalVariableTableN.size() - 1);
|
|
if(latestCodeFlag == (1 << 2) && latestLocalVariableTableN == 0) {
|
|
codeLocalVariableTableN.remove(codeLocalVariableTableN.size() - 1);
|
|
codeFlags.remove(codeFlags.size() - 1);
|
|
codeFlags.add(new Long(0));
|
|
}
|
|
}
|
|
}
|
|
|
|
protected static int countArgs(String descriptor) {
|
|
int bra = descriptor.indexOf('(');
|
|
int ket = descriptor.indexOf(')');
|
|
if (bra == -1 || ket == -1 || ket < bra)
|
|
throw new IllegalArgumentException("No arguments");
|
|
|
|
boolean inType = false;
|
|
boolean consumingNextType = false;
|
|
int count = 0;
|
|
for (int i = bra + 1; i < ket; i++) {
|
|
char charAt = descriptor.charAt(i);
|
|
if (inType && charAt == ';') {
|
|
inType = false;
|
|
consumingNextType = false;
|
|
} else if (!inType && charAt == 'L') {
|
|
inType = true;
|
|
count++;
|
|
} else if (charAt == '[') {
|
|
consumingNextType = true;
|
|
} else if (inType) {
|
|
// NOP
|
|
} else {
|
|
if (consumingNextType) {
|
|
count++;
|
|
consumingNextType = false;
|
|
} else {
|
|
if (charAt == 'D' || charAt == 'J') {
|
|
count += 2;
|
|
} else {
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
public void endOfClass() { // All the data for the current class has been
|
|
// read
|
|
int numFields = tempFieldDesc.size();
|
|
class_field_count[index] = numFields;
|
|
field_descr[index] = new CPNameAndType[numFields];
|
|
field_flags[index] = new long[numFields];
|
|
for (int i = 0; i < numFields; i++) {
|
|
field_descr[index][i] = (CPNameAndType) tempFieldDesc.get(i);
|
|
field_flags[index][i] = ((Long) tempFieldFlags.get(i)).longValue();
|
|
}
|
|
int numMethods = tempMethodDesc.size();
|
|
class_method_count[index] = numMethods;
|
|
method_descr[index] = new CPNameAndType[numMethods];
|
|
method_flags[index] = new long[numMethods];
|
|
for (int i = 0; i < numMethods; i++) {
|
|
method_descr[index][i] = (CPNameAndType) tempMethodDesc.get(i);
|
|
method_flags[index][i] = ((Long) tempMethodFlags.get(i))
|
|
.longValue();
|
|
}
|
|
tempFieldDesc.clear();
|
|
tempFieldFlags.clear();
|
|
tempMethodDesc.clear();
|
|
tempMethodFlags.clear();
|
|
index++;
|
|
}
|
|
|
|
public void addSourceFile(String source) {
|
|
String implicitSourceFileName = class_this[index].toString();
|
|
if(implicitSourceFileName.indexOf('$') != -1) {
|
|
implicitSourceFileName = implicitSourceFileName.substring(0, implicitSourceFileName.indexOf('$'));
|
|
}
|
|
implicitSourceFileName = implicitSourceFileName
|
|
.substring(implicitSourceFileName.lastIndexOf('/') + 1)
|
|
+ ".java";
|
|
if (source.equals(implicitSourceFileName)) {
|
|
classSourceFile.add(null);
|
|
} else {
|
|
classSourceFile.add(cpBands.getCPUtf8(source));
|
|
}
|
|
class_flags[index] |= (1 << 17);
|
|
}
|
|
|
|
public void addEnclosingMethod(String owner, String name, String desc) {
|
|
class_flags[index] |= (1 << 18);
|
|
classEnclosingMethodClass.add(cpBands.getCPClass(owner));
|
|
classEnclosingMethodDesc.add(name == null ? null : cpBands
|
|
.getCPNameAndType(name, desc));
|
|
}
|
|
|
|
public void addClassAttribute(NewAttribute attribute) {
|
|
// TODO: backwards calls
|
|
String attributeName = attribute.type;
|
|
for (Iterator iterator = classAttributeBands.iterator(); iterator.hasNext();) {
|
|
NewAttributeBands bands = (NewAttributeBands) iterator.next();
|
|
if(bands.getAttributeName().equals(attributeName)) {
|
|
bands.addAttribute(attribute);
|
|
int flagIndex = bands.getFlagIndex();
|
|
class_flags[index] |= (1 << flagIndex);
|
|
return;
|
|
}
|
|
}
|
|
throw new RuntimeException("No suitable definition for " + attributeName);
|
|
}
|
|
|
|
public void addFieldAttribute(NewAttribute attribute) {
|
|
String attributeName = attribute.type;
|
|
for (Iterator iterator = fieldAttributeBands.iterator(); iterator.hasNext();) {
|
|
NewAttributeBands bands = (NewAttributeBands) iterator.next();
|
|
if(bands.getAttributeName().equals(attributeName)) {
|
|
bands.addAttribute(attribute);
|
|
int flagIndex = bands.getFlagIndex();
|
|
Long flags = (Long)tempFieldFlags.remove(tempFieldFlags.size() - 1);
|
|
tempFieldFlags.add(new Long(flags.longValue() | (1 << flagIndex)));
|
|
return;
|
|
}
|
|
}
|
|
throw new RuntimeException("No suitable definition for " + attributeName);
|
|
}
|
|
|
|
public void addMethodAttribute(NewAttribute attribute) {
|
|
String attributeName = attribute.type;
|
|
for (Iterator iterator = methodAttributeBands.iterator(); iterator.hasNext();) {
|
|
NewAttributeBands bands = (NewAttributeBands) iterator.next();
|
|
if(bands.getAttributeName().equals(attributeName)) {
|
|
bands.addAttribute(attribute);
|
|
int flagIndex = bands.getFlagIndex();
|
|
Long flags = (Long)tempMethodFlags.remove(tempMethodFlags.size() - 1);
|
|
tempMethodFlags.add(new Long(flags.longValue() | (1 << flagIndex)));
|
|
return;
|
|
}
|
|
}
|
|
throw new RuntimeException("No suitable definition for " + attributeName);
|
|
}
|
|
|
|
public void addCodeAttribute(NewAttribute attribute) {
|
|
String attributeName = attribute.type;
|
|
for (Iterator iterator = codeAttributeBands.iterator(); iterator.hasNext();) {
|
|
NewAttributeBands bands = (NewAttributeBands) iterator.next();
|
|
if(bands.getAttributeName().equals(attributeName)) {
|
|
bands.addAttribute(attribute);
|
|
int flagIndex = bands.getFlagIndex();
|
|
Long flags = (Long)codeFlags.remove(codeFlags.size() - 1);
|
|
codeFlags.add(new Long(flags.longValue() | (1 << flagIndex)));
|
|
return;
|
|
}
|
|
}
|
|
throw new RuntimeException("No suitable definition for " + attributeName);
|
|
}
|
|
|
|
public void addMaxStack(int maxStack, int maxLocals) {
|
|
Long latestFlag = (Long) tempMethodFlags
|
|
.remove(tempMethodFlags.size() - 1);
|
|
Long newFlag = new Long(latestFlag.intValue() | (1 << 17));
|
|
tempMethodFlags.add(newFlag);
|
|
codeMaxStack.add(maxStack);
|
|
if ((newFlag.longValue() & (1 << 3)) == 0) { // not static
|
|
maxLocals--; // minus 'this' local
|
|
}
|
|
maxLocals -= numMethodArgs;
|
|
codeMaxLocals.add(maxLocals);
|
|
}
|
|
|
|
public void addCode() {
|
|
codeHandlerCount.add(0);
|
|
if(!stripDebug) {
|
|
codeFlags.add(new Long((1 << 2)));
|
|
codeLocalVariableTableN.add(0);
|
|
}
|
|
}
|
|
|
|
public void addHandler(Label start, Label end, Label handler, String type) {
|
|
int handlers = codeHandlerCount.remove(codeHandlerCount
|
|
.size() - 1);
|
|
codeHandlerCount.add(handlers + 1);
|
|
codeHandlerStartP.add(start);
|
|
codeHandlerEndPO.add(end);
|
|
codeHandlerCatchPO.add(handler);
|
|
codeHandlerClass.add(type == null ? null : cpBands.getCPClass(type));
|
|
}
|
|
|
|
public void addLineNumber(int line, Label start) {
|
|
Long latestCodeFlag = (Long) codeFlags.get(codeFlags.size() - 1);
|
|
if ((latestCodeFlag.intValue() & (1 << 1)) == 0) {
|
|
codeFlags.remove(codeFlags.size() - 1);
|
|
codeFlags.add(new Long(latestCodeFlag.intValue() | (1 << 1)));
|
|
codeLineNumberTableN.add(1);
|
|
} else {
|
|
codeLineNumberTableN
|
|
.increment(codeLineNumberTableN.size() - 1);
|
|
}
|
|
codeLineNumberTableLine.add(line);
|
|
codeLineNumberTableBciP.add(start);
|
|
}
|
|
|
|
public void addLocalVariable(String name, String desc, String signature,
|
|
Label start, Label end, int indx) {
|
|
if (signature != null) { // LocalVariableTypeTable attribute
|
|
Long latestCodeFlag = (Long) codeFlags.get(codeFlags.size() - 1);
|
|
if ((latestCodeFlag.intValue() & (1 << 3)) == 0) {
|
|
codeFlags.remove(codeFlags.size() - 1);
|
|
codeFlags.add(new Long(latestCodeFlag.intValue() | (1 << 3)));
|
|
codeLocalVariableTypeTableN.add(1);
|
|
} else {
|
|
codeLocalVariableTypeTableN
|
|
.increment(codeLocalVariableTypeTableN.size() - 1);
|
|
}
|
|
codeLocalVariableTypeTableBciP.add(start);
|
|
codeLocalVariableTypeTableSpanO.add(end);
|
|
codeLocalVariableTypeTableNameRU.add(cpBands.getCPUtf8(name));
|
|
codeLocalVariableTypeTableTypeRS.add(cpBands
|
|
.getCPSignature(signature));
|
|
codeLocalVariableTypeTableSlot.add(indx);
|
|
}
|
|
// LocalVariableTable attribute
|
|
codeLocalVariableTableN
|
|
.increment(codeLocalVariableTableN.size() - 1);
|
|
codeLocalVariableTableBciP.add(start);
|
|
codeLocalVariableTableSpanO.add(end);
|
|
codeLocalVariableTableNameRU.add(cpBands.getCPUtf8(name));
|
|
codeLocalVariableTableTypeRS.add(cpBands.getCPSignature(desc));
|
|
codeLocalVariableTableSlot.add(indx);
|
|
}
|
|
|
|
public void doBciRenumbering(IntList bciRenumbering, Map labelsToOffsets) {
|
|
renumberBci(codeLineNumberTableBciP, bciRenumbering, labelsToOffsets);
|
|
renumberBci(codeLocalVariableTableBciP, bciRenumbering, labelsToOffsets);
|
|
renumberOffsetBci(codeLocalVariableTableBciP,
|
|
codeLocalVariableTableSpanO, bciRenumbering, labelsToOffsets);
|
|
renumberBci(codeLocalVariableTypeTableBciP, bciRenumbering,
|
|
labelsToOffsets);
|
|
renumberOffsetBci(codeLocalVariableTypeTableBciP,
|
|
codeLocalVariableTypeTableSpanO, bciRenumbering,
|
|
labelsToOffsets);
|
|
renumberBci(codeHandlerStartP, bciRenumbering, labelsToOffsets);
|
|
renumberOffsetBci(codeHandlerStartP, codeHandlerEndPO,
|
|
bciRenumbering, labelsToOffsets);
|
|
renumberDoubleOffsetBci(codeHandlerStartP, codeHandlerEndPO, codeHandlerCatchPO,
|
|
bciRenumbering, labelsToOffsets);
|
|
|
|
for (Iterator iterator = classAttributeBands.iterator(); iterator.hasNext();) {
|
|
NewAttributeBands newAttributeBandSet = (NewAttributeBands) iterator.next();
|
|
newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
|
|
}
|
|
for (Iterator iterator = methodAttributeBands.iterator(); iterator.hasNext();) {
|
|
NewAttributeBands newAttributeBandSet = (NewAttributeBands) iterator.next();
|
|
newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
|
|
}
|
|
for (Iterator iterator = fieldAttributeBands.iterator(); iterator.hasNext();) {
|
|
NewAttributeBands newAttributeBandSet = (NewAttributeBands) iterator.next();
|
|
newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
|
|
}
|
|
for (Iterator iterator = codeAttributeBands.iterator(); iterator.hasNext();) {
|
|
NewAttributeBands newAttributeBandSet = (NewAttributeBands) iterator.next();
|
|
newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
|
|
}
|
|
}
|
|
|
|
private void renumberBci(List list, IntList bciRenumbering, Map labelsToOffsets) {
|
|
for (int i = list.size() - 1; i >= 0; i--) {
|
|
Object label = list.get(i);
|
|
if (label instanceof Integer) {
|
|
break;
|
|
} else if (label instanceof Label) {
|
|
list.remove(i);
|
|
Integer bytecodeIndex = (Integer) labelsToOffsets.get(label);
|
|
list.add(i, new Integer(bciRenumbering.get(bytecodeIndex.intValue())));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void renumberOffsetBci(List relative, List list,
|
|
IntList bciRenumbering, Map labelsToOffsets) {
|
|
for (int i = list.size() - 1; i >= 0; i--) {
|
|
Object label = list.get(i);
|
|
if (label instanceof Integer) {
|
|
break;
|
|
} else if (label instanceof Label) {
|
|
list.remove(i);
|
|
Integer bytecodeIndex = (Integer) labelsToOffsets.get(label);
|
|
Integer renumberedOffset = new Integer(bciRenumbering
|
|
.get(bytecodeIndex.intValue())
|
|
- ((Integer) relative.get(i)).intValue());
|
|
list.add(i, renumberedOffset);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void renumberDoubleOffsetBci(List relative, List firstOffset, List list,
|
|
IntList bciRenumbering, Map labelsToOffsets) {
|
|
// TODO: There's probably a nicer way of doing this...
|
|
for (int i = list.size() - 1; i >= 0; i--) {
|
|
Object label = list.get(i);
|
|
if (label instanceof Integer) {
|
|
break;
|
|
} else if (label instanceof Label) {
|
|
list.remove(i);
|
|
Integer bytecodeIndex = (Integer) labelsToOffsets.get(label);
|
|
Integer renumberedOffset = new Integer(bciRenumbering
|
|
.get(bytecodeIndex.intValue())
|
|
- ((Integer) relative.get(i)).intValue() - ((Integer) firstOffset.get(i)).intValue());
|
|
list.add(i, renumberedOffset);
|
|
}
|
|
}
|
|
}
|
|
|
|
public boolean isAnySyntheticClasses() {
|
|
return anySyntheticClasses;
|
|
}
|
|
|
|
public boolean isAnySyntheticFields() {
|
|
return anySyntheticFields;
|
|
}
|
|
|
|
public boolean isAnySyntheticMethods() {
|
|
return anySyntheticMethods;
|
|
}
|
|
|
|
public void addParameterAnnotation(int parameter, String desc,
|
|
boolean visible, List nameRU, List t, List values, List caseArrayN, List nestTypeRS, List nestNameRU, List nestPairN) {
|
|
if(visible) {
|
|
if(tempMethodRVPA == null) {
|
|
tempMethodRVPA = new TempParamAnnotation(numMethodArgs);
|
|
tempMethodRVPA.addParameterAnnotation(parameter, desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
|
|
}
|
|
Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1);
|
|
tempMethodFlags.add(new Long(flag.longValue() | (1<<23)));
|
|
} else {
|
|
if(tempMethodRIPA == null) {
|
|
tempMethodRIPA = new TempParamAnnotation(numMethodArgs);
|
|
tempMethodRIPA.addParameterAnnotation(parameter, desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
|
|
}
|
|
Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1);
|
|
tempMethodFlags.add(new Long(flag.longValue() | (1<<24)));
|
|
}
|
|
}
|
|
|
|
private static class TempParamAnnotation {
|
|
|
|
int numParams;
|
|
int[] annoN;
|
|
IntList pairN = new IntList();
|
|
List typeRS = new ArrayList();
|
|
List nameRU = new ArrayList();
|
|
List t = new ArrayList();
|
|
List values = new ArrayList();
|
|
List caseArrayN = new ArrayList();
|
|
List nestTypeRS = new ArrayList();
|
|
List nestNameRU = new ArrayList();
|
|
List nestPairN = new ArrayList();
|
|
|
|
public TempParamAnnotation (int numParams) {
|
|
this.numParams = numParams;
|
|
annoN = new int[numParams];
|
|
}
|
|
|
|
public void addParameterAnnotation(int parameter, String desc,
|
|
List nameRU, List t, List values, List caseArrayN,
|
|
List nestTypeRS, List nestNameRU, List nestPairN) {
|
|
annoN[parameter]++;
|
|
typeRS.add(desc);
|
|
pairN.add(nameRU.size());
|
|
this.nameRU.addAll(nameRU);
|
|
this.t.addAll(t);
|
|
this.values.addAll(values);
|
|
this.caseArrayN.addAll(caseArrayN);
|
|
this.nestTypeRS.addAll(nestTypeRS);
|
|
this.nestNameRU.addAll(nestNameRU);
|
|
this.nestPairN.addAll(nestPairN);
|
|
}
|
|
}
|
|
|
|
public void addAnnotation(int context, String desc, boolean visible, List nameRU, List t, List values, List caseArrayN, List nestTypeRS, List nestNameRU, List nestPairN) {
|
|
switch (context) {
|
|
case MetadataBandGroup.CONTEXT_CLASS:
|
|
if(visible) {
|
|
class_RVA_bands.addAnnotation(desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
|
|
if((class_flags[index] & (1<<21)) != 0) {
|
|
class_RVA_bands.incrementAnnoN();
|
|
} else {
|
|
class_RVA_bands.newEntryInAnnoN();
|
|
class_flags[index] = class_flags[index] | (1<<21);
|
|
}
|
|
} else {
|
|
class_RIA_bands.addAnnotation(desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
|
|
if((class_flags[index] & (1<<22)) != 0) {
|
|
class_RIA_bands.incrementAnnoN();
|
|
} else {
|
|
class_RIA_bands.newEntryInAnnoN();
|
|
class_flags[index] = class_flags[index] | (1<<22);
|
|
}
|
|
}
|
|
break;
|
|
case MetadataBandGroup.CONTEXT_FIELD:
|
|
if(visible) {
|
|
field_RVA_bands.addAnnotation(desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
|
|
Long flag = (Long) tempFieldFlags.remove(tempFieldFlags.size() - 1);
|
|
if((flag.intValue() & (1<<21)) != 0) {
|
|
field_RVA_bands.incrementAnnoN();
|
|
} else {
|
|
field_RVA_bands.newEntryInAnnoN();
|
|
}
|
|
tempFieldFlags.add(new Long(flag.intValue() | (1<<21)));
|
|
} else {
|
|
field_RIA_bands.addAnnotation(desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
|
|
Long flag = (Long) tempFieldFlags.remove(tempFieldFlags.size() - 1);
|
|
if((flag.intValue() & (1<<22)) != 0) {
|
|
field_RIA_bands.incrementAnnoN();
|
|
} else {
|
|
field_RIA_bands.newEntryInAnnoN();
|
|
}
|
|
tempFieldFlags.add(new Long(flag.intValue() | (1<<22)));
|
|
}
|
|
break;
|
|
case MetadataBandGroup.CONTEXT_METHOD:
|
|
if(visible) {
|
|
method_RVA_bands.addAnnotation(desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
|
|
Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1);
|
|
if((flag.intValue() & (1<<21)) != 0) {
|
|
method_RVA_bands.incrementAnnoN();
|
|
} else {
|
|
method_RVA_bands.newEntryInAnnoN();
|
|
}
|
|
tempMethodFlags.add(new Long(flag.intValue() | (1<<21)));
|
|
} else {
|
|
method_RIA_bands.addAnnotation(desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
|
|
Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1);
|
|
if((flag.intValue() & (1<<22)) != 0) {
|
|
method_RIA_bands.incrementAnnoN();
|
|
} else {
|
|
method_RIA_bands.newEntryInAnnoN();
|
|
}
|
|
tempMethodFlags.add(new Long(flag.intValue() | (1<<22)));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void addAnnotationDefault(List nameRU, List t, List values, List caseArrayN, List nestTypeRS, List nestNameRU, List nestPairN) {
|
|
method_AD_bands.addAnnotation(null, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
|
|
Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1);
|
|
tempMethodFlags.add(new Long(flag.longValue() | (1<<25)));
|
|
}
|
|
|
|
/**
|
|
* Remove all entries for the current class
|
|
*/
|
|
public void removeCurrentClass() {
|
|
// Note - this doesn't remove any entries added to the constant pool but
|
|
// that shouldn't be a problem
|
|
if ((class_flags[index] & (1 << 17)) != 0) {
|
|
classSourceFile.remove(classSourceFile.size() - 1);
|
|
}
|
|
if ((class_flags[index] & (1 << 18)) != 0) {
|
|
classEnclosingMethodClass
|
|
.remove(classEnclosingMethodClass.size() - 1);
|
|
classEnclosingMethodDesc
|
|
.remove(classEnclosingMethodDesc.size() - 1);
|
|
}
|
|
if ((class_flags[index] & (1 << 19)) != 0) {
|
|
classSignature.remove(classSignature.size() - 1);
|
|
}
|
|
if ((class_flags[index] & (1 << 21)) != 0) {
|
|
class_RVA_bands.removeLatest();
|
|
}
|
|
if ((class_flags[index] & (1 << 22)) != 0) {
|
|
class_RIA_bands.removeLatest();
|
|
}
|
|
for (Iterator iterator = tempFieldFlags.iterator(); iterator.hasNext();) {
|
|
Long flagsL = (Long) iterator.next();
|
|
long flags = flagsL.longValue();
|
|
if ((flags & (1 << 19)) != 0) {
|
|
fieldSignature.remove(fieldSignature.size() - 1);
|
|
}
|
|
if ((flags & (1 << 17)) != 0) {
|
|
fieldConstantValueKQ.remove(fieldConstantValueKQ.size() - 1);
|
|
}
|
|
if ((flags & (1 << 21)) != 0) {
|
|
field_RVA_bands.removeLatest();
|
|
}
|
|
if ((flags & (1 << 22)) != 0) {
|
|
field_RIA_bands.removeLatest();
|
|
}
|
|
}
|
|
for (Iterator iterator = tempMethodFlags.iterator(); iterator.hasNext();) {
|
|
Long flagsL = (Long) iterator.next();
|
|
long flags = flagsL.longValue();
|
|
if ((flags & (1 << 19)) != 0) {
|
|
methodSignature.remove(methodSignature.size() - 1);
|
|
}
|
|
if ((flags & (1 << 18)) != 0) {
|
|
int exceptions = methodExceptionNumber
|
|
.remove(methodExceptionNumber.size() - 1);
|
|
for (int i = 0; i < exceptions; i++) {
|
|
methodExceptionClasses
|
|
.remove(methodExceptionClasses.size() - 1);
|
|
}
|
|
}
|
|
if ((flags & (1 << 17)) != 0) { // has code attribute
|
|
codeMaxLocals.remove(codeMaxLocals.size() - 1);
|
|
codeMaxStack.remove(codeMaxStack.size() - 1);
|
|
int handlers = codeHandlerCount
|
|
.remove(codeHandlerCount.size() - 1);
|
|
for (int i = 0; i < handlers; i++) {
|
|
int index = codeHandlerStartP.size() - 1;
|
|
codeHandlerStartP.remove(index);
|
|
codeHandlerEndPO.remove(index);
|
|
codeHandlerCatchPO.remove(index);
|
|
codeHandlerClass.remove(index);
|
|
}
|
|
if (!stripDebug) {
|
|
long cdeFlags = ((Long) codeFlags
|
|
.remove(codeFlags.size() - 1)).longValue();
|
|
int numLocalVariables = codeLocalVariableTableN
|
|
.remove(codeLocalVariableTableN.size() - 1);
|
|
for (int i = 0; i < numLocalVariables; i++) {
|
|
int location = codeLocalVariableTableBciP.size() - 1;
|
|
codeLocalVariableTableBciP.remove(location);
|
|
codeLocalVariableTableSpanO.remove(location);
|
|
codeLocalVariableTableNameRU.remove(location);
|
|
codeLocalVariableTableTypeRS.remove(location);
|
|
codeLocalVariableTableSlot.remove(location);
|
|
}
|
|
if ((cdeFlags & (1 << 3)) != 0) {
|
|
int numLocalVariablesInTypeTable = codeLocalVariableTypeTableN
|
|
.remove(codeLocalVariableTypeTableN.size() - 1);
|
|
for (int i = 0; i < numLocalVariablesInTypeTable; i++) {
|
|
int location = codeLocalVariableTypeTableBciP
|
|
.size() - 1;
|
|
codeLocalVariableTypeTableBciP.remove(location);
|
|
codeLocalVariableTypeTableSpanO.remove(location);
|
|
codeLocalVariableTypeTableNameRU.remove(location);
|
|
codeLocalVariableTypeTableTypeRS.remove(location);
|
|
codeLocalVariableTypeTableSlot.remove(location);
|
|
}
|
|
}
|
|
if ((cdeFlags & (1 << 1)) != 0) {
|
|
int numLineNumbers = codeLineNumberTableN
|
|
.remove(codeLineNumberTableN.size() - 1);
|
|
for (int i = 0; i < numLineNumbers; i++) {
|
|
int location = codeLineNumberTableBciP.size() - 1;
|
|
codeLineNumberTableBciP.remove(location);
|
|
codeLineNumberTableLine.remove(location);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ((flags & (1 << 21)) != 0) {
|
|
method_RVA_bands.removeLatest();
|
|
}
|
|
if ((flags & (1 << 22)) != 0) {
|
|
method_RIA_bands.removeLatest();
|
|
}
|
|
if ((flags & (1 << 23)) != 0) {
|
|
method_RVPA_bands.removeLatest();
|
|
}
|
|
if ((flags & (1 << 24)) != 0) {
|
|
method_RIPA_bands.removeLatest();
|
|
}
|
|
if ((flags & (1 << 25)) != 0) {
|
|
method_AD_bands.removeLatest();
|
|
}
|
|
}
|
|
class_this[index] = null;
|
|
class_super[index] = null;
|
|
class_interface_count[index] = 0;
|
|
class_interface[index] = null;
|
|
major_versions[index] = 0;
|
|
class_flags[index] = 0;
|
|
tempFieldDesc.clear();
|
|
tempFieldFlags.clear();
|
|
tempMethodDesc.clear();
|
|
tempMethodFlags.clear();
|
|
if(index > 0) {
|
|
index--;
|
|
}
|
|
}
|
|
|
|
public int numClassesProcessed() {
|
|
return index;
|
|
}
|
|
}
|
|
|