in rhino/src/main/java/org/mozilla/classfile/ClassFileWriter.java [440:591]
public void add(int theOpCode, int theOperand) {
if (DEBUGCODE) {
System.out.println(
"Add " + bytecodeStr(theOpCode) + ", " + Integer.toHexString(theOperand));
}
int newStack = itsStackTop + stackChange(theOpCode);
if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack);
switch (theOpCode) {
case ByteCode.GOTO:
// This is necessary because dead code is seemingly being
// generated and Sun's verifier is expecting type state to be
// placed even at dead blocks of code.
addSuperBlockStart(itsCodeBufferTop + 3);
// fall through...
case ByteCode.IFEQ:
case ByteCode.IFNE:
case ByteCode.IFLT:
case ByteCode.IFGE:
case ByteCode.IFGT:
case ByteCode.IFLE:
case ByteCode.IF_ICMPEQ:
case ByteCode.IF_ICMPNE:
case ByteCode.IF_ICMPLT:
case ByteCode.IF_ICMPGE:
case ByteCode.IF_ICMPGT:
case ByteCode.IF_ICMPLE:
case ByteCode.IF_ACMPEQ:
case ByteCode.IF_ACMPNE:
case ByteCode.JSR:
case ByteCode.IFNULL:
case ByteCode.IFNONNULL:
{
if ((theOperand & 0x80000000) != 0x80000000) {
if ((theOperand < 0) || (theOperand > 65535))
throw new IllegalArgumentException("Bad label for branch");
}
int branchPC = itsCodeBufferTop;
addToCodeBuffer(theOpCode);
if ((theOperand & 0x80000000) != 0x80000000) {
// hard displacement
addToCodeInt16(theOperand);
int target = theOperand + branchPC;
addSuperBlockStart(target);
itsJumpFroms.put(target, branchPC);
} else { // a label
int targetPC = getLabelPC(theOperand);
if (DEBUGLABELS) {
int theLabel = theOperand & 0x7FFFFFFF;
System.out.println(
"Fixing branch to "
+ theLabel
+ " at "
+ targetPC
+ " from "
+ branchPC);
}
if (targetPC != -1) {
int offset = targetPC - branchPC;
addToCodeInt16(offset);
addSuperBlockStart(targetPC);
itsJumpFroms.put(targetPC, branchPC);
} else {
addLabelFixup(theOperand, branchPC + 1);
addToCodeInt16(0);
}
}
}
break;
case ByteCode.BIPUSH:
if ((byte) theOperand != theOperand)
throw new IllegalArgumentException("out of range byte");
addToCodeBuffer(theOpCode);
addToCodeBuffer((byte) theOperand);
break;
case ByteCode.SIPUSH:
if ((short) theOperand != theOperand)
throw new IllegalArgumentException("out of range short");
addToCodeBuffer(theOpCode);
addToCodeInt16(theOperand);
break;
case ByteCode.NEWARRAY:
if (!(0 <= theOperand && theOperand < 256))
throw new IllegalArgumentException("out of range index");
addToCodeBuffer(theOpCode);
addToCodeBuffer(theOperand);
break;
case ByteCode.GETFIELD:
case ByteCode.PUTFIELD:
if (!(0 <= theOperand && theOperand < 65536))
throw new IllegalArgumentException("out of range field");
addToCodeBuffer(theOpCode);
addToCodeInt16(theOperand);
break;
case ByteCode.LDC:
case ByteCode.LDC_W:
case ByteCode.LDC2_W:
if (!(0 <= theOperand && theOperand < 65536))
throw new ClassFileFormatException("out of range index");
if (theOperand >= 256
|| theOpCode == ByteCode.LDC_W
|| theOpCode == ByteCode.LDC2_W) {
if (theOpCode == ByteCode.LDC) {
addToCodeBuffer(ByteCode.LDC_W);
} else {
addToCodeBuffer(theOpCode);
}
addToCodeInt16(theOperand);
} else {
addToCodeBuffer(theOpCode);
addToCodeBuffer(theOperand);
}
break;
case ByteCode.RET:
case ByteCode.ILOAD:
case ByteCode.LLOAD:
case ByteCode.FLOAD:
case ByteCode.DLOAD:
case ByteCode.ALOAD:
case ByteCode.ISTORE:
case ByteCode.LSTORE:
case ByteCode.FSTORE:
case ByteCode.DSTORE:
case ByteCode.ASTORE:
if (theOperand < 0 || 65536 <= theOperand)
throw new ClassFileFormatException("out of range variable");
if (theOperand >= 256) {
addToCodeBuffer(ByteCode.WIDE);
addToCodeBuffer(theOpCode);
addToCodeInt16(theOperand);
} else {
addToCodeBuffer(theOpCode);
addToCodeBuffer(theOperand);
}
break;
default:
throw new IllegalArgumentException("Unexpected opcode for 1 operand");
}
itsStackTop = (short) newStack;
if (newStack > itsMaxStack) itsMaxStack = (short) newStack;
if (DEBUGSTACK) {
System.out.println("After " + bytecodeStr(theOpCode) + " stack = " + itsStackTop);
}
}