Remove dummy branch expressions instead of inserting POPs

This prevents Fernflower from inserting dummy boolean variables.
pull/48/head
Graham 5 years ago
parent 3242356c80
commit 4cfb9d9f69
  1. 16
      asm/src/main/java/dev/openrs2/asm/InsnNodeUtils.java
  2. 51
      deob/src/main/java/dev/openrs2/deob/transform/DummyArgTransformer.java

@ -308,22 +308,28 @@ public final class InsnNodeUtils {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
public static boolean deleteSimpleExpression(InsnList list, AbstractInsnNode last) { public static boolean replaceSimpleExpression(InsnList list, AbstractInsnNode last, AbstractInsnNode replacement) {
var deadInsns = new ArrayList<AbstractInsnNode>(); var deadInsns = new ArrayList<AbstractInsnNode>();
var height = 0; var height = 0;
var insn = last; var insn = last;
do { do {
deadInsns.add(insn);
var metadata = StackMetadata.get(insn); var metadata = StackMetadata.get(insn);
if (insn != last) { if (insn != last) {
deadInsns.add(insn);
height -= metadata.getPushes(); height -= metadata.getPushes();
} }
height += metadata.getPops(); height += metadata.getPops();
if (height == 0) { if (height == 0) {
deadInsns.forEach(list::remove); deadInsns.forEach(list::remove);
if (replacement != null) {
list.set(last, replacement);
} else {
list.remove(last);
}
return true; return true;
} }
@ -333,6 +339,10 @@ public final class InsnNodeUtils {
return false; return false;
} }
public static boolean deleteSimpleExpression(InsnList list, AbstractInsnNode last) {
return replaceSimpleExpression(list, last, null);
}
private InsnNodeUtils() { private InsnNodeUtils() {
/* empty */ /* empty */
} }

@ -11,6 +11,7 @@ import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import dev.openrs2.asm.InsnNodeUtils;
import dev.openrs2.asm.MemberRef; import dev.openrs2.asm.MemberRef;
import dev.openrs2.asm.classpath.ClassPath; import dev.openrs2.asm.classpath.ClassPath;
import dev.openrs2.asm.transform.Transformer; import dev.openrs2.asm.transform.Transformer;
@ -20,7 +21,6 @@ import dev.openrs2.util.collect.DisjointSet;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.JumpInsnNode; import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.MethodNode;
@ -187,11 +187,8 @@ public final class DummyArgTransformer extends Transformer {
var changed = false; var changed = false;
var alwaysTakenUnaryBranches = new ArrayList<JumpInsnNode>(); var alwaysTakenBranches = new ArrayList<JumpInsnNode>();
var neverTakenUnaryBranches = new ArrayList<JumpInsnNode>(); var neverTakenBranches = new ArrayList<JumpInsnNode>();
var alwaysTakenBinaryBranches = new ArrayList<JumpInsnNode>();
var neverTakenBinaryBranches = new ArrayList<JumpInsnNode>();
for (var i = 0; i < frames.length; i++) { for (var i = 0; i < frames.length; i++) {
var frame = frames[i]; var frame = frames[i];
@ -230,10 +227,10 @@ public final class DummyArgTransformer extends Transformer {
var result = evaluateUnaryBranch(insn.getOpcode(), value.getIntValues()); var result = evaluateUnaryBranch(insn.getOpcode(), value.getIntValues());
switch (result) { switch (result) {
case ALWAYS_TAKEN: case ALWAYS_TAKEN:
alwaysTakenUnaryBranches.add((JumpInsnNode) insn); alwaysTakenBranches.add((JumpInsnNode) insn);
break; break;
case NEVER_TAKEN: case NEVER_TAKEN:
neverTakenUnaryBranches.add((JumpInsnNode) insn); neverTakenBranches.add((JumpInsnNode) insn);
break; break;
} }
break; break;
@ -252,42 +249,28 @@ public final class DummyArgTransformer extends Transformer {
result = evaluateBinaryBranch(insn.getOpcode(), value1.getIntValues(), value2.getIntValues()); result = evaluateBinaryBranch(insn.getOpcode(), value1.getIntValues(), value2.getIntValues());
switch (result) { switch (result) {
case ALWAYS_TAKEN: case ALWAYS_TAKEN:
alwaysTakenBinaryBranches.add((JumpInsnNode) insn); alwaysTakenBranches.add((JumpInsnNode) insn);
break; break;
case NEVER_TAKEN: case NEVER_TAKEN:
neverTakenBinaryBranches.add((JumpInsnNode) insn); neverTakenBranches.add((JumpInsnNode) insn);
break; break;
} }
break; break;
} }
} }
for (var insn : alwaysTakenUnaryBranches) { for (var insn : alwaysTakenBranches) {
method.instructions.insertBefore(insn, new InsnNode(Opcodes.POP)); if (InsnNodeUtils.replaceSimpleExpression(method.instructions, insn, new JumpInsnNode(Opcodes.GOTO, insn.label))) {
method.instructions.set(insn, new JumpInsnNode(Opcodes.GOTO, insn.label)); branchesSimplified++;
branchesSimplified++; changed = true;
changed = true; }
}
for (var insn : neverTakenUnaryBranches) {
method.instructions.set(insn, new InsnNode(Opcodes.POP));
branchesSimplified++;
changed = true;
}
for (var insn : alwaysTakenBinaryBranches) {
method.instructions.insertBefore(insn, new InsnNode(Opcodes.POP));
method.instructions.insertBefore(insn, new InsnNode(Opcodes.POP));
method.instructions.set(insn, new JumpInsnNode(Opcodes.GOTO, insn.label));
branchesSimplified++;
changed = true;
} }
for (var insn : neverTakenBinaryBranches) { for (var insn : neverTakenBranches) {
method.instructions.insertBefore(insn, new InsnNode(Opcodes.POP)); if (InsnNodeUtils.deleteSimpleExpression(method.instructions, insn)) {
method.instructions.set(insn, new InsnNode(Opcodes.POP)); branchesSimplified++;
branchesSimplified++; changed = true;
changed = true; }
} }
return changed; return changed;

Loading…
Cancel
Save