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.
583 lines
22 KiB
583 lines
22 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.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
import org.objectweb.asm.Label;
|
|
|
|
/**
|
|
* Bytecode bands (corresponds to the <code>bc_bands</code> set of bands in the
|
|
* pack200 specification)
|
|
*/
|
|
public class BcBands extends BandSet {
|
|
|
|
private final CpBands cpBands;
|
|
private final Segment segment;
|
|
|
|
public BcBands(CpBands cpBands, Segment segment, int effort) {
|
|
super(effort, segment.getSegmentHeader());
|
|
this.cpBands = cpBands;
|
|
this.segment = segment;
|
|
}
|
|
|
|
private final IntList bcCodes = new IntList();
|
|
private final IntList bcCaseCount = new IntList();
|
|
private final IntList bcCaseValue = new IntList();
|
|
private final IntList bcByte = new IntList();
|
|
private final IntList bcShort = new IntList();
|
|
private final IntList bcLocal = new IntList();
|
|
private final List bcLabel = new ArrayList();
|
|
private final List bcIntref = new ArrayList();
|
|
private final List bcFloatRef = new ArrayList();
|
|
private final List bcLongRef = new ArrayList();
|
|
private final List bcDoubleRef = new ArrayList();
|
|
private final List bcStringRef = new ArrayList();
|
|
private final List bcClassRef = new ArrayList();
|
|
private final List bcFieldRef = new ArrayList();
|
|
private final List bcMethodRef = new ArrayList();
|
|
private final List bcIMethodRef = new ArrayList();
|
|
private List bcThisField = new ArrayList();
|
|
private final List bcSuperField = new ArrayList();
|
|
private List bcThisMethod = new ArrayList();
|
|
private List bcSuperMethod = new ArrayList();
|
|
private List bcInitRef = new ArrayList();
|
|
|
|
private String currentClass;
|
|
private String superClass;
|
|
private String currentNewClass;
|
|
|
|
private static final int MULTIANEWARRAY = 197;
|
|
private static final int ALOAD_0 = 42;
|
|
private static final int WIDE = 196;
|
|
private static final int INVOKEINTERFACE = 185;
|
|
private static final int TABLESWITCH = 170;
|
|
private static final int IINC = 132;
|
|
private static final int LOOKUPSWITCH = 171;
|
|
private static final int endMarker = 255;
|
|
|
|
private final IntList bciRenumbering = new IntList();
|
|
private final Map labelsToOffsets = new HashMap();
|
|
private int byteCodeOffset;
|
|
private int renumberedOffset;
|
|
private final IntList bcLabelRelativeOffsets = new IntList();
|
|
|
|
public void setCurrentClass(String name, String superName) {
|
|
currentClass = name;
|
|
superClass = superName;
|
|
}
|
|
|
|
/**
|
|
* 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() {
|
|
bcThisField = getIndexInClass(bcThisField);
|
|
bcThisMethod = getIndexInClass(bcThisMethod);
|
|
bcSuperMethod = getIndexInClass(bcSuperMethod);
|
|
bcInitRef = getIndexInClassForConstructor(bcInitRef);
|
|
}
|
|
|
|
public void pack(OutputStream out) throws IOException, Pack200Exception {
|
|
PackingUtils.log("Writing byte code bands...");
|
|
byte[] encodedBand = encodeBandInt("bcCodes", bcCodes.toArray(),
|
|
Codec.BYTE1);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length + " bytes from bcCodes["
|
|
+ bcCodes.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcCaseCount", bcCaseCount.toArray(),
|
|
Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from bcCaseCount[" + bcCaseCount.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcCaseValue", bcCaseValue.toArray(),
|
|
Codec.DELTA5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from bcCaseValue[" + bcCaseValue.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcByte", bcByte.toArray(), Codec.BYTE1);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length + " bytes from bcByte["
|
|
+ bcByte.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcShort", bcShort.toArray(), Codec.DELTA5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length + " bytes from bcShort["
|
|
+ bcShort.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcLocal", bcLocal.toArray(),
|
|
Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length + " bytes from bcLocal["
|
|
+ bcLocal.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcLabel", integerListToArray(bcLabel),
|
|
Codec.BRANCH5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length + " bytes from bcLabel["
|
|
+ bcLabel.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcIntref", cpEntryListToArray(bcIntref),
|
|
Codec.DELTA5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from bcIntref[" + bcIntref.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcFloatRef",
|
|
cpEntryListToArray(bcFloatRef), Codec.DELTA5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from bcFloatRef[" + bcFloatRef.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcLongRef", cpEntryListToArray(bcLongRef),
|
|
Codec.DELTA5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from bcLongRef[" + bcLongRef.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcDoubleRef",
|
|
cpEntryListToArray(bcDoubleRef), Codec.DELTA5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from bcDoubleRef[" + bcDoubleRef.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcStringRef",
|
|
cpEntryListToArray(bcStringRef), Codec.DELTA5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from bcStringRef[" + bcStringRef.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcClassRef",
|
|
cpEntryOrNullListToArray(bcClassRef), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from bcClassRef[" + bcClassRef.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcFieldRef",
|
|
cpEntryListToArray(bcFieldRef), Codec.DELTA5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from bcFieldRef[" + bcFieldRef.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcMethodRef",
|
|
cpEntryListToArray(bcMethodRef), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from bcMethodRef[" + bcMethodRef.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcIMethodRef",
|
|
cpEntryListToArray(bcIMethodRef), Codec.DELTA5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from bcIMethodRef[" + bcIMethodRef.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcThisField",
|
|
integerListToArray(bcThisField), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from bcThisField[" + bcThisField.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcSuperField",
|
|
integerListToArray(bcSuperField), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from bcSuperField[" + bcSuperField.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcThisMethod",
|
|
integerListToArray(bcThisMethod), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from bcThisMethod[" + bcThisMethod.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcSuperMethod",
|
|
integerListToArray(bcSuperMethod), Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from bcSuperMethod[" + bcSuperMethod.size() + "]");
|
|
|
|
encodedBand = encodeBandInt("bcInitRef", integerListToArray(bcInitRef),
|
|
Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from bcInitRef[" + bcInitRef.size() + "]");
|
|
|
|
// out.write(encodeBandInt(cpEntryintegerListToArray(bcEscRef),
|
|
// Codec.UNSIGNED5));
|
|
// out.write(encodeBandInt(integerListToArray(bcEscRefSize),
|
|
// Codec.UNSIGNED5));
|
|
// out.write(encodeBandInt(integerListToArray(bcEscSize),
|
|
// Codec.UNSIGNED5));
|
|
// out.write(encodeBandInt(integerListToArray(bcEscByte), Codec.BYTE1));
|
|
}
|
|
|
|
private List getIndexInClass(List cPMethodOrFieldList) {
|
|
List indices = new ArrayList(cPMethodOrFieldList.size());
|
|
for (int i = 0; i < cPMethodOrFieldList.size(); i++) {
|
|
CPMethodOrField cpMF = (CPMethodOrField) cPMethodOrFieldList.get(i);
|
|
indices.add(new Integer(cpMF.getIndexInClass()));
|
|
}
|
|
return indices;
|
|
}
|
|
|
|
private List getIndexInClassForConstructor(List cPMethodList) {
|
|
List indices = new ArrayList(cPMethodList.size());
|
|
for (int i = 0; i < cPMethodList.size(); i++) {
|
|
CPMethodOrField cpMF = (CPMethodOrField) cPMethodList.get(i);
|
|
indices.add(new Integer(cpMF.getIndexInClassForConstructor()));
|
|
}
|
|
return indices;
|
|
}
|
|
|
|
public void visitEnd() {
|
|
for (int i = 0; i < bciRenumbering.size(); i++) {
|
|
if (bciRenumbering.get(i) == -1) {
|
|
bciRenumbering.remove(i);
|
|
bciRenumbering.add(i, ++renumberedOffset);
|
|
}
|
|
}
|
|
if (renumberedOffset != 0) {
|
|
if(renumberedOffset + 1 != bciRenumbering.size()) {
|
|
throw new RuntimeException("Mistake made with renumbering");
|
|
}
|
|
for (int i = bcLabel.size() - 1; i >= 0; i--) {
|
|
Object label = bcLabel.get(i);
|
|
if (label instanceof Integer) {
|
|
break;
|
|
} else if (label instanceof Label) {
|
|
bcLabel.remove(i);
|
|
Integer offset = (Integer) labelsToOffsets.get(label);
|
|
int relativeOffset = bcLabelRelativeOffsets.get(i);
|
|
bcLabel.add(i, new Integer(bciRenumbering.get(offset.intValue()) - bciRenumbering.get(relativeOffset)));
|
|
}
|
|
}
|
|
bcCodes.add(endMarker);
|
|
segment.getClassBands().doBciRenumbering(bciRenumbering,
|
|
labelsToOffsets);
|
|
bciRenumbering.clear();
|
|
labelsToOffsets.clear();
|
|
byteCodeOffset = 0;
|
|
renumberedOffset = 0;
|
|
}
|
|
}
|
|
|
|
public void visitLabel(Label label) {
|
|
labelsToOffsets.put(label, new Integer(byteCodeOffset));
|
|
}
|
|
|
|
public void visitFieldInsn(int opcode, String owner, String name,
|
|
String desc) {
|
|
byteCodeOffset += 3;
|
|
updateRenumbering();
|
|
boolean aload_0 = false;
|
|
if (bcCodes.size() > 0
|
|
&& (bcCodes.get(bcCodes.size() - 1)) == ALOAD_0) {
|
|
bcCodes.remove(bcCodes.size() - 1);
|
|
aload_0 = true;
|
|
}
|
|
CPMethodOrField cpField = cpBands.getCPField(owner, name, desc);
|
|
if (aload_0) {
|
|
opcode += 7;
|
|
}
|
|
if (owner.equals(currentClass)) {
|
|
opcode += 24; // change to getstatic_this, putstatic_this etc.
|
|
bcThisField.add(cpField);
|
|
// } else if (owner.equals(superClass)) {
|
|
// opcode += 38; // change to getstatic_super etc.
|
|
// bcSuperField.add(cpField);
|
|
} else {
|
|
if (aload_0) {
|
|
opcode -= 7;
|
|
bcCodes.add(ALOAD_0); // add aload_0 back in because
|
|
// there's no special rewrite in
|
|
// this case.
|
|
}
|
|
bcFieldRef.add(cpField);
|
|
}
|
|
aload_0 = false;
|
|
bcCodes.add(opcode);
|
|
}
|
|
|
|
private void updateRenumbering() {
|
|
if(bciRenumbering.isEmpty()) {
|
|
bciRenumbering.add(0);
|
|
}
|
|
renumberedOffset ++;
|
|
for (int i = bciRenumbering.size(); i < byteCodeOffset; i++) {
|
|
bciRenumbering.add(-1);
|
|
}
|
|
bciRenumbering.add(renumberedOffset);
|
|
}
|
|
|
|
public void visitIincInsn(int var, int increment) {
|
|
if (var > 255 || increment > 255) {
|
|
byteCodeOffset += 6;
|
|
bcCodes.add(WIDE);
|
|
bcCodes.add(IINC);
|
|
bcLocal.add(var);
|
|
bcShort.add(increment);
|
|
} else {
|
|
byteCodeOffset += 3;
|
|
bcCodes.add(IINC);
|
|
bcLocal.add(var);
|
|
bcByte.add(increment & 0xFF);
|
|
}
|
|
updateRenumbering();
|
|
}
|
|
|
|
public void visitInsn(int opcode) {
|
|
if (opcode >= 202) {
|
|
throw new RuntimeException(
|
|
"Non-standard bytecode instructions not supported");
|
|
} else {
|
|
bcCodes.add(opcode);
|
|
byteCodeOffset++;
|
|
updateRenumbering();
|
|
}
|
|
}
|
|
|
|
public void visitIntInsn(int opcode, int operand) {
|
|
switch (opcode) {
|
|
case 17: // sipush
|
|
bcCodes.add(opcode);
|
|
bcShort.add(operand);
|
|
byteCodeOffset += 3;
|
|
break;
|
|
case 16: // bipush
|
|
case 188: // newarray
|
|
bcCodes.add(opcode);
|
|
bcByte.add(operand & 0xFF);
|
|
byteCodeOffset += 2;
|
|
}
|
|
updateRenumbering();
|
|
}
|
|
|
|
public void visitJumpInsn(int opcode, Label label) {
|
|
bcCodes.add(opcode);
|
|
bcLabel.add(label);
|
|
bcLabelRelativeOffsets.add(byteCodeOffset);
|
|
byteCodeOffset += 3;
|
|
updateRenumbering();
|
|
}
|
|
|
|
public void visitLdcInsn(Object cst) {
|
|
CPConstant constant = cpBands.getConstant(cst);
|
|
if (segment.lastConstantHadWideIndex() || constant instanceof CPLong
|
|
|| constant instanceof CPDouble) {
|
|
byteCodeOffset += 3;
|
|
if (constant instanceof CPInt) {
|
|
bcCodes.add(237); // ildc_w
|
|
bcIntref.add(constant);
|
|
} else if (constant instanceof CPFloat) {
|
|
bcCodes.add(238); // fldc
|
|
bcFloatRef.add(constant);
|
|
} else if (constant instanceof CPLong) {
|
|
bcCodes.add(20); // lldc2_w
|
|
bcLongRef.add(constant);
|
|
} else if (constant instanceof CPDouble) {
|
|
bcCodes.add(239); // dldc2_w
|
|
bcDoubleRef.add(constant);
|
|
} else if (constant instanceof CPString) {
|
|
bcCodes.add(19); // aldc
|
|
bcStringRef.add(constant);
|
|
} else if (constant instanceof CPClass) {
|
|
bcCodes.add(236); // cldc
|
|
bcClassRef.add(constant);
|
|
} else {
|
|
throw new RuntimeException("Constant should not be null");
|
|
}
|
|
} else {
|
|
byteCodeOffset += 2;
|
|
if (constant instanceof CPInt) {
|
|
bcCodes.add(234); // ildc
|
|
bcIntref.add(constant);
|
|
} else if (constant instanceof CPFloat) {
|
|
bcCodes.add(235); // fldc
|
|
bcFloatRef.add(constant);
|
|
} else if (constant instanceof CPString) {
|
|
bcCodes.add(18); // aldc
|
|
bcStringRef.add(constant);
|
|
} else if (constant instanceof CPClass) {
|
|
bcCodes.add(233); // cldc
|
|
bcClassRef.add(constant);
|
|
}
|
|
}
|
|
updateRenumbering();
|
|
}
|
|
|
|
public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
|
|
bcCodes.add(LOOKUPSWITCH);
|
|
bcLabel.add(dflt);
|
|
bcLabelRelativeOffsets.add(byteCodeOffset);
|
|
bcCaseCount.add(keys.length);
|
|
for (int i = 0; i < labels.length; i++) {
|
|
bcCaseValue.add(keys[i]);
|
|
bcLabel.add(labels[i]);
|
|
bcLabelRelativeOffsets.add(byteCodeOffset);
|
|
}
|
|
int padding = (byteCodeOffset + 1) % 4 == 0 ? 0 : 4 - ((byteCodeOffset + 1) % 4);
|
|
byteCodeOffset += 1 + padding + 8 + 8 * keys.length;
|
|
updateRenumbering();
|
|
}
|
|
|
|
public void visitMethodInsn(int opcode, String owner, String name,
|
|
String desc) {
|
|
byteCodeOffset += 3;
|
|
switch (opcode) {
|
|
case 182: // invokevirtual
|
|
case 183: // invokespecial
|
|
case 184: // invokestatic
|
|
boolean aload_0 = false;
|
|
if (bcCodes.size() > 0
|
|
&& (bcCodes.get(bcCodes.size() - 1))
|
|
== (ALOAD_0)) {
|
|
bcCodes.remove(bcCodes.size() - 1);
|
|
aload_0 = true;
|
|
opcode += 7;
|
|
}
|
|
if (owner.equals(currentClass)) {
|
|
opcode += 24; // change to invokevirtual_this,
|
|
// invokespecial_this etc.
|
|
|
|
if(name.equals("<init>") && opcode == 207) {
|
|
opcode = 230; // invokespecial_this_init
|
|
bcInitRef.add(cpBands.getCPMethod(owner, name, desc));
|
|
} else {
|
|
bcThisMethod.add(cpBands.getCPMethod(owner, name, desc));
|
|
}
|
|
} else if (owner.equals(superClass)) { // TODO
|
|
opcode += 38; // change to invokevirtual_super,
|
|
// invokespecial_super etc.
|
|
if(name.equals("<init>") && opcode == 221) {
|
|
opcode = 231; // invokespecial_super_init
|
|
bcInitRef.add(cpBands.getCPMethod(owner, name, desc));
|
|
} else {
|
|
bcSuperMethod.add(cpBands.getCPMethod(owner, name, desc));
|
|
}
|
|
} else {
|
|
if (aload_0) {
|
|
opcode -= 7;
|
|
bcCodes.add(ALOAD_0); // add aload_0 back in
|
|
// because there's no
|
|
// special rewrite in this
|
|
// case.
|
|
}
|
|
if(name.equals("<init>") && opcode == 183 && owner.equals(currentNewClass)) {
|
|
opcode = 232; // invokespecial_new_init
|
|
bcInitRef.add(cpBands.getCPMethod(owner, name, desc));
|
|
} else {
|
|
bcMethodRef.add(cpBands.getCPMethod(owner, name, desc));
|
|
}
|
|
}
|
|
bcCodes.add(opcode);
|
|
break;
|
|
case 185: // invokeinterface
|
|
byteCodeOffset += 2;
|
|
CPMethodOrField cpIMethod = cpBands.getCPIMethod(owner, name, desc);
|
|
bcIMethodRef.add(cpIMethod);
|
|
bcCodes.add(INVOKEINTERFACE);
|
|
break;
|
|
}
|
|
updateRenumbering();
|
|
}
|
|
|
|
public void visitMultiANewArrayInsn(String desc, int dimensions) {
|
|
byteCodeOffset += 4;
|
|
updateRenumbering();
|
|
bcCodes.add(MULTIANEWARRAY);
|
|
bcClassRef.add(cpBands.getCPClass(desc));
|
|
bcByte.add(dimensions & 0xFF);
|
|
}
|
|
|
|
public void visitTableSwitchInsn(int min, int max, Label dflt,
|
|
Label[] labels) {
|
|
bcCodes.add(TABLESWITCH);
|
|
bcLabel.add(dflt);
|
|
bcLabelRelativeOffsets.add(byteCodeOffset);
|
|
bcCaseValue.add(min);
|
|
int count = labels.length;
|
|
bcCaseCount.add(count);
|
|
for (int i = 0; i < count; i++) {
|
|
bcLabel.add(labels[i]);
|
|
bcLabelRelativeOffsets.add(byteCodeOffset);
|
|
}
|
|
int padding = byteCodeOffset % 4 == 0 ? 0 : 4 - (byteCodeOffset % 4);
|
|
byteCodeOffset+= (padding + 12 + 4 * labels.length);
|
|
updateRenumbering();
|
|
}
|
|
|
|
public void visitTypeInsn(int opcode, String type) {
|
|
// NEW, ANEWARRAY, CHECKCAST or INSTANCEOF
|
|
byteCodeOffset += 3;
|
|
updateRenumbering();
|
|
bcCodes.add(opcode);
|
|
bcClassRef.add(cpBands.getCPClass(type));
|
|
if(opcode == 187) { // NEW
|
|
currentNewClass = type;
|
|
}
|
|
}
|
|
|
|
public void visitVarInsn(int opcode, int var) {
|
|
// ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET
|
|
if (var > 255) {
|
|
byteCodeOffset += 4;
|
|
bcCodes.add(WIDE);
|
|
bcCodes.add(opcode);
|
|
bcLocal.add(var);
|
|
} else {
|
|
if(var > 3 || opcode == 169 /* RET */) {
|
|
byteCodeOffset += 2;
|
|
bcCodes.add(opcode);
|
|
bcLocal.add(var);
|
|
} else {
|
|
byteCodeOffset +=1;
|
|
switch(opcode) {
|
|
case 21: // ILOAD
|
|
case 54: // ISTORE
|
|
bcCodes.add(opcode + 5 + var);
|
|
break;
|
|
case 22: // LLOAD
|
|
case 55: // LSTORE
|
|
bcCodes.add(opcode + 8 + var);
|
|
break;
|
|
case 23: // FLOAD
|
|
case 56: // FSTORE
|
|
bcCodes.add(opcode + 11 + var);
|
|
break;
|
|
case 24: // DLOAD
|
|
case 57: // DSTORE
|
|
bcCodes.add(opcode + 14 + var);
|
|
break;
|
|
case 25: // A_LOAD
|
|
case 58: // A_STORE
|
|
bcCodes.add(opcode + 17 + var);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
updateRenumbering();
|
|
}
|
|
|
|
}
|
|
|