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:
@@ -41,7 +41,6 @@ public class Code extends Attribute
|
||||
this.attributes = new Attributes(this);
|
||||
this.attributes.load(is);
|
||||
|
||||
instructions.buildBlocks();
|
||||
instructions.buildJumpGraph();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user