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 25 years ago
parent 2ecb19a3d9
commit 900205e713
  1. 78
      jode/jode/decompiler/DeadCodeAnalysis.java
  2. 3
      jode/jode/decompiler/LocalVariableTable.java
  3. 64
      jode/jode/decompiler/Opcodes.java
  4. 272
      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 {
private final static Object reachable = new Integer(1);
private final static Object reachChanged = new Integer(2);
private final static String REACHABLE = "R";
private final static String REACHCHANGED = "C";
private static void propagateReachability(Instruction firstInstr,
Instruction reachInstr) {
if (reachInstr.tmpInfo != null)
if (reachInstr.getTmpInfo() != null)
return;
reachInstr.tmpInfo = reachChanged;
reachInstr.setTmpInfo(REACHCHANGED);
boolean changed;
do {
changed = false;
for (Instruction instr = firstInstr;
instr != null; instr = instr.nextByAddr) {
if (instr.tmpInfo == reachChanged) {
instr != null; instr = instr.getNextByAddr()) {
if (instr.getTmpInfo() == REACHCHANGED) {
changed = true;
instr.tmpInfo = reachable;
if (instr.succs != null)
for (int i=0; i< instr.succs.length; i++)
if (instr.succs[i].tmpInfo == null)
instr.succs[i].tmpInfo = reachChanged;
if (!instr.alwaysJumps && instr.nextByAddr != null)
if (instr.nextByAddr.tmpInfo == null)
instr.nextByAddr.tmpInfo = reachChanged;
instr.setTmpInfo(REACHABLE);
Instruction[] succs = instr.getSuccs();
if (succs != null)
for (int i=0; i< succs.length; i++)
if (succs[i].getTmpInfo() == null)
succs[i].setTmpInfo(REACHCHANGED);
if (!instr.doesAlwaysJump()
&& instr.getNextByAddr() != null)
if (instr.getNextByAddr().getTmpInfo() == null)
instr.getNextByAddr().setTmpInfo(REACHCHANGED);
/*XXX code after jsr reachable iff ret is reachable...*/
if (instr.opcode == Opcodes.opc_jsr)
if (instr.nextByAddr.tmpInfo == null)
instr.nextByAddr.tmpInfo = reachChanged;
if (instr.getOpcode() == Opcodes.opc_jsr)
if (instr.getNextByAddr().getTmpInfo() == null)
instr.getNextByAddr().setTmpInfo(REACHCHANGED);
}
}
} while (changed);
@ -63,13 +65,13 @@ public class DeadCodeAnalysis {
do {
changed = false;
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
* and mark the catcher as reachable then.
*/
for (Instruction instr = handlers[i].start;
instr != null; instr = instr.nextByAddr) {
if (instr.tmpInfo != null) {
instr != null; instr = instr.getNextByAddr()) {
if (instr.getTmpInfo() != null) {
propagateReachability(code.getFirstInstr(),
handlers[i].catcher);
changed = true;
@ -81,21 +83,10 @@ public class DeadCodeAnalysis {
}
}
} 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++) {
/* 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 */
Handler[] newHandlers = new Handler[handlers.length - 1];
System.arraycopy(handlers, 0, newHandlers, 0, i);
@ -106,15 +97,22 @@ public class DeadCodeAnalysis {
i--;
} else {
/* This works! */
while (handlers[i].start.tmpInfo == null)
handlers[i].start = handlers[i].start.nextByAddr;
while (handlers[i].end.tmpInfo == null)
handlers[i].end = handlers[i].end.prevByAddr;
while (handlers[i].start.getTmpInfo() == null)
handlers[i].start = handlers[i].start.getNextByAddr();
while (handlers[i].end.getTmpInfo() == null)
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();
instr != null; instr = instr.nextByAddr)
instr.tmpInfo = null;
instr != null; instr = nextInstr) {
nextInstr = instr.getNextByAddr();
if (instr.getTmpInfo() == null)
instr.removeInstruction();
else
instr.setTmpInfo(null);
}
}
}

@ -32,7 +32,8 @@ public class LocalVariableTable {
locals[i] = new LocalVariableRangeList();
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));
}

@ -91,14 +91,16 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
private static StructuredBlock createGoto(MethodAnalyzer ma,
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,
Instruction instr)
{
return new JsrBlock(new Jump((FlowBlock)instr.succs[0].tmpInfo),
new Jump(FlowBlock.NEXT_BY_ADDR));
return new JsrBlock
(new Jump((FlowBlock)instr.getSuccs()[0].getTmpInfo()),
new Jump(FlowBlock.NEXT_BY_ADDR));
}
private static StructuredBlock createIfGoto(MethodAnalyzer ma,
@ -106,7 +108,7 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
Expression expr)
{
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));
}
@ -146,21 +148,22 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
MethodAnalyzer ma)
throws ClassFormatError
{
int opcode = instr.opcode;
int opcode = instr.getOpcode();
switch (opcode) {
case opc_nop:
return createBlock(ma, instr, new EmptyBlock
(new Jump(FlowBlock.NEXT_BY_ADDR)));
case opc_ldc:
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_fload: case opc_dload: case opc_aload:
return createNormal
(ma, instr, new LocalLoadOperator
(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_faload: case opc_daload: case opc_aaload:
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
(new LocalStoreOperator
(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_fastore: case opc_dastore: case opc_aastore:
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],
(opcode - opc_iand)/2 + Operator.AND_OP));
case opc_iinc: {
int value = instr.intData;
int value = instr.getIntData();
int operation = Operator.ADD_OP;
if (value < 0) {
value = -value;
operation = Operator.SUB_OP;
}
LocalInfo li = ma.getLocalInfo(instr.addr, instr.localSlot);
LocalInfo li
= ma.getLocalInfo(instr.getAddr(), instr.getLocalSlot());
return createNormal
(ma, instr, new IIncOperator
(new LocalStoreOperator(Type.tInt, li),
@ -287,24 +292,27 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
return createJsr(ma, instr);
case opc_ret:
return createRet
(ma, instr, ma.getLocalInfo(instr.addr, instr.localSlot));
(ma, instr,
ma.getLocalInfo(instr.getAddr(), instr.getLocalSlot()));
case opc_tableswitch: {
int low = instr.intData;
int[] cases = new int[instr.succs.length-1];
FlowBlock[] dests = new FlowBlock[instr.succs.length];
int low = instr.getIntData();
int[] cases = new int[instr.getSuccs().length-1];
FlowBlock[] dests = new FlowBlock[instr.getSuccs().length];
for (int i=0; i < cases.length; i++) {
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);
}
case opc_lookupswitch: {
int[] cases = (int[]) instr.objData;
FlowBlock[] dests = new FlowBlock[instr.succs.length];
int[] cases = instr.getValues();
FlowBlock[] dests = new FlowBlock[instr.getSuccs().length];
for (int i=0; i < dests.length; i++)
dests[i] = (FlowBlock) instr.succs[i].tmpInfo;
dests[cases.length] = (FlowBlock)instr.succs[cases.length].tmpInfo;
dests[i] = (FlowBlock) instr.getSuccs()[i].getTmpInfo();
dests[cases.length] = (FlowBlock)
instr.getSuccs()[cases.length].getTmpInfo();
return createSwitch(ma, instr, cases, dests);
}
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)));
case opc_getstatic:
case opc_getfield: {
Reference ref = (Reference) instr.objData;
Reference ref = instr.getReference();
return createNormal
(ma, instr, new GetFieldOperator
(ma, opcode == opc_getstatic, ref));
}
case opc_putstatic:
case opc_putfield: {
Reference ref = (Reference) instr.objData;
Reference ref = instr.getReference();
return createNormal
(ma, instr, new StoreInstruction
(new PutFieldOperator(ma, opcode == opc_putstatic, ref)));
@ -334,7 +342,7 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
case opc_invokespecial:
case opc_invokestatic :
case opc_invokeinterface: {
Reference ref = (Reference) instr.objData;
Reference ref = instr.getReference();
StructuredBlock block = createNormal
(ma, instr, new InvokeOperator
(ma, opcode == opc_invokestatic,
@ -342,7 +350,7 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
return block;
}
case opc_new: {
Type type = Type.tType((String) instr.objData);
Type type = Type.tType(instr.getClazzType());
ma.useType(type);
return createNormal(ma, instr, new NewOperator(type));
}
@ -354,13 +362,13 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
(ma, instr,
new ThrowBlock(new NopOperator(Type.tUObject)));
case opc_checkcast: {
Type type = Type.tType((String) instr.objData);
Type type = Type.tType(instr.getClazzType());
ma.useType(type);
return createNormal
(ma, instr, new CheckCastOperator(type));
}
case opc_instanceof: {
Type type = Type.tType((String) instr.objData);
Type type = Type.tType(instr.getClazzType());
ma.useType(type);
return createNormal
(ma, instr, new InstanceOfOperator(type));
@ -372,9 +380,9 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
return createNormal(ma, instr,
new MonitorExitOperator());
case opc_multianewarray: {
Type type = Type.tType((String) instr.objData);
Type type = Type.tType(instr.getClazzType());
ma.useType(type);
int dimension = instr.intData;
int dimension = instr.getIntData();
return createNormal(ma, instr,
new NewArrayOperator(type, dimension));
}

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

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

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

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

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

Loading…
Cancel
Save