import java.util.HashMap;
import java.util.ArrayList;
+/**
+ * A basic block is a sequence of bytecode that does not contain jump/branch
+ * instructions except at the last bytecode.
+ * Since Java6 or later does not allow JSR, this class deals with JSR as a
+ * non-branch instruction.
+ */
public class BasicBlock {
public int position, length;
public int incoming; // the number of incoming branches.
else if (Opcode.GOTO <= op && op <= Opcode.LOOKUPSWITCH)
switch (op) {
case Opcode.GOTO :
+ makeGoto(marks, index, index + ci.s16bitAt(index + 1), 3);
+ break;
case Opcode.JSR :
- makeGotoJsr(marks, index, index + ci.s16bitAt(index + 1),
- op == Opcode.GOTO, 3);
+ makeJsr(marks, index, index + ci.s16bitAt(index + 1), 3);
break;
case Opcode.RET :
- makeMark(marks, index, null, 1, true);
+ makeMark(marks, index, null, 2, true);
break;
case Opcode.TABLESWITCH : {
int pos = (index & ~3) + 4;
}
else if ((Opcode.IRETURN <= op && op <= Opcode.RETURN) || op == Opcode.ATHROW)
makeMark(marks, index, null, 1, true);
- else if (op == Opcode.GOTO_W || op == Opcode.JSR_W)
- makeGotoJsr(marks, index, index + ci.s32bitAt(index + 1),
- op == Opcode.GOTO_W, 5);
+ else if (op == Opcode.GOTO_W)
+ makeGoto(marks, index, index + ci.s32bitAt(index + 1), 5);
+ else if (op == Opcode.JSR_W)
+ makeJsr(marks, index, index + ci.s32bitAt(index + 1), 5);
else if (op == Opcode.WIDE && ci.byteAt(index + 1) == Opcode.RET)
makeMark(marks, index, null, 1, true);
}
return marks;
}
- private void makeGotoJsr(HashMap marks, int pos, int target, boolean isGoto, int size) {
+ private void makeGoto(HashMap marks, int pos, int target, int size) {
Mark to = makeMark(marks, target);
- BasicBlock[] jumps;
- if (isGoto)
- jumps = makeArray(to.block);
- else {
- Mark next = makeMark(marks, pos + size);
- jumps = makeArray(to.block, next.block);
- }
+ BasicBlock[] jumps = makeArray(to.block);
+ makeMark(marks, pos, jumps, size, true);
+ }
- makeMark(marks, pos, jumps, size, isGoto);
+ /**
+ * We ignore JSR since Java 6 or later does not allow it.
+ */
+ protected void makeJsr(HashMap marks, int pos, int target, int size) {
+ /*
+ Mark to = makeMark(marks, target);
+ Mark next = makeMark(marks, pos + size);
+ BasicBlock[] jumps = makeArray(to.block, next.block);
+ makeMark(marks, pos, jumps, size, false);
+ */
}
private BasicBlock[] makeBlocks(HashMap markTable) {
/**
* Invoked when the visited instruction is jsr.
+ * Java6 or later does not allow using RET.
*/
protected void visitJSR(int pos, byte[] code) throws BadBytecode {
- throwBadBytecode(pos, "jsr");
+ /* Since JSR pushes a return address onto the operand stack,
+ * the stack map at the entry point of a subroutine is
+ * stackTypes resulting after executing the following code:
+ *
+ * stackTypes[stackTop++] = TOP;
+ */
}
/**
* Invoked when the visited instruction is ret or wide ret.
+ * Java6 or later does not allow using RET.
*/
- protected void visitRET(int pos, byte[] code) throws BadBytecode {
- throwBadBytecode(pos, "ret");
- }
-
- private void throwBadBytecode(int pos, String name) throws BadBytecode {
- throw new BadBytecode(name + " at " + pos);
- }
+ protected void visitRET(int pos, byte[] code) throws BadBytecode {}
private int doOpcode0_53(int pos, byte[] code, int op) throws BadBytecode {
int reg;
visitGoto(pos, code, ByteArray.readS16bit(code, pos + 1));
return 3; // branch
case Opcode.JSR :
- stackTypes[stackTop++] = TOP; // not allowed?
visitJSR(pos, code);
return 3; // branch
case Opcode.RET :
visitRET(pos, code);
- return 2; // not allowed?
+ return 2;
case Opcode.TABLESWITCH : {
stackTop--; // branch
int pos2 = (pos & ~3) + 8;
visitGoto(pos, code, ByteArray.read32bit(code, pos + 1));
return 5; // branch
case Opcode.JSR_W :
- stackTypes[stackTop++] = TOP; // not allowed?
visitJSR(pos, code);
return 5;
}