Remove block graph and jump inliner which wasn't used. The loading time for the block graph (because of the way exceptions were looked up) was too slow.

This commit is contained in:
Adam
2015-11-15 18:39:05 -05:00
parent 9a68e863bd
commit 83a51ea037
6 changed files with 1 additions and 233 deletions

View File

@@ -41,7 +41,6 @@ public class Code extends Attribute
this.attributes = new Attributes(this);
this.attributes.load(is);
instructions.buildBlocks();
instructions.buildJumpGraph();
}

View File

@@ -2,19 +2,16 @@ package net.runelite.deob.attributes.code;
import java.io.DataInputStream;
import net.runelite.deob.ConstantPool;
import net.runelite.deob.block.Block;
import net.runelite.deob.execution.Frame;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import net.runelite.deob.util.IdGen;
public abstract class Instruction implements Cloneable
{
private Instructions instructions;
public Block block;
private InstructionType type;
private int pc; // offset into method this instructions resides at
@@ -43,7 +40,6 @@ public abstract class Instruction implements Cloneable
throw new RuntimeException();
}
i.block = null;
i.from = new ArrayList<>();
i.jump = new ArrayList<>();
@@ -56,8 +52,6 @@ public abstract class Instruction implements Cloneable
protected void remove()
{
assert block == null;
for (Instruction i : jump)
i.from.remove(this);
jump.clear();
@@ -81,10 +75,6 @@ public abstract class Instruction implements Cloneable
assert ins.contains(this);
assert !ins.contains(other);
// XXX this corrupts the block graph. we shouldn't keep it around once we are done using it,
// too much stuff to keep updated.
this.block = null;
// XXX instructions which hold references to instructions !
for (Instruction i : ins)
{
@@ -130,8 +120,7 @@ public abstract class Instruction implements Cloneable
}
public boolean removeStack()
{
block = null;
{
assert instructions != null;
// update instructions which jump here to jump to the next instruction

View File

@@ -2,7 +2,6 @@ package net.runelite.deob.attributes.code;
import net.runelite.deob.attributes.Code;
import net.runelite.deob.attributes.code.instruction.types.JumpingInstruction;
import net.runelite.deob.block.Block;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
@@ -12,14 +11,11 @@ import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import net.runelite.deob.attributes.code.instructions.Goto;
import net.runelite.deob.attributes.code.instructions.If;
public class Instructions
{
private Code code;
private List<Instruction> instructions = new ArrayList<>();
private List<Block> blocks = new ArrayList<>();
public Instructions(Code code)
{
@@ -76,11 +72,6 @@ public class Instructions
instructions.add(i);
}
public List<Block> getBlocks()
{
return blocks;
}
public void remove(Instruction ins)
{
assert ins.getInstructions() == this;
@@ -89,95 +80,6 @@ public class Instructions
ins.setInstructions(null);
}
public void remove(Block block)
{
blocks.remove(block);
for (Instruction i : block.instructions)
{
i.block = null;
remove(i);
}
}
private void findExceptionInfo(Block block, Instruction i)
{
for (Exception e : code.getExceptions().getExceptions())
{
int startIdx = instructions.indexOf(e.getStart()),
endIdx = instructions.indexOf(e.getEnd()),
thisIdx = instructions.indexOf(i);
assert startIdx != -1;
assert endIdx != -1;
assert thisIdx != -1;
assert endIdx > startIdx;
if (thisIdx >= startIdx && thisIdx < endIdx)
{
if (!block.exceptions.contains(e))
block.exceptions.add(e);
}
if (e.getHandler() == i)
{
block.handlers.add(e);
}
}
}
private boolean isException(Instruction i)
{
for (Exception e : code.getExceptions().getExceptions())
if (e.getHandler() == i || e.getStart() == i)
return true;
return false;
}
private boolean isExceptionEnd(Instruction i)
{
for (Exception e : code.getExceptions().getExceptions())
if (e.getEnd() == i)
return true;
return false;
}
public void buildBlocks()
{
clearBlockGraph();
buildJumpGraph();
Block current = null;
for (int j = 0; j < instructions.size(); ++j)
{
Instruction i = instructions.get(j),
next = j + 1 < instructions.size() ? instructions.get(j + 1) : null;
if (current == null)
{
current = new Block();
current.begin = i;
}
current.instructions.add(i);
findExceptionInfo(current, i);
if (i.isTerminal() || next == null || isException(next) || isExceptionEnd(i) || !next.from.isEmpty())
{
current.end = i;
blocks.add(current);
current = null;
}
}
}
public void clearBlockGraph()
{
for (Instruction i : instructions)
i.block = null;
blocks.clear();
}
public void write(DataOutputStream out) throws IOException
{
// trnaslate instructions to specific

View File

@@ -1,15 +0,0 @@
package net.runelite.deob.block;
import net.runelite.deob.attributes.code.Exception;
import net.runelite.deob.attributes.code.Instruction;
import java.util.ArrayList;
import java.util.List;
public class Block
{
public Instruction begin, end;
public List<Instruction> instructions = new ArrayList<>();
public List<Exception> exceptions = new ArrayList<>(); // is an instruction in the handlers try { }
public List<Exception> handlers = new ArrayList<>(); // first ins is a handler for exception
}

View File

@@ -38,7 +38,6 @@ public class IllegalStateExceptions implements Deobfuscator
assert execution.methods.contains(m);
Instructions instructions = c.getInstructions();
instructions.clearBlockGraph();
instructions.buildJumpGraph();
List<Instruction> ilist = instructions.getInstructions();

View File

@@ -1,106 +0,0 @@
package net.runelite.deob.deobfuscators;
import net.runelite.deob.ClassFile;
import net.runelite.deob.ClassGroup;
import net.runelite.deob.Deobfuscator;
import net.runelite.deob.Method;
import net.runelite.deob.attributes.code.Instruction;
import net.runelite.deob.attributes.code.Instructions;
import net.runelite.deob.attributes.code.instructions.Goto;
import net.runelite.deob.attributes.code.instructions.GotoW;
import net.runelite.deob.block.Block;
import java.util.ArrayList;
import java.util.List;
public class Jumps implements Deobfuscator
{
private int checkBlockGraphOnce(ClassGroup group)
{
int count = 0;
for (ClassFile cf : group.getClasses())
{
methods:
for (Method m : new ArrayList<>(cf.getMethods().getMethods()))
{
if (m.getCode() == null)
continue;
Instructions ins = m.getCode().getInstructions();
ins.buildBlocks();
ins.buildJumpGraph();
List<Block> blocks = ins.getBlocks();
for (int i = 0; i < blocks.size(); ++i)
{
Block block = blocks.get(i);
Block prev = i > 0 ? blocks.get(i - 1) : null;
if (block.begin.from.size() == 1 && block.end.isTerminal() && prev != null && prev.end.isTerminal())
{
// not sure if this is right, just don't mess with blocks in exception ranges or directly handling them
if (block.exceptions.isEmpty() == false || block.handlers.isEmpty() == false || prev.exceptions.isEmpty() == false || prev.handlers.isEmpty() == false)
continue;
Instruction from = block.begin.from.get(0); // this instruction jumps to block
if (from.block == block)
continue;
if (from instanceof Goto || from instanceof GotoW)
{
++count;
List<Instruction> ilist = ins.getInstructions();
// clear jump graph
//ins.clearBlocks();
ins.clearJumpGraph();
// remove instructions
for (Instruction in : block.instructions)
{
boolean b = ilist.remove(in);
assert b;
}
int idx = ilist.indexOf(from);
boolean b = ilist.remove(from);
assert b;
b = ilist.addAll(idx, block.instructions);
assert b;
// replace from with block.begin
for (Instruction ins2 : ilist)
ins2.replace(from, block.begin);
for (net.runelite.deob.attributes.code.Exception e : m.getCode().getExceptions().getExceptions())
e.replace(from, block.begin);
continue methods;
}
}
}
}
}
return count;
}
@Override
public void run(ClassGroup g)
{
int count = 0;
int passes = 0;
int i;
do
{
i = checkBlockGraphOnce(g);
System.out.println("pass " + i);
count += i;
++passes;
}
while (i > 0);
System.out.println("Inlined " + count + " jumps in " + passes + " passes");
}
}