|
|
|
@ -25,6 +25,8 @@ import java.io.ByteArrayInputStream; |
|
|
|
|
import java.io.InputStream; |
|
|
|
|
import java.io.EOFException; |
|
|
|
|
import java.io.IOException; |
|
|
|
|
import java.util.BitSet; |
|
|
|
|
import java.util.Stack; |
|
|
|
|
import java.util.Vector; |
|
|
|
|
import java.util.Enumeration; |
|
|
|
|
import java.util.NoSuchElementException; |
|
|
|
@ -901,9 +903,61 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void calculateMaxStack() { |
|
|
|
|
maxStack = 0; |
|
|
|
|
int[] stackHeights = new int[instructions.getCodeLength()]; |
|
|
|
|
int[] poppush = new int[2]; |
|
|
|
|
Stack todo = new Stack(); |
|
|
|
|
|
|
|
|
|
for (int i=0; i < stackHeights.length; i++) |
|
|
|
|
stackHeights[i] = -1; |
|
|
|
|
|
|
|
|
|
stackHeights[0] = 0; |
|
|
|
|
todo.push(instructions.get(0)); |
|
|
|
|
while (!todo.isEmpty()) { |
|
|
|
|
Instruction instr = (Instruction) todo.pop(); |
|
|
|
|
Instruction next = instr.getNextByAddr(); |
|
|
|
|
Instruction[] succs = instr.getSuccs(); |
|
|
|
|
int addr = instr.getAddr(); |
|
|
|
|
instr.getStackPopPush(poppush); |
|
|
|
|
int sh = stackHeights[addr] - poppush[0] + poppush[1]; |
|
|
|
|
// System.err.println("Instr: "+instr.getDescription()+
|
|
|
|
|
// "; before: "+stackHeights[addr]+" after: "+sh);
|
|
|
|
|
if (maxStack < sh) |
|
|
|
|
maxStack = sh; |
|
|
|
|
if (instr.getOpcode() == opc_jsr) { |
|
|
|
|
if (stackHeights[next.getAddr()] == -1) { |
|
|
|
|
stackHeights[next.getAddr()] = sh - 1; |
|
|
|
|
todo.push(next); |
|
|
|
|
} |
|
|
|
|
if (stackHeights[succs[0].getAddr()] == -1) { |
|
|
|
|
stackHeights[succs[0].getAddr()] = sh; |
|
|
|
|
todo.push(succs[0]); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
if (succs != null) { |
|
|
|
|
for (int i=0; i < succs.length; i++) { |
|
|
|
|
if (stackHeights[succs[i].getAddr()] == -1) { |
|
|
|
|
stackHeights[succs[i].getAddr()] = sh; |
|
|
|
|
todo.push(succs[i]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (!instr.doesAlwaysJump() |
|
|
|
|
&& stackHeights[next.getAddr()] == -1) { |
|
|
|
|
stackHeights[next.getAddr()] = sh; |
|
|
|
|
todo.push(next); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// System.err.println("New maxStack: "+maxStack+" Locals: "+maxLocals);
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void prepareWriting(GrowableConstantPool gcp) { |
|
|
|
|
/* Recalculate addr, length and add all constants to gcp */ |
|
|
|
|
/* Recalculate addr, length, maxStack, maxLocals and add all |
|
|
|
|
* constants to gcp */ |
|
|
|
|
int addr = 0; |
|
|
|
|
maxLocals = 0; |
|
|
|
|
for (Iterator iter = instructions.iterator(); iter.hasNext(); ) { |
|
|
|
|
Instruction instr = (Instruction) iter.next(); |
|
|
|
|
int opcode = instr.getOpcode(); |
|
|
|
@ -957,22 +1011,44 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes { |
|
|
|
|
length = 3; |
|
|
|
|
else |
|
|
|
|
length = 6; |
|
|
|
|
if (slot >= maxLocals) |
|
|
|
|
maxLocals = slot + 1; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case opc_iload: case opc_lload: |
|
|
|
|
case opc_fload: case opc_dload: case opc_aload: |
|
|
|
|
case opc_istore: case opc_lstore: |
|
|
|
|
case opc_fstore: case opc_dstore: case opc_astore: |
|
|
|
|
if (instr.getLocalSlot() < 4) { |
|
|
|
|
case opc_iload: case opc_fload: case opc_aload: |
|
|
|
|
case opc_istore: case opc_fstore: case opc_astore: { |
|
|
|
|
int slot = instr.getLocalSlot(); |
|
|
|
|
if (slot < 4) |
|
|
|
|
length = 1; |
|
|
|
|
else if (slot < 256) |
|
|
|
|
length = 2; |
|
|
|
|
else |
|
|
|
|
length = 4; |
|
|
|
|
if (slot >= maxLocals) |
|
|
|
|
maxLocals = slot + 1; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case opc_lload: case opc_dload: |
|
|
|
|
case opc_lstore: case opc_dstore: { |
|
|
|
|
int slot = instr.getLocalSlot(); |
|
|
|
|
if (slot < 4) |
|
|
|
|
length = 1; |
|
|
|
|
else if (slot < 256) |
|
|
|
|
length = 2; |
|
|
|
|
else |
|
|
|
|
length = 4; |
|
|
|
|
if (slot+1 >= maxLocals) |
|
|
|
|
maxLocals = slot + 2; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
/* fall through */ |
|
|
|
|
case opc_ret: { |
|
|
|
|
if (instr.getLocalSlot() < 256) |
|
|
|
|
int slot = instr.getLocalSlot(); |
|
|
|
|
if (slot < 256) |
|
|
|
|
length = 2; |
|
|
|
|
else |
|
|
|
|
length = 4; |
|
|
|
|
if (slot >= maxLocals) |
|
|
|
|
maxLocals = slot + 1; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case opc_lookupswitch: { |
|
|
|
@ -1092,6 +1168,7 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes { |
|
|
|
|
addr += length; |
|
|
|
|
} |
|
|
|
|
instructions.setLastAddr(addr); |
|
|
|
|
calculateMaxStack(); |
|
|
|
|
for (int i=0; i< exceptionHandlers.length; i++) |
|
|
|
|
if (exceptionHandlers[i].type != null) |
|
|
|
|
gcp.putClassName(exceptionHandlers[i].type); |
|
|
|
@ -1483,14 +1560,6 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes { |
|
|
|
|
return lnt; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void setMaxStack(int ms) { |
|
|
|
|
maxStack = ms; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void setMaxLocals(int ml) { |
|
|
|
|
maxLocals = ml; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void setExceptionHandlers(Handler[] handlers) { |
|
|
|
|
exceptionHandlers = handlers; |
|
|
|
|
} |
|
|
|
|