First update, not complete...

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1289 379699f6-c40d-0410-875b-85095c16579e
master
hoenicke 24 years ago
parent 8c85a88d39
commit 31b99cc4f0
  1. 42
      jode/jode/obfuscator/modules/LocalOptimizer.java

@ -33,43 +33,47 @@ import java.util.ListIterator;
/** /**
* This class takes some bytecode and tries to minimize the number * This class takes some bytecode and tries to minimize the number
* of locals used. It will also remove unnecessary stores. * of locals used. It will also remove unnecessary stores. <br>
* *
* This class can only work on verified code. There should also be no * This class can only work on verified code. There should also be no
* deadcode, since the verifier doesn't check that deadcode behaves * dead code, since the verifier doesn't check that dead code behaves
* okay. * okay. <br>
* *
* This is done in two phases. First we determine which locals are * This is done in two phases. First we determine which locals are
* the same, and which locals have a overlapping life time. In the * the same, and which locals have a overlapping life time. In the
* second phase we will then redistribute the locals with a coloring * second phase we will then redistribute the locals with a coloring
* graph algorithm. * graph algorithm. <br>
* *
* The idea for the first phase is: For each read we follow the * The idea for the first phase is: For each read we follow the
* instruction flow backward to find the corresponding writes. We can * instruction flow backward to find the corresponding writes. We can
* also merge with another control flow that has a different read, in * also merge with another control flow that has a different read, in
* this case we merge with that read, too. * this case we merge with that read, too. <br>
* *
* The tricky part is the subroutine handling. We follow the local * The tricky part is the subroutine handling. We follow the local
* that is used in a ret and find the corresponding jsr target (there * that is used in a ret and find the corresponding jsr target (there
* must be only one, if the verifier should accept this class). While * must be only one, if the verifier should accept this class). While
* we do this we remember in the info of the ret, which locals are * we do this we remember in the info of the ret, which locals are
* used in that subroutine. * used in that subroutine. <br>
* *
* When we know the jsr target<->ret correlation, we promote from the * When we know the jsr target<->ret correlation, we promote from the
* nextByAddr of every jsr the locals that are accessed by the * nextByAddr of every jsr the locals that are accessed by the
* subroutine to the corresponding ret and the others to the jsr. Also * subroutine to the corresponding ret and the others to the jsr. Also
* we will promote all reads from the jsr targets to the jsr. * we will promote all reads from the jsr targets to the jsr. <br>
* *
* If you think this might be to complicated, keep in mind that jsr's * If you think this might be to complicated, keep in mind that jsr's
* are not only left by the ret instructions, but also "spontanously" * are not only left by the ret instructions, but also "spontanously"
* (by not reading the return address again). * (by not reading the return address again). <br>
*/ */
public class LocalOptimizer implements Opcodes, CodeTransformer { public class LocalOptimizer implements Opcodes, CodeTransformer {
/** /**
* This class keeps track of which locals must be the same, which * This class keeps track for each local variables:
* name and type each local (if there is a local variable table) and * <ul>
* which other locals have an intersecting life time. * <li>which name and type this local has
* (if there is a local variable table),</li>
* <li>which other locals must be the same,</li>
* <li>which other locals have an intersecting life time.</li>
* </ul>
*/ */
class LocalInfo { class LocalInfo {
LocalInfo shadow = null; LocalInfo shadow = null;
@ -172,12 +176,12 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
int maxlocals; int maxlocals;
/** /**
* This class contains information for each instruction. * This class contains information for each basic block.
*/ */
class BlockInfo { class BlockInfo {
/** /**
* The next changed BlockInfo, or null, if this instr info did * The next Instruction in the todo list; null, if this block
* not changed. * info is not on todo list, or if it is the last one.
*/ */
BlockInfo nextTodo; BlockInfo nextTodo;
@ -309,16 +313,18 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
void promoteIn(int slot, LocalInfo local) { void promoteIn(int slot, LocalInfo local) {
if (gens[slot] == null) { if (gens[slot] == null) {
changedInfos.add(this); changedInfos.add(this);
gens[slot] = local;
ins[slot] = local; ins[slot] = local;
} else { } else {
gens[slot].combineInto(local); gens[slot].combineInto(local);
} }
} }
void promoteInToAll(int slot, LocalInfo local) { void promoteInForTry(int slot, LocalInfo local) {
if (ins[slot] == null) { if (ins[slot] == null) {
changedInfos.add(this); gens[slot] = local;
ins[slot] = local; ins[slot] = local;
changedInfos.add(this);
} else } else
ins[slot].combineInto(local); ins[slot].combineInto(local);
@ -343,7 +349,7 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
for (Iterator iter = tryBlocks.iterator(); for (Iterator iter = tryBlocks.iterator();
iter.hasNext();) { iter.hasNext();) {
BlockInfo pred = (BlockInfo) iter.next(); BlockInfo pred = (BlockInfo) iter.next();
pred.promoteInToAll(i, ins[i]); pred.promoteInForTry(i, ins[i]);
} }
} }
} }
@ -376,7 +382,7 @@ public class LocalOptimizer implements Opcodes, CodeTransformer {
* is active at this point. * is active at this point.
*/ */
for (int i=0; i < maxlocals; i++) { for (int i=0; i < maxlocals; i++) {
if (i != info.instr.getLocalSlot() if (i != instr.getLocalSlot()
&& active[i] != null) && active[i] != null)
instrLocals[instrNr].conflictsWith(active[i]); instrLocals[instrNr].conflictsWith(active[i]);

Loading…
Cancel
Save