use member functions to access Instruction fields

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1064 379699f6-c40d-0410-875b-85095c16579e
branch_1_1
jochen 26 years ago
parent 2ecb19a3d9
commit 900205e713
  1. 78
      jode/jode/decompiler/DeadCodeAnalysis.java
  2. 3
      jode/jode/decompiler/LocalVariableTable.java
  3. 62
      jode/jode/decompiler/Opcodes.java
  4. 268
      jode/jode/obfuscator/ConstantAnalyzer.java
  5. 146
      jode/jode/obfuscator/LocalOptimizer.java
  6. 19
      jode/jode/obfuscator/MethodIdentifier.java
  7. 93
      jode/jode/obfuscator/RemovePopAnalyzer.java
  8. 40
      jode/jode/obfuscator/SimpleAnalyzer.java

@ -24,33 +24,35 @@ import jode.bytecode.Handler;
public class DeadCodeAnalysis { public class DeadCodeAnalysis {
private final static Object reachable = new Integer(1); private final static String REACHABLE = "R";
private final static Object reachChanged = new Integer(2); private final static String REACHCHANGED = "C";
private static void propagateReachability(Instruction firstInstr, private static void propagateReachability(Instruction firstInstr,
Instruction reachInstr) { Instruction reachInstr) {
if (reachInstr.tmpInfo != null) if (reachInstr.getTmpInfo() != null)
return; return;
reachInstr.tmpInfo = reachChanged; reachInstr.setTmpInfo(REACHCHANGED);
boolean changed; boolean changed;
do { do {
changed = false; changed = false;
for (Instruction instr = firstInstr; for (Instruction instr = firstInstr;
instr != null; instr = instr.nextByAddr) { instr != null; instr = instr.getNextByAddr()) {
if (instr.tmpInfo == reachChanged) { if (instr.getTmpInfo() == REACHCHANGED) {
changed = true; changed = true;
instr.tmpInfo = reachable; instr.setTmpInfo(REACHABLE);
if (instr.succs != null) Instruction[] succs = instr.getSuccs();
for (int i=0; i< instr.succs.length; i++) if (succs != null)
if (instr.succs[i].tmpInfo == null) for (int i=0; i< succs.length; i++)
instr.succs[i].tmpInfo = reachChanged; if (succs[i].getTmpInfo() == null)
if (!instr.alwaysJumps && instr.nextByAddr != null) succs[i].setTmpInfo(REACHCHANGED);
if (instr.nextByAddr.tmpInfo == null) if (!instr.doesAlwaysJump()
instr.nextByAddr.tmpInfo = reachChanged; && instr.getNextByAddr() != null)
if (instr.getNextByAddr().getTmpInfo() == null)
instr.getNextByAddr().setTmpInfo(REACHCHANGED);
/*XXX code after jsr reachable iff ret is reachable...*/ /*XXX code after jsr reachable iff ret is reachable...*/
if (instr.opcode == Opcodes.opc_jsr) if (instr.getOpcode() == Opcodes.opc_jsr)
if (instr.nextByAddr.tmpInfo == null) if (instr.getNextByAddr().getTmpInfo() == null)
instr.nextByAddr.tmpInfo = reachChanged; instr.getNextByAddr().setTmpInfo(REACHCHANGED);
} }
} }
} while (changed); } while (changed);
@ -63,13 +65,13 @@ public class DeadCodeAnalysis {
do { do {
changed = false; changed = false;
for (int i=0; i < handlers.length; i++) { for (int i=0; i < handlers.length; i++) {
if (handlers[i].catcher.tmpInfo == null) { if (handlers[i].catcher.getTmpInfo() == null) {
/* check if the try block is somewhere reachable /* check if the try block is somewhere reachable
* and mark the catcher as reachable then. * and mark the catcher as reachable then.
*/ */
for (Instruction instr = handlers[i].start; for (Instruction instr = handlers[i].start;
instr != null; instr = instr.nextByAddr) { instr != null; instr = instr.getNextByAddr()) {
if (instr.tmpInfo != null) { if (instr.getTmpInfo() != null) {
propagateReachability(code.getFirstInstr(), propagateReachability(code.getFirstInstr(),
handlers[i].catcher); handlers[i].catcher);
changed = true; changed = true;
@ -81,21 +83,10 @@ public class DeadCodeAnalysis {
} }
} }
} while (changed); } while (changed);
/* Now remove the dead code */
Instruction nextInstr;
for (Instruction instr = code.getFirstInstr();
instr != null; instr = nextInstr) {
nextInstr = instr.nextByAddr;
if (instr.tmpInfo == null) {
instr.removeInstruction();
/* adjust length, since someone may rely on this */
/* first block is always reachable, so prevByAddr != null */
instr.prevByAddr.length += instr.length;
}
}
for (int i=0; i< handlers.length; i++) { for (int i=0; i< handlers.length; i++) {
/* A handler is not reachable iff the catcher is not reachable */ /* A handler is not reachable iff the catcher is not reachable */
if (handlers[i].catcher.tmpInfo == null) { if (handlers[i].catcher.getTmpInfo() == null) {
/* This is very seldom, so we can make it slow */ /* This is very seldom, so we can make it slow */
Handler[] newHandlers = new Handler[handlers.length - 1]; Handler[] newHandlers = new Handler[handlers.length - 1];
System.arraycopy(handlers, 0, newHandlers, 0, i); System.arraycopy(handlers, 0, newHandlers, 0, i);
@ -106,15 +97,22 @@ public class DeadCodeAnalysis {
i--; i--;
} else { } else {
/* This works! */ /* This works! */
while (handlers[i].start.tmpInfo == null) while (handlers[i].start.getTmpInfo() == null)
handlers[i].start = handlers[i].start.nextByAddr; handlers[i].start = handlers[i].start.getNextByAddr();
while (handlers[i].end.tmpInfo == null) while (handlers[i].end.getTmpInfo() == null)
handlers[i].end = handlers[i].end.prevByAddr; handlers[i].end = handlers[i].end.getPrevByAddr();
} }
} }
/* clean up tmpInfo */
/* Now remove the dead code and clean up tmpInfo */
Instruction nextInstr;
for (Instruction instr = code.getFirstInstr(); for (Instruction instr = code.getFirstInstr();
instr != null; instr = instr.nextByAddr) instr != null; instr = nextInstr) {
instr.tmpInfo = null; nextInstr = instr.getNextByAddr();
if (instr.getTmpInfo() == null)
instr.removeInstruction();
else
instr.setTmpInfo(null);
}
} }
} }

@ -32,7 +32,8 @@ public class LocalVariableTable {
locals[i] = new LocalVariableRangeList(); locals[i] = new LocalVariableRangeList();
for (int i=0; i<lvt.length; i++) for (int i=0; i<lvt.length; i++)
locals[lvt[i].slot].addLocal(lvt[i].start.addr, lvt[i].end.addr, locals[lvt[i].slot].addLocal(lvt[i].start.getAddr(),
lvt[i].end.getAddr(),
lvt[i].name, Type.tType(lvt[i].type)); lvt[i].name, Type.tType(lvt[i].type));
} }

@ -91,13 +91,15 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
private static StructuredBlock createGoto(MethodAnalyzer ma, private static StructuredBlock createGoto(MethodAnalyzer ma,
Instruction instr) Instruction instr)
{ {
return new EmptyBlock(new Jump((FlowBlock)instr.succs[0].tmpInfo)); return new EmptyBlock
(new Jump((FlowBlock)instr.getSuccs()[0].getTmpInfo()));
} }
private static StructuredBlock createJsr(MethodAnalyzer ma, private static StructuredBlock createJsr(MethodAnalyzer ma,
Instruction instr) Instruction instr)
{ {
return new JsrBlock(new Jump((FlowBlock)instr.succs[0].tmpInfo), return new JsrBlock
(new Jump((FlowBlock)instr.getSuccs()[0].getTmpInfo()),
new Jump(FlowBlock.NEXT_BY_ADDR)); new Jump(FlowBlock.NEXT_BY_ADDR));
} }
@ -106,7 +108,7 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
Expression expr) Expression expr)
{ {
return new ConditionalBlock return new ConditionalBlock
(expr, new Jump((FlowBlock)instr.succs[0].tmpInfo), (expr, new Jump((FlowBlock)instr.getSuccs()[0].getTmpInfo()),
new Jump(FlowBlock.NEXT_BY_ADDR)); new Jump(FlowBlock.NEXT_BY_ADDR));
} }
@ -146,21 +148,22 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
MethodAnalyzer ma) MethodAnalyzer ma)
throws ClassFormatError throws ClassFormatError
{ {
int opcode = instr.opcode; int opcode = instr.getOpcode();
switch (opcode) { switch (opcode) {
case opc_nop: case opc_nop:
return createBlock(ma, instr, new EmptyBlock return createBlock(ma, instr, new EmptyBlock
(new Jump(FlowBlock.NEXT_BY_ADDR))); (new Jump(FlowBlock.NEXT_BY_ADDR)));
case opc_ldc: case opc_ldc:
case opc_ldc2_w: case opc_ldc2_w:
return createNormal (ma, instr, new ConstOperator(instr.objData)); return createNormal (ma, instr,
new ConstOperator(instr.getConstant()));
case opc_iload: case opc_lload: case opc_iload: case opc_lload:
case opc_fload: case opc_dload: case opc_aload: case opc_fload: case opc_dload: case opc_aload:
return createNormal return createNormal
(ma, instr, new LocalLoadOperator (ma, instr, new LocalLoadOperator
(types[LOCAL_TYPES][opcode-opc_iload], ma, (types[LOCAL_TYPES][opcode-opc_iload], ma,
ma.getLocalInfo(instr.addr, instr.localSlot))); ma.getLocalInfo(instr.getAddr(), instr.getLocalSlot())));
case opc_iaload: case opc_laload: case opc_iaload: case opc_laload:
case opc_faload: case opc_daload: case opc_aaload: case opc_faload: case opc_daload: case opc_aaload:
case opc_baload: case opc_caload: case opc_saload: case opc_baload: case opc_caload: case opc_saload:
@ -173,7 +176,8 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
(ma, instr, new StoreInstruction (ma, instr, new StoreInstruction
(new LocalStoreOperator (new LocalStoreOperator
(types[LOCAL_TYPES][opcode-opc_istore], (types[LOCAL_TYPES][opcode-opc_istore],
ma.getLocalInfo(instr.addr+instr.length,instr.localSlot)))); ma.getLocalInfo(instr.getAddr()+instr.getLength(),
instr.getLocalSlot()))));
case opc_iastore: case opc_lastore: case opc_iastore: case opc_lastore:
case opc_fastore: case opc_dastore: case opc_aastore: case opc_fastore: case opc_dastore: case opc_aastore:
case opc_bastore: case opc_castore: case opc_sastore: case opc_bastore: case opc_castore: case opc_sastore:
@ -219,13 +223,14 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
(types[ZBIN_TYPES][(opcode - opc_iand)%2], (types[ZBIN_TYPES][(opcode - opc_iand)%2],
(opcode - opc_iand)/2 + Operator.AND_OP)); (opcode - opc_iand)/2 + Operator.AND_OP));
case opc_iinc: { case opc_iinc: {
int value = instr.intData; int value = instr.getIntData();
int operation = Operator.ADD_OP; int operation = Operator.ADD_OP;
if (value < 0) { if (value < 0) {
value = -value; value = -value;
operation = Operator.SUB_OP; operation = Operator.SUB_OP;
} }
LocalInfo li = ma.getLocalInfo(instr.addr, instr.localSlot); LocalInfo li
= ma.getLocalInfo(instr.getAddr(), instr.getLocalSlot());
return createNormal return createNormal
(ma, instr, new IIncOperator (ma, instr, new IIncOperator
(new LocalStoreOperator(Type.tInt, li), (new LocalStoreOperator(Type.tInt, li),
@ -287,24 +292,27 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
return createJsr(ma, instr); return createJsr(ma, instr);
case opc_ret: case opc_ret:
return createRet return createRet
(ma, instr, ma.getLocalInfo(instr.addr, instr.localSlot)); (ma, instr,
ma.getLocalInfo(instr.getAddr(), instr.getLocalSlot()));
case opc_tableswitch: { case opc_tableswitch: {
int low = instr.intData; int low = instr.getIntData();
int[] cases = new int[instr.succs.length-1]; int[] cases = new int[instr.getSuccs().length-1];
FlowBlock[] dests = new FlowBlock[instr.succs.length]; FlowBlock[] dests = new FlowBlock[instr.getSuccs().length];
for (int i=0; i < cases.length; i++) { for (int i=0; i < cases.length; i++) {
cases[i] = i+low; cases[i] = i+low;
dests[i] = (FlowBlock) instr.succs[i].tmpInfo; dests[i] = (FlowBlock) instr.getSuccs()[i].getTmpInfo();
} }
dests[cases.length] = (FlowBlock)instr.succs[cases.length].tmpInfo; dests[cases.length] = (FlowBlock)
instr.getSuccs()[cases.length].getTmpInfo();
return createSwitch(ma, instr, cases, dests); return createSwitch(ma, instr, cases, dests);
} }
case opc_lookupswitch: { case opc_lookupswitch: {
int[] cases = (int[]) instr.objData; int[] cases = instr.getValues();
FlowBlock[] dests = new FlowBlock[instr.succs.length]; FlowBlock[] dests = new FlowBlock[instr.getSuccs().length];
for (int i=0; i < dests.length; i++) for (int i=0; i < dests.length; i++)
dests[i] = (FlowBlock) instr.succs[i].tmpInfo; dests[i] = (FlowBlock) instr.getSuccs()[i].getTmpInfo();
dests[cases.length] = (FlowBlock)instr.succs[cases.length].tmpInfo; dests[cases.length] = (FlowBlock)
instr.getSuccs()[cases.length].getTmpInfo();
return createSwitch(ma, instr, cases, dests); return createSwitch(ma, instr, cases, dests);
} }
case opc_ireturn: case opc_lreturn: case opc_ireturn: case opc_lreturn:
@ -318,14 +326,14 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
(ma, instr, new EmptyBlock(new Jump(FlowBlock.END_OF_METHOD))); (ma, instr, new EmptyBlock(new Jump(FlowBlock.END_OF_METHOD)));
case opc_getstatic: case opc_getstatic:
case opc_getfield: { case opc_getfield: {
Reference ref = (Reference) instr.objData; Reference ref = instr.getReference();
return createNormal return createNormal
(ma, instr, new GetFieldOperator (ma, instr, new GetFieldOperator
(ma, opcode == opc_getstatic, ref)); (ma, opcode == opc_getstatic, ref));
} }
case opc_putstatic: case opc_putstatic:
case opc_putfield: { case opc_putfield: {
Reference ref = (Reference) instr.objData; Reference ref = instr.getReference();
return createNormal return createNormal
(ma, instr, new StoreInstruction (ma, instr, new StoreInstruction
(new PutFieldOperator(ma, opcode == opc_putstatic, ref))); (new PutFieldOperator(ma, opcode == opc_putstatic, ref)));
@ -334,7 +342,7 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
case opc_invokespecial: case opc_invokespecial:
case opc_invokestatic : case opc_invokestatic :
case opc_invokeinterface: { case opc_invokeinterface: {
Reference ref = (Reference) instr.objData; Reference ref = instr.getReference();
StructuredBlock block = createNormal StructuredBlock block = createNormal
(ma, instr, new InvokeOperator (ma, instr, new InvokeOperator
(ma, opcode == opc_invokestatic, (ma, opcode == opc_invokestatic,
@ -342,7 +350,7 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
return block; return block;
} }
case opc_new: { case opc_new: {
Type type = Type.tType((String) instr.objData); Type type = Type.tType(instr.getClazzType());
ma.useType(type); ma.useType(type);
return createNormal(ma, instr, new NewOperator(type)); return createNormal(ma, instr, new NewOperator(type));
} }
@ -354,13 +362,13 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
(ma, instr, (ma, instr,
new ThrowBlock(new NopOperator(Type.tUObject))); new ThrowBlock(new NopOperator(Type.tUObject)));
case opc_checkcast: { case opc_checkcast: {
Type type = Type.tType((String) instr.objData); Type type = Type.tType(instr.getClazzType());
ma.useType(type); ma.useType(type);
return createNormal return createNormal
(ma, instr, new CheckCastOperator(type)); (ma, instr, new CheckCastOperator(type));
} }
case opc_instanceof: { case opc_instanceof: {
Type type = Type.tType((String) instr.objData); Type type = Type.tType(instr.getClazzType());
ma.useType(type); ma.useType(type);
return createNormal return createNormal
(ma, instr, new InstanceOfOperator(type)); (ma, instr, new InstanceOfOperator(type));
@ -372,9 +380,9 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
return createNormal(ma, instr, return createNormal(ma, instr,
new MonitorExitOperator()); new MonitorExitOperator());
case opc_multianewarray: { case opc_multianewarray: {
Type type = Type.tType((String) instr.objData); Type type = Type.tType(instr.getClazzType());
ma.useType(type); ma.useType(type);
int dimension = instr.intData; int dimension = instr.getIntData();
return createNormal(ma, instr, return createNormal(ma, instr,
new NewArrayOperator(type, dimension)); new NewArrayOperator(type, dimension));
} }

@ -416,16 +416,16 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
public void mergeInfo(Instruction instr, public void mergeInfo(Instruction instr,
StackLocalInfo info) { StackLocalInfo info) {
if (instr.tmpInfo == null) { if (instr.getTmpInfo() == null) {
instr.tmpInfo = info; instr.setTmpInfo(info);
info.instr = instr; info.instr = instr;
info.enqueue(); info.enqueue();
} else } else
((StackLocalInfo)instr.tmpInfo).merge(info); ((StackLocalInfo)instr.getTmpInfo()).merge(info);
} }
public Identifier canonizeReference(Instruction instr) { public Identifier canonizeReference(Instruction instr) {
Reference ref = (Reference) instr.objData; Reference ref = instr.getReference();
Identifier ident = Main.getClassBundle().getIdentifier(ref); Identifier ident = Main.getClassBundle().getIdentifier(ref);
String clName = ref.getClazz(); String clName = ref.getClazz();
String realClazzName; String realClazzName;
@ -448,7 +448,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
(clName.substring(1, clName.length()-1) (clName.substring(1, clName.length()-1)
.replace('/','.')); .replace('/','.'));
} }
if (instr.opcode >= opc_invokevirtual) { if (instr.getOpcode() >= opc_invokevirtual) {
while (clazz != null while (clazz != null
&& clazz.findMethod(ref.getName(), && clazz.findMethod(ref.getName(),
ref.getType()) == null) ref.getType()) == null)
@ -470,7 +470,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
if (!realClazzName.equals(ref.getClazz())) { if (!realClazzName.equals(ref.getClazz())) {
ref = Reference.getReference(realClazzName, ref = Reference.getReference(realClazzName,
ref.getName(), ref.getType()); ref.getName(), ref.getType());
instr.objData = ref; instr.setReference(ref);
} }
return ident; return ident;
} }
@ -499,29 +499,29 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
Instruction instr = info.instr; Instruction instr = info.instr;
constInfos.put(instr, unknownConstInfo); constInfos.put(instr, unknownConstInfo);
int opcode = instr.opcode; int opcode = instr.getOpcode();
Handler[] handlers = bytecode.getExceptionHandlers(); Handler[] handlers = bytecode.getExceptionHandlers();
for (int i=0; i< handlers.length; i++) { for (int i=0; i< handlers.length; i++) {
if (handlers[i].start.addr <= instr.addr if (handlers[i].start.getAddr() <= instr.getAddr()
&& handlers[i].end.addr >= instr.addr) && handlers[i].end.getAddr() >= instr.getAddr())
mergeInfo(handlers[i].catcher, mergeInfo(handlers[i].catcher,
info.poppush(info.stack.length, unknownValue[0])); info.poppush(info.stack.length, unknownValue[0]));
} }
ConstValue result; ConstValue result;
switch (opcode) { switch (opcode) {
case opc_nop: case opc_nop:
mergeInfo(instr.nextByAddr, info.pop(0)); mergeInfo(instr.getNextByAddr(), info.pop(0));
break; break;
case opc_ldc: case opc_ldc:
case opc_ldc2_w: case opc_ldc2_w:
result = new ConstValue(instr.objData); result = new ConstValue(instr.getConstant());
mergeInfo(instr.nextByAddr, info.poppush(0, result)); mergeInfo(instr.getNextByAddr(), info.poppush(0, result));
break; break;
case opc_iload: case opc_lload: case opc_iload: case opc_lload:
case opc_fload: case opc_dload: case opc_aload: case opc_fload: case opc_dload: case opc_aload:
result = info.getLocal(instr.localSlot); result = info.getLocal(instr.getLocalSlot());
if (result == null) { if (result == null) {
dumpStackLocalInfo(); dumpStackLocalInfo();
System.err.println(info); System.err.println(info);
@ -534,9 +534,9 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
shortInfo.constant = result.value; shortInfo.constant = result.value;
result.addConstantListener(shortInfo); result.addConstantListener(shortInfo);
} }
mergeInfo(instr.nextByAddr, mergeInfo(instr.getNextByAddr(),
info.poppush(0, result) info.poppush(0, result)
.setLocal(instr.localSlot, result.copy())); .setLocal(instr.getLocalSlot(), result.copy()));
break; break;
case opc_iaload: case opc_laload: case opc_iaload: case opc_laload:
case opc_faload: case opc_daload: case opc_aaload: case opc_faload: case opc_daload: case opc_aaload:
@ -578,17 +578,17 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
result = unknownValue[(opcode == opc_laload result = unknownValue[(opcode == opc_laload
|| opcode == opc_daload) ? 1 : 0]; || opcode == opc_daload) ? 1 : 0];
// } // }
mergeInfo(instr.nextByAddr, info.poppush(2, result)); mergeInfo(instr.getNextByAddr(), info.poppush(2, result));
break; break;
} }
case opc_istore: case opc_fstore: case opc_astore: { case opc_istore: case opc_fstore: case opc_astore: {
mergeInfo(instr.nextByAddr, mergeInfo(instr.getNextByAddr(),
info.pop(1).setLocal(instr.localSlot, info.getStack(1))); info.pop(1).setLocal(instr.getLocalSlot(), info.getStack(1)));
break; break;
} }
case opc_lstore: case opc_dstore: { case opc_lstore: case opc_dstore: {
mergeInfo(instr.nextByAddr, mergeInfo(instr.getNextByAddr(),
info.pop(2).setLocal(instr.localSlot, info.getStack(2))); info.pop(2).setLocal(instr.getLocalSlot(), info.getStack(2)));
break; break;
} }
case opc_iastore: case opc_lastore: case opc_iastore: case opc_lastore:
@ -596,21 +596,21 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
case opc_bastore: case opc_castore: case opc_sastore: { case opc_bastore: case opc_castore: case opc_sastore: {
int size = (opcode == opc_lastore int size = (opcode == opc_lastore
|| opcode == opc_dastore) ? 2 : 1; || opcode == opc_dastore) ? 2 : 1;
mergeInfo(instr.nextByAddr, info.pop(2+size)); mergeInfo(instr.getNextByAddr(), info.pop(2+size));
break; break;
} }
case opc_pop: case opc_pop2: case opc_pop: case opc_pop2:
mergeInfo(instr.nextByAddr, info.pop(opcode - (opc_pop - 1))); mergeInfo(instr.getNextByAddr(), info.pop(opcode - (opc_pop - 1)));
break; break;
case opc_dup: case opc_dup_x1: case opc_dup_x2: case opc_dup: case opc_dup_x1: case opc_dup_x2:
case opc_dup2: case opc_dup2_x1: case opc_dup2_x2: case opc_dup2: case opc_dup2_x1: case opc_dup2_x2:
mergeInfo(instr.nextByAddr, mergeInfo(instr.getNextByAddr(),
info.dup((opcode - (opc_dup - 3)) / 3, info.dup((opcode - (opc_dup - 3)) / 3,
(opcode - (opc_dup - 3)) % 3)); (opcode - (opc_dup - 3)) % 3));
break; break;
case opc_swap: case opc_swap:
mergeInfo(instr.nextByAddr, info.swap()); mergeInfo(instr.getNextByAddr(), info.swap());
break; break;
case opc_iadd: case opc_ladd: case opc_fadd: case opc_dadd: case opc_iadd: case opc_ladd: case opc_fadd: case opc_dadd:
@ -782,7 +782,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
value2.addConstantListener(result); value2.addConstantListener(result);
} else } else
result = unknownValue[size-1]; result = unknownValue[size-1];
mergeInfo(instr.nextByAddr, info.poppush(2*size, result)); mergeInfo(instr.getNextByAddr(), info.poppush(2*size, result));
break; break;
} }
case opc_ineg: case opc_lneg: case opc_fneg: case opc_dneg: { case opc_ineg: case opc_lneg: case opc_fneg: case opc_dneg: {
@ -819,7 +819,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
value.addConstantListener(result); value.addConstantListener(result);
} else } else
result = unknownValue[size-1]; result = unknownValue[size-1];
mergeInfo(instr.nextByAddr, info.poppush(size, result)); mergeInfo(instr.getNextByAddr(), info.poppush(size, result));
break; break;
} }
case opc_ishl: case opc_lshl: case opc_ishl: case opc_lshl:
@ -876,20 +876,20 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
value2.addConstantListener(result); value2.addConstantListener(result);
} else } else
result = unknownValue[size-1]; result = unknownValue[size-1];
mergeInfo(instr.nextByAddr, info.poppush(size+1, result)); mergeInfo(instr.getNextByAddr(), info.poppush(size+1, result));
break; break;
} }
case opc_iinc: { case opc_iinc: {
ConstValue local = info.getLocal(instr.localSlot); ConstValue local = info.getLocal(instr.getLocalSlot());
if (local.value != ConstValue.VOLATILE) { if (local.value != ConstValue.VOLATILE) {
result = new ConstValue result = new ConstValue
(new Integer(((Integer)local.value).intValue() (new Integer(((Integer)local.value).intValue()
+ instr.intData)); + instr.getIntData()));
local.addConstantListener(result); local.addConstantListener(result);
} else } else
result = unknownValue[0]; result = unknownValue[0];
mergeInfo(instr.nextByAddr, mergeInfo(instr.getNextByAddr(),
info.copy().setLocal(instr.localSlot, result)); info.copy().setLocal(instr.getLocalSlot(), result));
break; break;
} }
case opc_i2l: case opc_i2f: case opc_i2d: case opc_i2l: case opc_i2f: case opc_i2d:
@ -933,7 +933,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
result = unknownValue[0]; result = unknownValue[0];
} }
} }
mergeInfo(instr.nextByAddr, info.poppush(insize, result)); mergeInfo(instr.getNextByAddr(), info.poppush(insize, result));
break; break;
} }
case opc_i2b: case opc_i2c: case opc_i2s: { case opc_i2b: case opc_i2c: case opc_i2s: {
@ -960,7 +960,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
stack.addConstantListener(result); stack.addConstantListener(result);
} else } else
result = unknownValue[0]; result = unknownValue[0];
mergeInfo(instr.nextByAddr, mergeInfo(instr.getNextByAddr(),
info.poppush(1, result)); info.poppush(1, result));
break; break;
} }
@ -982,7 +982,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
val2.addConstantListener(result); val2.addConstantListener(result);
} else } else
result = unknownValue[0]; result = unknownValue[0];
mergeInfo(instr.nextByAddr, info.poppush(4, result)); mergeInfo(instr.getNextByAddr(), info.poppush(4, result));
break; break;
} }
case opc_fcmpl: case opc_fcmpg: { case opc_fcmpl: case opc_fcmpg: {
@ -1006,7 +1006,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
val2.addConstantListener(result); val2.addConstantListener(result);
} else } else
result = unknownValue[0]; result = unknownValue[0];
mergeInfo(instr.nextByAddr, info.poppush(2, result)); mergeInfo(instr.getNextByAddr(), info.poppush(2, result));
break; break;
} }
case opc_dcmpl: case opc_dcmpg: { case opc_dcmpl: case opc_dcmpg: {
@ -1030,7 +1030,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
val2.addConstantListener(result); val2.addConstantListener(result);
} else } else
result = unknownValue[0]; result = unknownValue[0];
mergeInfo(instr.nextByAddr, info.poppush(4, result)); mergeInfo(instr.getNextByAddr(), info.poppush(4, result));
break; break;
} }
case opc_ifeq: case opc_ifne: case opc_ifeq: case opc_ifne:
@ -1055,7 +1055,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
if (other != null) if (other != null)
other.addConstantListener(info); other.addConstantListener(info);
Instruction pc = instr.nextByAddr; Instruction pc = instr.getNextByAddr();
int opc_mask; int opc_mask;
if (opcode >= opc_if_acmpeq) { if (opcode >= opc_if_acmpeq) {
if (opcode >= opc_ifnull) { if (opcode >= opc_ifnull) {
@ -1084,7 +1084,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
} }
if ((opc_mask & (1<<opcode)) != 0) if ((opc_mask & (1<<opcode)) != 0)
pc = instr.succs[0]; pc = instr.getSuccs()[0];
ConstantInfo shortInfo = new ConstantInfo(); ConstantInfo shortInfo = new ConstantInfo();
constInfos.put(instr, shortInfo); constInfos.put(instr, shortInfo);
@ -1092,18 +1092,18 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
shortInfo.constant = pc; shortInfo.constant = pc;
mergeInfo(pc, info.pop(size)); mergeInfo(pc, info.pop(size));
} else { } else {
mergeInfo(instr.nextByAddr, info.pop(size)); mergeInfo(instr.getNextByAddr(), info.pop(size));
mergeInfo(instr.succs[0], info.pop(size)); mergeInfo(instr.getSuccs()[0], info.pop(size));
} }
break; break;
} }
case opc_goto: case opc_goto:
mergeInfo(instr.succs[0], info.copy()); mergeInfo(instr.getSuccs()[0], info.copy());
break; break;
case opc_jsr: case opc_jsr:
mergeInfo(instr.succs[0], mergeInfo(instr.getSuccs()[0],
info.poppush(0, new ConstValue info.poppush(0, new ConstValue
(new JSRTargetInfo(instr.succs[0])))); (new JSRTargetInfo(instr.getSuccs()[0]))));
break; break;
case opc_tableswitch: { case opc_tableswitch: {
ConstValue stacktop = info.getStack(1); ConstValue stacktop = info.getStack(1);
@ -1111,19 +1111,19 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
stacktop.addConstantListener(info); stacktop.addConstantListener(info);
Instruction pc; Instruction pc;
int value = ((Integer) stacktop.value).intValue(); int value = ((Integer) stacktop.value).intValue();
int low = instr.intData; int low = instr.getIntData();
if (value >= low && value <= low + instr.succs.length - 2) if (value >= low && value <= low + instr.getSuccs().length - 2)
pc = instr.succs[value - low]; pc = instr.getSuccs()[value - low];
else else
pc = instr.succs[instr.succs.length-1]; pc = instr.getSuccs()[instr.getSuccs().length-1];
ConstantInfo shortInfo = new ConstantInfo(); ConstantInfo shortInfo = new ConstantInfo();
constInfos.put(instr, shortInfo); constInfos.put(instr, shortInfo);
shortInfo.flags |= CONSTANTFLOW; shortInfo.flags |= CONSTANTFLOW;
shortInfo.constant = pc; shortInfo.constant = pc;
mergeInfo(pc, info.pop(1)); mergeInfo(pc, info.pop(1));
} else { } else {
for (int i=0; i < instr.succs.length; i++) for (int i=0; i < instr.getSuccs().length; i++)
mergeInfo(instr.succs[i], info.pop(1)); mergeInfo(instr.getSuccs()[i], info.pop(1));
} }
break; break;
} }
@ -1133,11 +1133,11 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
stacktop.addConstantListener(info); stacktop.addConstantListener(info);
Instruction pc; Instruction pc;
int value = ((Integer) stacktop.value).intValue(); int value = ((Integer) stacktop.value).intValue();
int[] values = (int[]) instr.objData; int[] values = instr.getValues();
pc = instr.succs[values.length]; pc = instr.getSuccs()[values.length];
for (int i=0; i< values.length; i++) { for (int i=0; i< values.length; i++) {
if (values[i] == value) { if (values[i] == value) {
pc = instr.succs[i]; pc = instr.getSuccs()[i];
break; break;
} }
} }
@ -1147,33 +1147,33 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
shortInfo.constant = pc; shortInfo.constant = pc;
mergeInfo(pc, info.pop(1)); mergeInfo(pc, info.pop(1));
} else { } else {
for (int i=0; i < instr.succs.length; i++) for (int i=0; i < instr.getSuccs().length; i++)
mergeInfo(instr.succs[i], info.pop(1)); mergeInfo(instr.getSuccs()[i], info.pop(1));
} }
break; break;
} }
case opc_ret: { case opc_ret: {
// dumpStackLocalInfo(); // dumpStackLocalInfo();
// System.err.println(instr); // System.err.println(instr);
result = info.getLocal(instr.localSlot); result = info.getLocal(instr.getLocalSlot());
JSRTargetInfo jsrInfo = (JSRTargetInfo) result.value; JSRTargetInfo jsrInfo = (JSRTargetInfo) result.value;
jsrInfo.retInfo = info; jsrInfo.retInfo = info;
result.addConstantListener(info); result.addConstantListener(info);
Instruction jsrTarget = jsrInfo.jsrTarget; Instruction jsrTarget = jsrInfo.jsrTarget;
for (int i=0; i < jsrTarget.preds.length; i++) { for (int i=0; i < jsrTarget.getPreds().length; i++) {
Instruction jsr = jsrTarget.preds[i]; Instruction jsr = jsrTarget.getPreds()[i];
if (jsr.tmpInfo == null) if (jsr.getTmpInfo() == null)
continue; continue;
StackLocalInfo nextInfo StackLocalInfo nextInfo
= ((StackLocalInfo) jsr.tmpInfo).copy(); = ((StackLocalInfo) jsr.getTmpInfo()).copy();
int maxLocals = bytecode.getMaxLocals(); int maxLocals = bytecode.getMaxLocals();
for (int slot = 0; slot < maxLocals; slot++) { for (int slot = 0; slot < maxLocals; slot++) {
if (slot == instr.localSlot) if (slot == instr.getLocalSlot())
nextInfo.setLocal(slot, null); nextInfo.setLocal(slot, null);
else if (jsrInfo.usedLocals.get(slot)) else if (jsrInfo.usedLocals.get(slot))
nextInfo.setLocal(slot, info.getLocal(slot)); nextInfo.setLocal(slot, info.getLocal(slot));
} }
mergeInfo(jsr.nextByAddr, nextInfo); mergeInfo(jsr.getNextByAddr(), nextInfo);
} }
break; break;
} }
@ -1187,20 +1187,20 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
case opc_putfield: { case opc_putfield: {
FieldIdentifier fi = (FieldIdentifier) canonizeReference(instr); FieldIdentifier fi = (FieldIdentifier) canonizeReference(instr);
int size = (opcode == opc_putstatic) ? 0 : 1; int size = (opcode == opc_putstatic) ? 0 : 1;
Reference ref = (Reference) instr.objData; Reference ref = instr.getReference();
if (fi != null && !fi.isNotConstant()) { if (fi != null && !fi.isNotConstant()) {
fi.setNotConstant(); fi.setNotConstant();
fieldNotConstant(fi); fieldNotConstant(fi);
} }
Type type = Type.tType(ref.getType()); Type type = Type.tType(ref.getType());
mergeInfo(instr.nextByAddr, info.pop(size + type.stackSize())); mergeInfo(instr.getNextByAddr(), info.pop(size + type.stackSize()));
break; break;
} }
case opc_getstatic: case opc_getstatic:
case opc_getfield: { case opc_getfield: {
int size = (opcode == opc_getstatic) ? 0 : 1; int size = (opcode == opc_getstatic) ? 0 : 1;
FieldIdentifier fi = (FieldIdentifier) canonizeReference(instr); FieldIdentifier fi = (FieldIdentifier) canonizeReference(instr);
Reference ref = (Reference) instr.objData; Reference ref = instr.getReference();
Type type = Type.tType(ref.getType()); Type type = Type.tType(ref.getType());
if (fi != null) { if (fi != null) {
if (fi.isNotConstant()) { if (fi.isNotConstant()) {
@ -1220,7 +1220,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
} }
} else } else
result = unknownValue[type.stackSize()-1]; result = unknownValue[type.stackSize()-1];
mergeInfo(instr.nextByAddr, info.poppush(size, result)); mergeInfo(instr.getNextByAddr(), info.poppush(size, result));
break; break;
} }
case opc_invokespecial: case opc_invokespecial:
@ -1228,7 +1228,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
case opc_invokeinterface: case opc_invokeinterface:
case opc_invokevirtual: { case opc_invokevirtual: {
canonizeReference(instr); canonizeReference(instr);
Reference ref = (Reference) instr.objData; Reference ref = instr.getReference();
MethodType mt = (MethodType) Type.tType(ref.getType()); MethodType mt = (MethodType) Type.tType(ref.getType());
boolean constant = true; boolean constant = true;
int size = 0; int size = 0;
@ -1258,7 +1258,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
if (retType == Type.tVoid) { if (retType == Type.tVoid) {
handleReference(ref, opcode == opc_invokevirtual handleReference(ref, opcode == opc_invokevirtual
|| opcode == opc_invokeinterface); || opcode == opc_invokeinterface);
mergeInfo(instr.nextByAddr, info.pop(size)); mergeInfo(instr.getNextByAddr(), info.pop(size));
break; break;
} }
if (constant if (constant
@ -1305,13 +1305,13 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
for (int i=0; i< argValues.length; i++) for (int i=0; i< argValues.length; i++)
argValues[i].addConstantListener(returnVal); argValues[i].addConstantListener(returnVal);
} }
mergeInfo(instr.nextByAddr, info.poppush(size, returnVal)); mergeInfo(instr.getNextByAddr(), info.poppush(size, returnVal));
break; break;
} }
case opc_new: { case opc_new: {
handleClass((String) instr.objData); handleClass(instr.getClazzType());
mergeInfo(instr.nextByAddr, info.poppush(0, unknownValue[0])); mergeInfo(instr.getNextByAddr(), info.poppush(0, unknownValue[0]));
break; break;
} }
case opc_arraylength: { case opc_arraylength: {
@ -1325,27 +1325,27 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
// array.addConstantListener(result); // array.addConstantListener(result);
// } else // } else
result = unknownValue[0]; result = unknownValue[0];
mergeInfo(instr.nextByAddr, info.poppush(1, result)); mergeInfo(instr.getNextByAddr(), info.poppush(1, result));
break; break;
} }
case opc_checkcast: { case opc_checkcast: {
handleClass((String) instr.objData); handleClass(instr.getClazzType());
mergeInfo(instr.nextByAddr, info.pop(0)); mergeInfo(instr.getNextByAddr(), info.pop(0));
break; break;
} }
case opc_instanceof: { case opc_instanceof: {
handleClass((String) instr.objData); handleClass(instr.getClazzType());
mergeInfo(instr.nextByAddr, info.poppush(1, unknownValue[0])); mergeInfo(instr.getNextByAddr(), info.poppush(1, unknownValue[0]));
break; break;
} }
case opc_monitorenter: case opc_monitorenter:
case opc_monitorexit: case opc_monitorexit:
mergeInfo(instr.nextByAddr, info.pop(1)); mergeInfo(instr.getNextByAddr(), info.pop(1));
break; break;
case opc_multianewarray: case opc_multianewarray:
handleClass((String) instr.objData); handleClass(instr.getClazzType());
mergeInfo(instr.nextByAddr, mergeInfo(instr.getNextByAddr(),
info.poppush(instr.intData, unknownValue[0])); info.poppush(instr.getIntData(), unknownValue[0]));
break; break;
default: default:
throw new jode.AssertError("Invalid opcode "+opcode); throw new jode.AssertError("Invalid opcode "+opcode);
@ -1355,14 +1355,14 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
public void fieldNotConstant(FieldIdentifier fi) { public void fieldNotConstant(FieldIdentifier fi) {
for (Instruction instr = bytecode.getFirstInstr(); for (Instruction instr = bytecode.getFirstInstr();
instr != null; instr = instr.nextByAddr) { instr != null; instr = instr.getNextByAddr()) {
if (instr.opcode == opc_getfield if (instr.getOpcode() == opc_getfield
|| instr.opcode == opc_getstatic) { || instr.getOpcode() == opc_getstatic) {
Reference ref = (Reference) instr.objData; Reference ref = instr.getReference();
if (ref.getName().equals(fi.getName()) if (ref.getName().equals(fi.getName())
&& ref.getType().equals(fi.getType()) && ref.getType().equals(fi.getType())
&& instr.tmpInfo != null) { && instr.getTmpInfo() != null) {
((StackLocalInfo) instr.tmpInfo).enqueue(); ((StackLocalInfo) instr.getTmpInfo()).enqueue();
} }
} }
} }
@ -1370,8 +1370,8 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
public void dumpStackLocalInfo() { public void dumpStackLocalInfo() {
for (Instruction instr = bytecode.getFirstInstr(); for (Instruction instr = bytecode.getFirstInstr();
instr != null; instr = instr.nextByAddr) { instr != null; instr = instr.getNextByAddr()) {
StackLocalInfo info = (StackLocalInfo) instr.tmpInfo; StackLocalInfo info = (StackLocalInfo) instr.getTmpInfo();
System.err.println(""+info); System.err.println(""+info);
System.err.println(instr.getDescription()); System.err.println(instr.getDescription());
} }
@ -1389,7 +1389,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
(bytecode.getMaxLocals(), minfo.isStatic(), minfo.getType(), (bytecode.getMaxLocals(), minfo.isStatic(), minfo.getType(),
modifiedQueue); modifiedQueue);
firstInfo.instr = bytecode.getFirstInstr(); firstInfo.instr = bytecode.getFirstInstr();
firstInfo.instr.tmpInfo = firstInfo; firstInfo.instr.setTmpInfo(firstInfo);
modifiedQueue.add(firstInfo); modifiedQueue.add(firstInfo);
while (!modifiedQueue.isEmpty()) { while (!modifiedQueue.isEmpty()) {
Iterator iter = modifiedQueue.iterator(); Iterator iter = modifiedQueue.iterator();
@ -1400,25 +1400,24 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
Handler[] handlers = bytecode.getExceptionHandlers(); Handler[] handlers = bytecode.getExceptionHandlers();
for (int i=0; i< handlers.length; i++) { for (int i=0; i< handlers.length; i++) {
if (handlers[i].catcher.tmpInfo != null if (handlers[i].catcher.getTmpInfo() != null
&& handlers[i].type != null) && handlers[i].type != null)
Main.getClassBundle().reachableIdentifier(handlers[i].type, false); Main.getClassBundle().reachableIdentifier(handlers[i].type, false);
} }
working = false; working = false;
for (Instruction instr = bytecode.getFirstInstr(); for (Instruction instr = bytecode.getFirstInstr();
instr != null; instr = instr.nextByAddr) instr != null; instr = instr.getNextByAddr())
instr.tmpInfo = null; instr.setTmpInfo(null);
} }
public void insertOnePop(Instruction instr, int count) { public void insertOnePop(Instruction instr, int count) {
/* Add a goto instruction after this opcode. */ /* Add a goto instruction after this opcode. */
Instruction pop = instr.insertInstruction(); Instruction pop
pop.length = 1; = instr.insertInstruction(Instruction.opc_pop - 1 + count);
pop.opcode = Instruction.opc_pop - 1 + count;
} }
public void insertPop(Instruction instr) { public void insertPop(Instruction instr) {
switch(instr.opcode) { switch(instr.getOpcode()) {
case opc_ldc: case opc_ldc:
case opc_ldc2_w: case opc_ldc2_w:
case opc_iload: case opc_lload: case opc_iload: case opc_lload:
@ -1466,23 +1465,23 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
break; break;
case opc_putstatic: case opc_putstatic:
case opc_putfield: case opc_putfield:
if (Type.tType(((Reference)instr.objData).getType()) if (Type.tType(instr.getReference().getType())
.stackSize() == 2) { .stackSize() == 2) {
insertOnePop(instr, 2); insertOnePop(instr, 2);
if (instr.opcode == opc_putfield) if (instr.getOpcode() == opc_putfield)
insertOnePop(instr, 1); insertOnePop(instr, 1);
} else } else
insertOnePop(instr, (instr.opcode == opc_putfield) ? 2 : 1); insertOnePop(instr, (instr.getOpcode() == opc_putfield) ? 2 : 1);
break; break;
case opc_invokespecial: case opc_invokespecial:
case opc_invokestatic: case opc_invokestatic:
case opc_invokeinterface: case opc_invokeinterface:
case opc_invokevirtual: { case opc_invokevirtual: {
Reference ref = (Reference) instr.objData; Reference ref = instr.getReference();
MethodType mt = (MethodType) Type.tType(ref.getType()); MethodType mt = (MethodType) Type.tType(ref.getType());
for (int i=mt.getParameterTypes().length-1; i >=0; i--) for (int i=mt.getParameterTypes().length-1; i >=0; i--)
insertOnePop(instr, mt.getParameterTypes()[i].stackSize()); insertOnePop(instr, mt.getParameterTypes()[i].stackSize());
if (instr.opcode != opc_invokestatic) if (instr.getOpcode() != opc_invokestatic)
insertOnePop(instr, 1); insertOnePop(instr, 1);
} }
} }
@ -1490,30 +1489,24 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
public void appendJump(Instruction instr, Instruction dest) { public void appendJump(Instruction instr, Instruction dest) {
/* Add a goto instruction after this opcode. */ /* Add a goto instruction after this opcode. */
Instruction second = instr.appendInstruction(); instr.appendInstruction(Instruction.opc_goto,
second.alwaysJumps = true; new Instruction[] { dest });
second.opcode = Instruction.opc_goto;
second.length = 3;
second.succs = new Instruction[] { dest };
dest.addPredecessor(second);
} }
public void transformCode(BytecodeInfo bytecode) { public void transformCode(BytecodeInfo bytecode) {
for (Instruction instr = bytecode.getFirstInstr(); for (Instruction instr = bytecode.getFirstInstr();
instr != null; instr = instr.nextByAddr) { instr != null; instr = instr.getNextByAddr()) {
ConstantInfo info = (ConstantInfo) constInfos.get(instr); ConstantInfo info = (ConstantInfo) constInfos.get(instr);
if (info == null || (info.flags & REACHABLE) == 0) { if (info == null || (info.flags & REACHABLE) == 0) {
/* This instruction can't be reached logically */ /* This instruction can't be reached logically */
instr.removeInstruction(); instr.removeInstruction();
} else if ((info.flags & CONSTANT) != 0) { } else if ((info.flags & CONSTANT) != 0) {
insertPop(instr); insertPop(instr);
if (instr.opcode > opc_ldc2_w) { if (instr.getOpcode() > opc_ldc2_w) {
instr.opcode = (info.constant instanceof Long instr.replaceInstruction(info.constant instanceof Long
|| info.constant instanceof Double || info.constant instanceof Double
? opc_ldc2_w : opc_ldc); ? opc_ldc2_w : opc_ldc);
instr.localSlot = -1; instr.setConstant(info.constant);
instr.length = 2;
instr.objData = info.constant;
if (GlobalOptions.verboseLevel > 2) if (GlobalOptions.verboseLevel > 2)
GlobalOptions.err.println GlobalOptions.err.println
(bytecode + ": Replacing " + instr (bytecode + ": Replacing " + instr
@ -1521,79 +1514,68 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
} }
} else if ((info.flags & CONSTANTFLOW) != 0) { } else if ((info.flags & CONSTANTFLOW) != 0) {
Instruction pc = (Instruction) info.constant; Instruction pc = (Instruction) info.constant;
if (instr.opcode >= opc_if_icmpeq if (instr.getOpcode() >= opc_if_icmpeq
&& instr.opcode <= opc_if_acmpne) && instr.getOpcode() <= opc_if_acmpne)
instr.opcode = opc_pop2; instr.replaceInstruction(opc_pop2);
else else
instr.opcode = opc_pop; instr.replaceInstruction(opc_pop);
if (GlobalOptions.verboseLevel > 2) if (GlobalOptions.verboseLevel > 2)
GlobalOptions.err.println GlobalOptions.err.println
(bytecode + ": Replacing " + instr (bytecode + ": Replacing " + instr
+ " with goto " + pc.addr); + " with goto " + pc.getAddr());
instr.alwaysJumps = false; while (instr.getNextByAddr() != null) {
for (int i = 0; i< instr.succs.length; i++)
instr.succs[i].removePredecessor(instr);
instr.succs = null;
instr.length = 1;
while (instr.nextByAddr != null) {
ConstantInfo nextinfo ConstantInfo nextinfo
= (ConstantInfo) constInfos.get(instr.nextByAddr); = (ConstantInfo) constInfos.get(instr.getNextByAddr());
if (nextinfo != null && (nextinfo.flags & REACHABLE) != 0) if (nextinfo != null && (nextinfo.flags & REACHABLE) != 0)
break; break;
/* Next instruction can't be reached logically */ /* Next instruction can't be reached logically */
instr.nextByAddr.removeInstruction(); instr.getNextByAddr().removeInstruction();
} }
if (pc != instr.nextByAddr) { if (pc != instr.getNextByAddr()) {
appendJump(instr, pc); appendJump(instr, pc);
instr = instr.nextByAddr; instr = instr.getNextByAddr();
} }
} else { } else {
int opcode = instr.opcode; int opcode = instr.getOpcode();
switch (opcode) { switch (opcode) {
case opc_nop: case opc_nop:
instr.removeInstruction(); instr.removeInstruction();
break; break;
case opc_goto: case opc_goto:
while (instr.nextByAddr != null) { while (instr.getNextByAddr() != null) {
ConstantInfo nextinfo ConstantInfo nextinfo
= (ConstantInfo) constInfos.get(instr.nextByAddr); = (ConstantInfo) constInfos.get(instr.getNextByAddr());
if (nextinfo != null if (nextinfo != null
&& (nextinfo.flags & REACHABLE) != 0) && (nextinfo.flags & REACHABLE) != 0)
break; break;
/* Next instruction can't be reached logically */ /* Next instruction can't be reached logically */
instr.nextByAddr.removeInstruction(); instr.getNextByAddr().removeInstruction();
} }
if (instr.succs[0] == instr.nextByAddr) if (instr.getSuccs()[0] == instr.getNextByAddr())
instr.removeInstruction(); instr.removeInstruction();
break; break;
case opc_ifeq: case opc_ifne: case opc_ifeq: case opc_ifne:
case opc_iflt: case opc_ifge: case opc_iflt: case opc_ifge:
case opc_ifgt: case opc_ifle: case opc_ifgt: case opc_ifle:
case opc_ifnull: case opc_ifnonnull: case opc_ifnull: case opc_ifnonnull:
if (instr.succs[0] == instr.nextByAddr) { if (instr.getSuccs()[0] == instr.getNextByAddr())
instr.opcode = opc_pop; instr.replaceInstruction(opc_pop);
instr.succs[0].removePredecessor(instr);
instr.succs = null;
}
break; break;
case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpeq: case opc_if_icmpne:
case opc_if_icmplt: case opc_if_icmpge: case opc_if_icmplt: case opc_if_icmpge:
case opc_if_icmpgt: case opc_if_icmple: case opc_if_icmpgt: case opc_if_icmple:
case opc_if_acmpeq: case opc_if_acmpne: case opc_if_acmpeq: case opc_if_acmpne:
if (instr.succs[0] == instr.nextByAddr) { if (instr.getSuccs()[0] == instr.getNextByAddr())
instr.opcode = opc_pop2; instr.replaceInstruction(opc_pop2);
instr.succs[0].removePredecessor(instr);
instr.succs = null;
}
break; break;
case opc_putstatic: case opc_putstatic:
case opc_putfield: { case opc_putfield: {
Reference ref = (Reference) instr.objData; Reference ref = instr.getReference();
FieldIdentifier fi = (FieldIdentifier) FieldIdentifier fi = (FieldIdentifier)
Main.getClassBundle().getIdentifier(ref); Main.getClassBundle().getIdentifier(ref);
if (fi != null if (fi != null

@ -122,14 +122,14 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
} }
public int getFirstAddr() { public int getFirstAddr() {
int addr = Integer.MAX_VALUE; int minAddr = Integer.MAX_VALUE;
Enumeration enum = usingInstrs.elements(); Enumeration enum = usingInstrs.elements();
while (enum.hasMoreElements()) { while (enum.hasMoreElements()) {
InstrInfo instr = (InstrInfo) enum.nextElement(); InstrInfo info = (InstrInfo) enum.nextElement();
if (instr.instr.addr < addr) if (info.instr.getAddr() < minAddr)
addr = instr.instr.addr; minAddr = info.instr.getAddr();
} }
return addr; return minAddr;
} }
} }
@ -221,14 +221,14 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
BitSet mergeSet, boolean inverted) { BitSet mergeSet, boolean inverted) {
InstrInfo preInfo = (InstrInfo) instrInfos.get(preInstr); InstrInfo preInfo = (InstrInfo) instrInfos.get(preInstr);
int omitLocal = -1; int omitLocal = -1;
if (preInstr.localSlot != -1 if (preInstr.getLocalSlot() != -1
&& preInstr.opcode >= opc_istore && preInstr.getOpcode() >= opc_istore
&& preInstr.opcode <= opc_astore) { && preInstr.getOpcode() <= opc_astore) {
/* This is a store */ /* This is a store */
omitLocal = preInstr.localSlot; omitLocal = preInstr.getLocalSlot();
if (info.nextReads[preInstr.localSlot] != null) if (info.nextReads[preInstr.getLocalSlot()] != null)
preInfo.local.combineInto preInfo.local.combineInto
(info.nextReads[preInstr.localSlot].local); (info.nextReads[preInstr.getLocalSlot()].local);
} }
for (int i=0; i < maxlocals; i++) { for (int i=0; i < maxlocals; i++) {
if (info.nextReads[i] != null && i != omitLocal if (info.nextReads[i] != null && i != omitLocal
@ -254,8 +254,8 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
LocalVariableInfo match = null; LocalVariableInfo match = null;
for (int i=0; i < lvt.length; i++) { for (int i=0; i < lvt.length; i++) {
if (lvt[i].slot == slot if (lvt[i].slot == slot
&& lvt[i].start.addr <= addr && lvt[i].start.getAddr() <= addr
&& lvt[i].end.addr >= addr) { && lvt[i].end.getAddr() >= addr) {
if (match != null if (match != null
&& (!match.name.equals(lvt[i].name) && (!match.name.equals(lvt[i].name)
|| !match.type.equals(lvt[i].type))) { || !match.type.equals(lvt[i].type))) {
@ -270,11 +270,11 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
public LocalVariableInfo findLVTEntry(LocalVariableInfo[] lvt, public LocalVariableInfo findLVTEntry(LocalVariableInfo[] lvt,
Instruction instr) { Instruction instr) {
int addr = instr.addr; int addr = instr.getAddr();
if (instr.opcode >= opc_istore if (instr.getOpcode() >= opc_istore
&& instr.opcode <= opc_astore) && instr.getOpcode() <= opc_astore)
addr += instr.length; addr += instr.getLength();
return findLVTEntry(lvt, instr.localSlot, addr); return findLVTEntry(lvt, instr.getLocalSlot(), addr);
} }
public void calcLocalInfo() { public void calcLocalInfo() {
@ -331,7 +331,7 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
instrInfos.put(instr, info); instrInfos.put(instr, info);
info.instr = instr; info.instr = instr;
info.nextReads = new InstrInfo[maxlocals]; info.nextReads = new InstrInfo[maxlocals];
if (instr.localSlot != -1) { if (instr.getLocalSlot() != -1) {
info.local = new LocalInfo(info); info.local = new LocalInfo(info);
if (lvt != null) { if (lvt != null) {
LocalVariableInfo lvi = findLVTEntry(lvt, instr); LocalVariableInfo lvi = findLVTEntry(lvt, instr);
@ -341,21 +341,21 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
} }
} }
info.local.size = 1; info.local.size = 1;
switch (instr.opcode) { switch (instr.getOpcode()) {
case opc_lload: case opc_dload: case opc_lload: case opc_dload:
info.local.size = 2; info.local.size = 2;
/* fall through */ /* fall through */
case opc_iload: case opc_fload: case opc_aload: case opc_iload: case opc_fload: case opc_aload:
case opc_iinc: case opc_iinc:
/* this is a load instruction */ /* this is a load instruction */
info.nextReads[instr.localSlot] = info; info.nextReads[instr.getLocalSlot()] = info;
changedInfos.push(info); changedInfos.push(info);
break; break;
case opc_ret: case opc_ret:
/* this is a ret instruction */ /* this is a ret instruction */
info.usedBySub = new BitSet(); info.usedBySub = new BitSet();
info.nextReads[instr.localSlot] = info; info.nextReads[instr.getLocalSlot()] = info;
changedInfos.push(info); changedInfos.push(info);
break; break;
@ -364,7 +364,7 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
//case opc_istore: case opc_fstore: case opc_astore: //case opc_istore: case opc_fstore: case opc_astore:
} }
} }
if ((instr = instr.nextByAddr) == null) if ((instr = instr.getNextByAddr()) == null)
break; break;
info = info.nextInfo = new InstrInfo(); info = info.nextInfo = new InstrInfo();
} }
@ -377,12 +377,12 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
Instruction instr = info.instr; Instruction instr = info.instr;
/* Mark the local as used in all ret instructions */ /* Mark the local as used in all ret instructions */
if (instr.localSlot != -1) { if (instr.getLocalSlot() != -1) {
for (int i=0; i< maxlocals; i++) { for (int i=0; i< maxlocals; i++) {
InstrInfo retInfo = info.nextReads[i]; InstrInfo retInfo = info.nextReads[i];
if (retInfo != null && retInfo.instr.opcode == opc_ret if (retInfo != null && retInfo.instr.getOpcode() == opc_ret
&& !retInfo.usedBySub.get(instr.localSlot)) { && !retInfo.usedBySub.get(instr.getLocalSlot())) {
retInfo.usedBySub.set(instr.localSlot); retInfo.usedBySub.set(instr.getLocalSlot());
if (retInfo.jsrTargetInfo != null) if (retInfo.jsrTargetInfo != null)
changedInfos.push(retInfo.jsrTargetInfo); changedInfos.push(retInfo.jsrTargetInfo);
} }
@ -390,14 +390,14 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
} }
} }
Instruction prevInstr = instr.prevByAddr; Instruction prevInstr = instr.getPrevByAddr();
if (prevInstr != null) { if (prevInstr != null) {
if (prevInstr.opcode == opc_jsr) { if (prevInstr.getOpcode() == opc_jsr) {
/* Prev instr is a jsr, promote reads to the /* Prev instr is a jsr, promote reads to the
* corresponding ret. * corresponding ret.
*/ */
InstrInfo jsrInfo = InstrInfo jsrInfo =
(InstrInfo) instrInfos.get(prevInstr.succs[0]); (InstrInfo) instrInfos.get(prevInstr.getSuccs()[0]);
if (jsrInfo.retInfo != null) { if (jsrInfo.retInfo != null) {
/* Now promote reads that are modified by the /* Now promote reads that are modified by the
* subroutine to the ret, and those that are not * subroutine to the ret, and those that are not
@ -408,17 +408,17 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
promoteReads(info, prevInstr, promoteReads(info, prevInstr,
jsrInfo.retInfo.usedBySub, true); jsrInfo.retInfo.usedBySub, true);
} }
} else if (!prevInstr.alwaysJumps) } else if (!prevInstr.doesAlwaysJump())
promoteReads(info, prevInstr); promoteReads(info, prevInstr);
} }
if (instr.preds != null) { if (instr.getPreds() != null) {
for (int i = 0; i < instr.preds.length; i++) { for (int i = 0; i < instr.getPreds().length; i++) {
Instruction predInstr = instr.preds[i]; Instruction predInstr = instr.getPreds()[i];
if (instr.preds[i].opcode == opc_jsr) { if (instr.getPreds()[i].getOpcode() == opc_jsr) {
/* This is the target of a jsr instr. /* This is the target of a jsr instr.
*/ */
if (info.instr.opcode != opc_astore) { if (info.instr.getOpcode() != opc_astore) {
/* XXX Grrr, the bytecode verifier doesn't /* XXX Grrr, the bytecode verifier doesn't
* test if a jsr starts with astore. So * test if a jsr starts with astore. So
* it is possible to do something else * it is possible to do something else
@ -427,10 +427,10 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
throw new AssertError("Non standard jsr"); throw new AssertError("Non standard jsr");
} }
InstrInfo retInfo InstrInfo retInfo
= info.nextInfo.nextReads[info.instr.localSlot]; = info.nextInfo.nextReads[info.instr.getLocalSlot()];
if (retInfo != null) { if (retInfo != null) {
if (retInfo.instr.opcode != opc_ret) if (retInfo.instr.getOpcode() != opc_ret)
throw new AssertError throw new AssertError
("reading return address"); ("reading return address");
@ -442,7 +442,7 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
* they are modified by the subroutine, * they are modified by the subroutine,
* and to the jsr instruction otherwise. * and to the jsr instruction otherwise.
*/ */
Instruction nextInstr = predInstr.nextByAddr; Instruction nextInstr = predInstr.getNextByAddr();
InstrInfo nextInfo InstrInfo nextInfo
= (InstrInfo) instrInfos.get(nextInstr); = (InstrInfo) instrInfos.get(nextInstr);
@ -453,15 +453,15 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
retInfo.usedBySub, true); retInfo.usedBySub, true);
} }
} }
promoteReads(info, instr.preds[i]); promoteReads(info, instr.getPreds()[i]);
} }
} }
for (int i=0; i < handlers.length; i++) { for (int i=0; i < handlers.length; i++) {
if (handlers[i].catcher == instr) { if (handlers[i].catcher == instr) {
for (Instruction preInstr = handlers[i].start; for (Instruction preInstr = handlers[i].start;
preInstr != handlers[i].end.nextByAddr; preInstr != handlers[i].end.getNextByAddr();
preInstr = preInstr.nextByAddr) { preInstr = preInstr.getNextByAddr()) {
promoteReads(info, preInstr); promoteReads(info, preInstr);
} }
} }
@ -485,21 +485,17 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
if (info.local != null && info.local.usingInstrs.size() == 1) { if (info.local != null && info.local.usingInstrs.size() == 1) {
/* If this is a store, whose value is never read; it can /* If this is a store, whose value is never read; it can
* be removed, i.e replaced by a pop. */ * be removed, i.e replaced by a pop. */
switch (info.instr.opcode) { switch (info.instr.getOpcode()) {
case opc_istore: case opc_istore:
case opc_fstore: case opc_fstore:
case opc_astore: case opc_astore:
info.local = null; info.local = null;
info.instr.opcode = opc_pop; info.instr.replaceInstruction(opc_pop);
info.instr.length = 1;
info.instr.localSlot = -1;
break; break;
case opc_lstore: case opc_lstore:
case opc_dstore: case opc_dstore:
info.local = null; info.local = null;
info.instr.opcode = opc_pop2; info.instr.replaceInstruction(opc_pop);
info.instr.length = 1;
info.instr.localSlot = -1;
break; break;
default: default:
} }
@ -572,9 +568,9 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
/* Now calculate the conflict settings. /* Now calculate the conflict settings.
*/ */
for (InstrInfo info = firstInfo; info != null; info = info.nextInfo) { for (InstrInfo info = firstInfo; info != null; info = info.nextInfo) {
if (info.instr.localSlot != -1 if (info.instr.getLocalSlot() != -1
&& info.instr.opcode >= BytecodeInfo.opc_istore && info.instr.getOpcode() >= BytecodeInfo.opc_istore
&& info.instr.opcode <= BytecodeInfo.opc_astore) { && info.instr.getOpcode() <= BytecodeInfo.opc_astore) {
/* This is a store. It conflicts with every local, whose /* This is a store. It conflicts with every local, whose
* value will be read without write. * value will be read without write.
* *
@ -583,13 +579,13 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
* would conflict with. * would conflict with.
*/ */
for (int i=0; i < maxlocals; i++) { for (int i=0; i < maxlocals; i++) {
if (i != info.instr.localSlot if (i != info.instr.getLocalSlot()
&& info.nextReads[i] != null) && info.nextReads[i] != null)
info.local.conflictsWith(info.nextReads[i].local); info.local.conflictsWith(info.nextReads[i].local);
if (info.nextInfo.nextReads[i] != null if (info.nextInfo.nextReads[i] != null
&& info.nextInfo.nextReads[i].jsrTargetInfo != null) { && info.nextInfo.nextReads[i].jsrTargetInfo != null) {
Instruction[] jsrs = info.nextInfo.nextReads[i] Instruction[] jsrs = info.nextInfo.nextReads[i]
.jsrTargetInfo.instr.preds; .jsrTargetInfo.instr.getPreds();
for (int j=0; j< jsrs.length; j++) { for (int j=0; j< jsrs.length; j++) {
InstrInfo jsrInfo InstrInfo jsrInfo
= (InstrInfo) instrInfos.get(jsrs[j]); = (InstrInfo) instrInfos.get(jsrs[j]);
@ -627,7 +623,7 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
if (info.local != null) { if (info.local != null) {
if (info.local.newSlot+info.local.size > maxlocals) if (info.local.newSlot+info.local.size > maxlocals)
maxlocals = info.local.newSlot + info.local.size; maxlocals = info.local.newSlot + info.local.size;
info.instr.localSlot = info.local.newSlot; info.instr.setLocalSlot(info.local.newSlot);
} }
} }
bc.setMaxLocals(maxlocals); bc.setMaxLocals(maxlocals);
@ -675,7 +671,7 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
if (info.local != null) { if (info.local != null) {
for (int i=0; i < info.nextReads.length; i++) { for (int i=0; i < info.nextReads.length; i++) {
if (info.nextReads[i] != null if (info.nextReads[i] != null
&& info.nextReads[i].instr.opcode == opc_ret) && info.nextReads[i].instr.getOpcode() == opc_ret)
info.nextReads[i].usedBySub.set(info.local.newSlot); info.nextReads[i].usedBySub.set(info.local.newSlot);
} }
} }
@ -696,13 +692,13 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
InstrInfo info = (InstrInfo) changedInfo.pop(); InstrInfo info = (InstrInfo) changedInfo.pop();
Instruction instr = info.instr; Instruction instr = info.instr;
LocalInfo[] newLife = info.lifeLocals; LocalInfo[] newLife = info.lifeLocals;
if (instr.localSlot != -1) { if (instr.getLocalSlot() != -1) {
LocalInfo instrLocal = info.local.getReal(); LocalInfo instrLocal = info.local.getReal();
newLife = (LocalInfo[]) newLife.clone(); newLife = (LocalInfo[]) newLife.clone();
newLife[instr.localSlot] = instrLocal; newLife[instr.getLocalSlot()] = instrLocal;
if (instrLocal.name != null) { if (instrLocal.name != null) {
for (int j=0; j< newLife.length; j++) { for (int j=0; j< newLife.length; j++) {
if (j != instr.localSlot if (j != instr.getLocalSlot()
&& newLife[j] != null && newLife[j] != null
&& instrLocal.name.equals(newLife[j].name)) { && instrLocal.name.equals(newLife[j].name)) {
/* This local changed the slot. */ /* This local changed the slot. */
@ -712,22 +708,22 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
} }
} }
if (!instr.alwaysJumps) { if (!instr.doesAlwaysJump()) {
InstrInfo nextInfo = info.nextInfo; InstrInfo nextInfo = info.nextInfo;
if (promoteLifeLocals(newLife, nextInfo)) if (promoteLifeLocals(newLife, nextInfo))
changedInfo.push(nextInfo); changedInfo.push(nextInfo);
} }
if (instr.succs != null) { if (instr.getSuccs() != null) {
for (int i = 0; i < instr.succs.length; i++) { for (int i = 0; i < instr.getSuccs().length; i++) {
InstrInfo nextInfo InstrInfo nextInfo
= (InstrInfo) instrInfos.get(instr.succs[i]); = (InstrInfo) instrInfos.get(instr.getSuccs()[i]);
if (promoteLifeLocals(newLife, nextInfo)) if (promoteLifeLocals(newLife, nextInfo))
changedInfo.push(nextInfo); changedInfo.push(nextInfo);
} }
} }
for (int i=0; i < handlers.length; i++) { for (int i=0; i < handlers.length; i++) {
if (handlers[i].start.addr <= instr.addr if (handlers[i].start.getAddr() <= instr.getAddr()
&& handlers[i].end.addr >= instr.addr) { && handlers[i].end.getAddr() >= instr.getAddr()) {
InstrInfo nextInfo InstrInfo nextInfo
= (InstrInfo) instrInfos.get(handlers[i].catcher); = (InstrInfo) instrInfos.get(handlers[i].catcher);
if (promoteLifeLocals(newLife, nextInfo)) if (promoteLifeLocals(newLife, nextInfo))
@ -735,10 +731,10 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
} }
} }
if (info.instr.opcode == opc_jsr) { if (info.instr.getOpcode() == opc_jsr) {
/* On a jsr we do a special merge */ /* On a jsr we do a special merge */
Instruction jsrTargetInstr = info.instr.succs[0]; Instruction jsrTargetInstr = info.instr.getSuccs()[0];
InstrInfo jsrTargetInfo InstrInfo jsrTargetInfo
= (InstrInfo) instrInfos.get(jsrTargetInstr); = (InstrInfo) instrInfos.get(jsrTargetInstr);
InstrInfo retInfo = jsrTargetInfo.retInfo; InstrInfo retInfo = jsrTargetInfo.retInfo;
@ -757,9 +753,9 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
/* On a ret we do a special merge */ /* On a ret we do a special merge */
Instruction jsrTargetInstr = info.jsrTargetInfo.instr; Instruction jsrTargetInstr = info.jsrTargetInfo.instr;
for (int j=0; j< jsrTargetInstr.preds.length; j++) { for (int j=0; j< jsrTargetInstr.getPreds().length; j++) {
InstrInfo jsrInfo InstrInfo jsrInfo
= (InstrInfo) instrInfos.get(jsrTargetInstr.preds[j]); = (InstrInfo) instrInfos.get(jsrTargetInstr.getPreds()[j]);
if (jsrInfo.lifeLocals == null) if (jsrInfo.lifeLocals == null)
/* life locals are not calculated, yet */ /* life locals are not calculated, yet */
@ -803,7 +799,7 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
|| !lcl.name.equals(currentLocal[i].name) || !lcl.name.equals(currentLocal[i].name)
|| !lcl.type.equals(currentLocal[i].type))) { || !lcl.type.equals(currentLocal[i].type))) {
if (lvi[i] != null) { if (lvi[i] != null) {
lvi[i].end = info.instr.prevByAddr; lvi[i].end = info.instr.getPrevByAddr();
} }
lvi[i] = null; lvi[i] = null;
currentLocal[i] = lcl; currentLocal[i] = lcl;
@ -840,15 +836,15 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
if (info.nextReads[i] == null) if (info.nextReads[i] == null)
GlobalOptions.err.print("-,"); GlobalOptions.err.print("-,");
else else
GlobalOptions.err.print(info.nextReads[i].instr.addr+","); GlobalOptions.err.print(info.nextReads[i].instr.getAddr()+",");
if (info.usedBySub != null) if (info.usedBySub != null)
GlobalOptions.err.print(" usedBySub: "+info.usedBySub); GlobalOptions.err.print(" usedBySub: "+info.usedBySub);
if (info.retInfo != null) if (info.retInfo != null)
GlobalOptions.err.print(" ret info: " GlobalOptions.err.print(" ret info: "
+info.retInfo.instr.addr); +info.retInfo.instr.getAddr());
if (info.jsrTargetInfo != null) if (info.jsrTargetInfo != null)
GlobalOptions.err.print(" jsr info: " GlobalOptions.err.print(" jsr info: "
+info.jsrTargetInfo.instr.addr); +info.jsrTargetInfo.instr.getAddr());
GlobalOptions.err.println(); GlobalOptions.err.println();
if (info.local != null && !locals.contains(info.local)) if (info.local != null && !locals.contains(info.local))
@ -858,7 +854,7 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
while (enum.hasMoreElements()) { while (enum.hasMoreElements()) {
LocalInfo li = (LocalInfo) enum.nextElement(); LocalInfo li = (LocalInfo) enum.nextElement();
int slot = ((InstrInfo)li.usingInstrs.elementAt(0)) int slot = ((InstrInfo)li.usingInstrs.elementAt(0))
.instr.localSlot; .instr.getLocalSlot();
GlobalOptions.err.print("Slot: "+slot+" conflicts:"); GlobalOptions.err.print("Slot: "+slot+" conflicts:");
Enumeration enum1 = li.conflictingLocals.elements(); Enumeration enum1 = li.conflictingLocals.elements();
while (enum1.hasMoreElements()) { while (enum1.hasMoreElements()) {
@ -871,7 +867,7 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
Enumeration enum2 = li.usingInstrs.elements(); Enumeration enum2 = li.usingInstrs.elements();
while (enum2.hasMoreElements()) while (enum2.hasMoreElements())
GlobalOptions.err.print(((InstrInfo)enum2.nextElement()) GlobalOptions.err.print(((InstrInfo)enum2.nextElement())
.instr.addr+", "); .instr.getAddr()+", ");
GlobalOptions.err.println(); GlobalOptions.err.println();
} }
GlobalOptions.err.println("-----------"); GlobalOptions.err.println("-----------");

@ -189,14 +189,15 @@ public class MethodIdentifier extends Identifier implements Opcodes {
} }
for (Instruction instr = bytecode.getFirstInstr(); for (Instruction instr = bytecode.getFirstInstr();
instr != null; instr = instr.nextByAddr) { instr != null; instr = instr.getNextByAddr()) {
switch (instr.opcode) { switch (instr.getOpcode()) {
case opc_invokespecial: case opc_invokespecial:
case opc_invokestatic: case opc_invokestatic:
case opc_invokeinterface: case opc_invokeinterface:
case opc_invokevirtual: { case opc_invokevirtual: {
instr.objData = Main.getClassBundle() instr.setReference
.getReferenceAlias((Reference) instr.objData); (Main.getClassBundle()
.getReferenceAlias(instr.getReference()));
break; break;
} }
@ -204,16 +205,18 @@ public class MethodIdentifier extends Identifier implements Opcodes {
case opc_putfield: case opc_putfield:
case opc_getstatic: case opc_getstatic:
case opc_getfield: { case opc_getfield: {
instr.objData = Main.getClassBundle() instr.setReference
.getReferenceAlias((Reference) instr.objData); (Main.getClassBundle()
.getReferenceAlias(instr.getReference()));
break; break;
} }
case opc_new: case opc_new:
case opc_checkcast: case opc_checkcast:
case opc_instanceof: case opc_instanceof:
case opc_multianewarray: { case opc_multianewarray: {
instr.objData = Main.getClassBundle() instr.setClazzType
.getTypeAlias((String) instr.objData); (Main.getClassBundle()
.getTypeAlias(instr.getClazzType()));
break; break;
} }
} }

@ -21,8 +21,6 @@ package jode.obfuscator;
import jode.bytecode.*; import jode.bytecode.*;
import jode.AssertError; import jode.AssertError;
import jode.GlobalOptions; import jode.GlobalOptions;
import jode.type.MethodType;
import jode.type.Type;
public class RemovePopAnalyzer implements CodeTransformer, Opcodes { public class RemovePopAnalyzer implements CodeTransformer, Opcodes {
public RemovePopAnalyzer() { public RemovePopAnalyzer() {
@ -35,15 +33,15 @@ public class RemovePopAnalyzer implements CodeTransformer, Opcodes {
} }
static Instruction shrinkPop(Instruction popInstr, int amount) { static Instruction shrinkPop(Instruction popInstr, int amount) {
int newPop = popInstr.opcode - (opc_pop-1) - amount; int newPop = popInstr.getOpcode() - (opc_pop-1) - amount;
if (newPop < 0) if (newPop < 0)
throw new jode.AssertError("pop1 on long or double"); throw new jode.AssertError("pop1 on long or double");
if (newPop == 0) { if (newPop == 0) {
Instruction nextInstr = popInstr.nextByAddr; Instruction nextInstr = popInstr.getNextByAddr();
popInstr.removeInstruction(); popInstr.removeInstruction();
return nextInstr; return nextInstr;
} }
popInstr.opcode = opc_pop - 1 + newPop; popInstr.replaceInstruction(opc_pop - 1 + newPop);
return popInstr; return popInstr;
} }
@ -51,9 +49,9 @@ public class RemovePopAnalyzer implements CodeTransformer, Opcodes {
int poppush[] = new int[2]; int poppush[] = new int[2];
Instruction instr = bytecode.getFirstInstr(); Instruction instr = bytecode.getFirstInstr();
while (instr != null) { while (instr != null) {
switch (instr.opcode) { switch (instr.getOpcode()) {
case opc_nop: { case opc_nop: {
Instruction nextInstr = instr.nextByAddr; Instruction nextInstr = instr.getNextByAddr();
instr.removeInstruction(); instr.removeInstruction();
instr = nextInstr; instr = nextInstr;
continue; continue;
@ -64,14 +62,14 @@ public class RemovePopAnalyzer implements CodeTransformer, Opcodes {
int count = 0; int count = 0;
Instruction pushInstr = instr; Instruction pushInstr = instr;
while (true) { while (true) {
if (pushInstr.preds != null) { if (pushInstr.getPreds() != null) {
pushInstr = null; pushInstr = null;
break; break;
} }
pushInstr = pushInstr.prevByAddr; pushInstr = pushInstr.getPrevByAddr();
if (pushInstr == null if (pushInstr == null
|| pushInstr.succs != null || pushInstr.getSuccs() != null
|| pushInstr.alwaysJumps) { || pushInstr.doesAlwaysJump()) {
pushInstr = null; pushInstr = null;
break; break;
} }
@ -80,7 +78,7 @@ public class RemovePopAnalyzer implements CodeTransformer, Opcodes {
break; break;
count += poppush[0] - poppush[1]; count += poppush[0] - poppush[1];
} }
int opcode = pushInstr == null ? -1 : pushInstr.opcode; int opcode = pushInstr == null ? -1 : pushInstr.getOpcode();
if (count > 0) { if (count > 0) {
/* If this is a dup and the instruction popped is the /* If this is a dup and the instruction popped is the
@ -92,7 +90,7 @@ public class RemovePopAnalyzer implements CodeTransformer, Opcodes {
continue; continue;
} }
if (instr.opcode == opc_pop2 if (instr.getOpcode() == opc_pop2
&& count > 1 && count <= 3 && count > 1 && count <= 3
&& opcode == (opc_dup2 + count-2)) { && opcode == (opc_dup2 + count-2)) {
pushInstr.removeInstruction(); pushInstr.removeInstruction();
@ -118,16 +116,16 @@ public class RemovePopAnalyzer implements CodeTransformer, Opcodes {
case opc_iaload: case opc_faload: case opc_aaload: case opc_iaload: case opc_faload: case opc_aaload:
case opc_baload: case opc_caload: case opc_saload: case opc_baload: case opc_caload: case opc_saload:
/* We have to pop one entry more. */ /* We have to pop one entry more. */
pushInstr.opcode = opc_pop; pushInstr.replaceInstruction(opc_pop);
instr = pushInstr; instr = pushInstr;
continue; continue;
case opc_dup_x1: case opc_dup_x1:
pushInstr.opcode = opc_swap; pushInstr.replaceInstruction(opc_swap);
instr = shrinkPop(instr, 1); instr = shrinkPop(instr, 1);
continue; continue;
case opc_dup2: case opc_dup2:
if (instr.opcode == opc_pop2) { if (instr.getOpcode() == opc_pop2) {
pushInstr.removeInstruction(); pushInstr.removeInstruction();
instr = shrinkPop(instr, 2); instr = shrinkPop(instr, 2);
} }
@ -136,7 +134,7 @@ public class RemovePopAnalyzer implements CodeTransformer, Opcodes {
case opc_lneg: case opc_dneg: case opc_lneg: case opc_dneg:
case opc_l2d: case opc_d2l: case opc_l2d: case opc_d2l:
case opc_laload: case opc_daload: case opc_laload: case opc_daload:
if (instr.opcode != opc_pop2) if (instr.getOpcode() != opc_pop2)
break; break;
/* fall through */ /* fall through */
case opc_ineg: case opc_fneg: case opc_ineg: case opc_fneg:
@ -158,7 +156,7 @@ public class RemovePopAnalyzer implements CodeTransformer, Opcodes {
case opc_fcmpl: case opc_fcmpg: case opc_fcmpl: case opc_fcmpg:
case opc_l2i: case opc_l2f: case opc_l2i: case opc_l2f:
case opc_d2i: case opc_d2f: case opc_d2i: case opc_d2f:
pushInstr.opcode = opc_pop2; pushInstr.replaceInstruction(opc_pop2);
shrinkPop(instr, 1); shrinkPop(instr, 1);
instr = pushInstr; instr = pushInstr;
continue; continue;
@ -168,44 +166,42 @@ public class RemovePopAnalyzer implements CodeTransformer, Opcodes {
case opc_ldiv: case opc_ddiv: case opc_ldiv: case opc_ddiv:
case opc_lrem: case opc_drem: case opc_lrem: case opc_drem:
case opc_land: case opc_lor : case opc_lxor: case opc_land: case opc_lor : case opc_lxor:
if (instr.opcode != opc_pop2) if (instr.getOpcode() != opc_pop2)
break; break;
pushInstr.opcode = opc_pop2; pushInstr.replaceInstruction(opc_pop2);
instr = pushInstr; instr = pushInstr;
continue; continue;
case opc_lshl: case opc_lshr: case opc_lushr: case opc_lshl: case opc_lshr: case opc_lushr:
if (instr.opcode != opc_pop2) if (instr.getOpcode() != opc_pop2)
break; break;
pushInstr.opcode = opc_pop; pushInstr.replaceInstruction(opc_pop);
instr = pushInstr; instr = pushInstr;
continue; continue;
case opc_i2l: case opc_i2d: case opc_i2l: case opc_i2d:
case opc_f2l: case opc_f2d: case opc_f2l: case opc_f2d:
if (instr.opcode != opc_pop2) if (instr.getOpcode() != opc_pop2)
break; break;
pushInstr.removeInstruction(); pushInstr.removeInstruction();
instr.opcode = opc_pop; instr.replaceInstruction(opc_pop);
continue; continue;
case opc_lcmp: case opc_lcmp:
case opc_dcmpl: case opc_dcmpg: case opc_dcmpl: case opc_dcmpg:
pushInstr.opcode = opc_pop2; pushInstr.replaceInstruction(opc_pop2);
if (instr.opcode == opc_pop) if (instr.getOpcode() == opc_pop)
instr.opcode = opc_pop2; instr.replaceInstruction(opc_pop2);
else { else {
Instruction thirdPop = instr.appendInstruction(); instr.appendInstruction(opc_pop);
thirdPop.length = 1;
thirdPop.opcode = opc_pop;
} }
instr = pushInstr; instr = pushInstr;
continue; continue;
case opc_getstatic: case opc_getstatic:
case opc_getfield: { case opc_getfield: {
Reference ref = (Reference) pushInstr.objData; Reference ref = pushInstr.getReference();
int size = Type.tType(ref.getType()).stackSize(); int size = TypeSignature.getTypeSize(ref.getType());
if (pushInstr.opcode == opc_getfield) if (pushInstr.getOpcode() == opc_getfield)
size--; size--;
pushInstr.removeInstruction(); pushInstr.removeInstruction();
if (size > 0) if (size > 0)
@ -214,18 +210,15 @@ public class RemovePopAnalyzer implements CodeTransformer, Opcodes {
} }
case opc_multianewarray: { case opc_multianewarray: {
int dims = pushInstr.intData; int dims = pushInstr.getIntData();
pushInstr.removeInstruction(); pushInstr.removeInstruction();
if (dims == 0) if (dims == 0)
instr = shrinkPop(instr, 1); instr = shrinkPop(instr, 1);
else { else {
dims--; dims--;
while (dims > 0) { while (dims > 0) {
Instruction aPop = instr.insertInstruction(); instr = instr.insertInstruction(opc_pop);
aPop.length = 1;
aPop.opcode = opc_pop;
dims--; dims--;
instr = aPop;
} }
} }
continue; continue;
@ -235,35 +228,33 @@ public class RemovePopAnalyzer implements CodeTransformer, Opcodes {
case opc_invokespecial: case opc_invokespecial:
case opc_invokestatic: case opc_invokestatic:
case opc_invokeinterface: case opc_invokeinterface:
if (((MethodType) if (TypeSignature.getReturnSize
Type.tType(((Reference) pushInstr.objData).getType())) (pushInstr.getReference().getType()) != 1)
.getReturnType().stackSize() != 1)
break; break;
/* fall through */ /* fall through */
case opc_checkcast: case opc_checkcast:
case -1: case -1:
if (instr.opcode == opc_pop2) { if (instr.getOpcode() == opc_pop2) {
/* This is/may be a double pop on a single value /* This is/may be a double pop on a single value
* split it and continue with second half * split it and continue with second half
*/ */
instr.opcode = opc_pop; instr.replaceInstruction(opc_pop);
instr = instr.appendInstruction(); instr = instr.appendInstruction(opc_pop);
instr.opcode = opc_pop;
instr.length = 1;
continue; continue;
} }
} }
if (instr.opcode == opc_pop && instr.preds == null if (instr.getOpcode() == opc_pop
&& instr.prevByAddr.opcode == opc_pop) { && instr.getPreds() == null
&& instr.getPrevByAddr().getOpcode() == opc_pop) {
/* merge two single pops together. */ /* merge two single pops together. */
instr.prevByAddr.removeInstruction(); instr.getPrevByAddr().removeInstruction();
instr.opcode = opc_pop2; instr.replaceInstruction(opc_pop2);
} }
/* Cant do anything with this pop */ /* Cant do anything with this pop */
} }
/* fall through */ /* fall through */
default: default:
instr = instr.nextByAddr; instr = instr.getNextByAddr();
continue; continue;
} }
} }

@ -30,7 +30,7 @@ import jode.type.Type;
public class SimpleAnalyzer implements CodeAnalyzer, Opcodes { public class SimpleAnalyzer implements CodeAnalyzer, Opcodes {
public Identifier canonizeReference(Instruction instr) { public Identifier canonizeReference(Instruction instr) {
Reference ref = (Reference) instr.objData; Reference ref = instr.getReference();
Identifier ident = Main.getClassBundle().getIdentifier(ref); Identifier ident = Main.getClassBundle().getIdentifier(ref);
String clName = ref.getClazz(); String clName = ref.getClazz();
String realClazzName; String realClazzName;
@ -53,7 +53,7 @@ public class SimpleAnalyzer implements CodeAnalyzer, Opcodes {
(clName.substring(1, clName.length()-1) (clName.substring(1, clName.length()-1)
.replace('/','.')); .replace('/','.'));
} }
if (instr.opcode >= opc_invokevirtual) { if (instr.getOpcode() >= opc_invokevirtual) {
while (clazz != null while (clazz != null
&& clazz.findMethod(ref.getName(), && clazz.findMethod(ref.getName(),
ref.getType()) == null) ref.getType()) == null)
@ -75,7 +75,7 @@ public class SimpleAnalyzer implements CodeAnalyzer, Opcodes {
if (!realClazzName.equals(ref.getClazz())) { if (!realClazzName.equals(ref.getClazz())) {
ref = Reference.getReference(realClazzName, ref = Reference.getReference(realClazzName,
ref.getName(), ref.getType()); ref.getName(), ref.getType());
instr.objData = ref; instr.setReference(ref);
} }
return ident; return ident;
} }
@ -88,12 +88,12 @@ public class SimpleAnalyzer implements CodeAnalyzer, Opcodes {
*/ */
public void analyzeCode(MethodIdentifier m, BytecodeInfo bytecode) { public void analyzeCode(MethodIdentifier m, BytecodeInfo bytecode) {
for (Instruction instr = bytecode.getFirstInstr(); for (Instruction instr = bytecode.getFirstInstr();
instr != null; instr = instr.nextByAddr) { instr != null; instr = instr.getNextByAddr()) {
switch (instr.opcode) { switch (instr.getOpcode()) {
case opc_checkcast: case opc_checkcast:
case opc_instanceof: case opc_instanceof:
case opc_multianewarray: { case opc_multianewarray: {
String clName = (String) instr.objData; String clName = instr.getClazzType();
int i = 0; int i = 0;
while (i < clName.length() && clName.charAt(i) == '[') while (i < clName.length() && clName.charAt(i) == '[')
i++; i++;
@ -115,13 +115,13 @@ public class SimpleAnalyzer implements CodeAnalyzer, Opcodes {
case opc_getfield: { case opc_getfield: {
Identifier ident = canonizeReference(instr); Identifier ident = canonizeReference(instr);
if (ident != null) { if (ident != null) {
if (instr.opcode == opc_putstatic if (instr.getOpcode() == opc_putstatic
|| instr.opcode == opc_putfield) { || instr.getOpcode() == opc_putfield) {
FieldIdentifier fi = (FieldIdentifier) ident; FieldIdentifier fi = (FieldIdentifier) ident;
if (fi != null && !fi.isNotConstant()) if (fi != null && !fi.isNotConstant())
fi.setNotConstant(); fi.setNotConstant();
} else if (instr.opcode == opc_invokevirtual } else if (instr.getOpcode() == opc_invokevirtual
|| instr.opcode == opc_invokeinterface) { || instr.getOpcode() == opc_invokeinterface) {
((ClassIdentifier) ident.getParent()) ((ClassIdentifier) ident.getParent())
.reachableIdentifier(ident.getName(), .reachableIdentifier(ident.getName(),
ident.getType(), true); ident.getType(), true);
@ -144,10 +144,10 @@ public class SimpleAnalyzer implements CodeAnalyzer, Opcodes {
public void transformCode(BytecodeInfo bytecode) { public void transformCode(BytecodeInfo bytecode) {
for (Instruction instr = bytecode.getFirstInstr(); for (Instruction instr = bytecode.getFirstInstr();
instr != null; instr = instr.nextByAddr) { instr != null; instr = instr.getNextByAddr()) {
if (instr.opcode == opc_putstatic if (instr.getOpcode() == opc_putstatic
|| instr.opcode == opc_putfield) { || instr.getOpcode() == opc_putfield) {
Reference ref = (Reference) instr.objData; Reference ref = instr.getReference();
FieldIdentifier fi = (FieldIdentifier) FieldIdentifier fi = (FieldIdentifier)
Main.getClassBundle().getIdentifier(ref); Main.getClassBundle().getIdentifier(ref);
if (fi != null if (fi != null
@ -155,20 +155,16 @@ public class SimpleAnalyzer implements CodeAnalyzer, Opcodes {
&& !fi.isReachable()) { && !fi.isReachable()) {
/* Replace instruction with pop opcodes. */ /* Replace instruction with pop opcodes. */
int stacksize = int stacksize =
(instr.opcode (instr.getOpcode()
== Instruction.opc_putstatic) ? 0 : 1; == Instruction.opc_putstatic) ? 0 : 1;
stacksize += Type.tType(ref.getType()).stackSize(); stacksize += Type.tType(ref.getType()).stackSize();
if (stacksize == 3) { if (stacksize == 3) {
/* Add a pop instruction after this opcode. */ /* Add a pop instruction after this opcode. */
Instruction second = instr.appendInstruction(); instr.appendInstruction(Instruction.opc_pop);
second.length = 1;
second.opcode = Instruction.opc_pop;
stacksize--; stacksize--;
} }
instr.objData = null; instr.replaceInstruction(Instruction.opc_pop - 1
instr.intData = 0; + stacksize);
instr.opcode = Instruction.opc_pop - 1 + stacksize;
instr.length = 1;
} }
} }
} }

Loading…
Cancel
Save