1. Support for generation tableswitch code

2. Utility method addLoadThis() as an alias for add(ByteCode.ALOAD_0)
This commit is contained in:
igor%mir2.org 2003-08-26 15:43:11 +00:00
Родитель 54b6ac62e1
Коммит 856b7cabb4
1 изменённых файлов: 119 добавлений и 18 удалений

Просмотреть файл

@ -68,6 +68,7 @@ public class ClassFileWriter {
public ClassFileWriter(String className, String superClassName,
String sourceFileName)
{
generatedClassName = className;
itsConstantPool = new ConstantPool(this);
itsThisClassIndex = itsConstantPool.addClass(className);
itsSuperClassIndex = itsConstantPool.addClass(superClassName);
@ -75,6 +76,11 @@ public class ClassFileWriter {
itsSourceFileNameIndex = itsConstantPool.addUtf8(sourceFileName);
itsFlags = ACC_PUBLIC;
}
public final String getClassName()
{
return generatedClassName;
}
/**
* Add an interface implemented by this class.
@ -130,11 +136,11 @@ public class ClassFileWriter {
* "Lname-with-dots-replaced-by-slashes;" form suitable for use as
* JVM type signatures.
*/
public String classNameToSignature(String name)
public static String classNameToSignature(String name)
{
int nameLength = name.length();
int colonPos = 1 + nameLength;
char[] buf = getCharBuffer(colonPos + 1);
char[] buf = new char[colonPos + 1];
buf[0] = 'L';
buf[colonPos] = ';';
name.getChars(0, nameLength, buf, 1);
@ -985,6 +991,14 @@ public class ClassFileWriter {
xop(ByteCode.ALOAD_0, ByteCode.ALOAD, local);
}
/**
* Load "this" into stack.
*/
public void addLoadThis()
{
add(ByteCode.ALOAD_0);
}
private void xop(byte shortOp, byte op, int local)
{
switch (local) {
@ -1005,6 +1019,89 @@ public class ClassFileWriter {
}
}
public int addTableSwitch(int low, int high)
{
if (DEBUGCODE) {
System.out.println("Add "+bytecodeStr(ByteCode.TABLESWITCH)
+" "+low+" "+high);
}
if (low > high)
throw new IllegalArgumentException("Bad bounds: "+low+' '+ high);
int newStack = itsStackTop + stackChange(ByteCode.TABLESWITCH);
if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack);
int entryCount = high - low + 1;
int padSize = 3 & ~itsCodeBufferTop; // == 3 - itsCodeBufferTop % 4
int N = addReservedCodeSpace(1 + padSize + 4 * (1 + 2 + entryCount));
int switchStart = N;
itsCodeBuffer[N++] = ByteCode.TABLESWITCH;
while (padSize != 0) {
itsCodeBuffer[N++] = 0;
--padSize;
}
N += 4; // skip default offset
N = putInt32(low, itsCodeBuffer, N);
putInt32(high, itsCodeBuffer, N);
itsStackTop = (short)newStack;
if (newStack > itsMaxStack) itsMaxStack = (short)newStack;
if (DEBUGSTACK) {
System.out.println("After "+bytecodeStr(ByteCode.TABLESWITCH)
+" stack = "+itsStackTop);
}
return switchStart;
}
public final void markTableSwitchDefault(int switchStart)
{
setTableSwitchJump(switchStart, -1, itsCodeBufferTop);
}
public final void markTableSwitchCase(int switchStart, int caseIndex)
{
setTableSwitchJump(switchStart, caseIndex, itsCodeBufferTop);
}
public void setTableSwitchJump(int switchStart, int caseIndex,
int jumpTarget)
{
if (!(0 <= jumpTarget && jumpTarget <= itsCodeBufferTop))
throw new IllegalArgumentException("Bad jump target: "+jumpTarget);
if (!(caseIndex >= -1))
throw new IllegalArgumentException("Bad case index: "+caseIndex);
int padSize = 3 & ~switchStart; // == 3 - switchStart % 4
int caseOffset;
if (caseIndex < 0) {
// default label
caseOffset = switchStart + 1 + padSize;
} else {
caseOffset = switchStart + 1 + padSize + 4 * (3 + caseIndex);
}
if (!(0 <= switchStart
&& switchStart <= itsCodeBufferTop - 4 * 4 - padSize - 1))
{
throw new IllegalArgumentException(
switchStart+" is outside a possible range of tableswitch"
+" in already generated code");
}
if (!(itsCodeBuffer[switchStart] == ByteCode.TABLESWITCH)) {
throw new IllegalArgumentException(
switchStart+" is not offset of tableswitch statement");
}
if (!(0 <= caseOffset && caseOffset + 4 <= itsCodeBufferTop)) {
// caseIndex >= -1 does not guarantee that caseOffset >= 0 due
// to a possible overflow.
throw new IllegalArgumentException(
"Too big case index: "+caseIndex);
}
// ALERT: perhaps check against case bounds?
putInt32(jumpTarget - switchStart, itsCodeBuffer, caseOffset);
}
public int acquireLabel() {
return itsLabels.acquireLabel() | 0x80000000;
}
@ -1053,31 +1150,33 @@ public class ClassFileWriter {
}
}
private void addToCodeBuffer(byte b) {
if (itsCurrentMethod == null)
throw new IllegalArgumentException("No method to add to");
int N = itsCodeBufferTop;
if (N == itsCodeBuffer.length) {
byte[] tmp = new byte[N * 2];
System.arraycopy(itsCodeBuffer, 0, tmp, 0, N);
itsCodeBuffer = tmp;
}
private void addToCodeBuffer(byte b)
{
int N = addReservedCodeSpace(1);
itsCodeBuffer[N] = b;
itsCodeBufferTop = N + 1;
}
private void addToCodeInt16(int value) {
private void addToCodeInt16(int value)
{
int N = addReservedCodeSpace(2);
putInt16(value, itsCodeBuffer, N);
}
private int addReservedCodeSpace(int size)
{
if (itsCurrentMethod == null)
throw new IllegalArgumentException("No method to add to");
int N = itsCodeBufferTop;
if (N + 2 > itsCodeBuffer.length) {
int oldTop = itsCodeBufferTop;
int newTop = oldTop + size;
if (newTop > itsCodeBuffer.length) {
int newSize = itsCodeBuffer.length * 2;
if (N + 2 > newSize) { newSize = N + 2; }
if (newTop > newSize) { newSize = newTop; }
byte[] tmp = new byte[newSize];
System.arraycopy(itsCodeBuffer, 0, tmp, 0, N);
System.arraycopy(itsCodeBuffer, 0, tmp, 0, oldTop);
itsCodeBuffer = tmp;
}
itsCodeBufferTop = putInt16(value, itsCodeBuffer, N);
itsCodeBufferTop = newTop;
return oldTop;
}
public void addExceptionHandler(int startLabel, int endLabel,
@ -2287,6 +2386,8 @@ public class ClassFileWriter {
private static final boolean DEBUGLABELS = false;
private static final boolean DEBUGCODE = false;
private static final int CodeBufferSize = 128;
private String generatedClassName;
private ExceptionTableEntry itsExceptionTable[];
private int itsExceptionTableTop;