Rewrite regex search so that it pattern checks each instruction without building a string of the whole method first. Regex duration on mobile cpu (i5-7200U) goes down from 2635ms to 430ms for one specific test case.

This commit is contained in:
tiziw 2020-02-12 11:35:01 +01:00
parent 2f65241269
commit 9f142781b0
2 changed files with 78 additions and 48 deletions

View file

@ -255,6 +255,43 @@ public class RegexInsnFinder {
} }
offsets[i] = insnString.length(); offsets[i] = insnString.length();
insnString += opcodes[ain.getOpcode()]; insnString += opcodes[ain.getOpcode()];
insnString = getInsString(ain);
insnString += " ";
}
}
}
// Do a pattern check against each instruction directly,
// without building a string of the whole method.
public static boolean staticScan(ClassNode node, MethodNode mn, Pattern pattern) {
final List<AbstractInsnNode> il = new ArrayList<AbstractInsnNode>();
for (final AbstractInsnNode ain : mn.instructions.toArray())
if (ain.getOpcode() >= 0) {
il.add(ain);
}
return il.stream().anyMatch(ain -> {
if (ain.getOpcode() >= 0) {
if (ain.getOpcode() >= opcodes.length) {
try {
throw new UnexpectedException(
"Unknown opcode encountered: "
+ ain.getOpcode());
} catch (final UnexpectedException e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
}
}
String insnString = getInsString(ain);
boolean result = pattern.matcher(insnString).find();
if(result) {
return true;
}
}
return false;
});
}
private static String getInsString(AbstractInsnNode ain) {
String insnString = "";
switch (ain.getType()) { switch (ain.getType()) {
case AbstractInsnNode.INT_INSN: case AbstractInsnNode.INT_INSN:
final IntInsnNode iin = (IntInsnNode) ain; final IntInsnNode iin = (IntInsnNode) ain;
@ -292,9 +329,7 @@ public class RegexInsnFinder {
insnString += "{" + manain.dims + "," + manain.desc + "}"; insnString += "{" + manain.dims + "," + manain.desc + "}";
break; break;
} }
insnString += " "; return insnString;
}
}
} }
public void setMethod(final ClassNode ci, final MethodNode mi) { public void setMethod(final ClassNode ci, final MethodNode mi) {

View file

@ -2,6 +2,7 @@ package the.bytecode.club.bytecodeviewer.searching;
import java.awt.GridLayout; import java.awt.GridLayout;
import java.util.Iterator; import java.util.Iterator;
import java.util.regex.Pattern;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JPanel; import javax.swing.JPanel;
@ -12,6 +13,8 @@ import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.MethodNode;
import the.bytecode.club.bytecodeviewer.util.FileContainer; import the.bytecode.club.bytecodeviewer.util.FileContainer;
import static the.bytecode.club.bytecodeviewer.searching.RegexInsnFinder.processRegex;
/*************************************************************************** /***************************************************************************
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite * * Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
* Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com * * Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com *
@ -71,21 +74,13 @@ public class RegexSearch implements SearchTypeDetails {
if (srchText.isEmpty()) if (srchText.isEmpty())
return; return;
Pattern pattern = Pattern.compile(processRegex(srchText),
Pattern.MULTILINE);
while (methods.hasNext()) while (methods.hasNext())
{ {
final MethodNode method = methods.next(); final MethodNode method = methods.next();
if (regexFinder == null) if (RegexInsnFinder.staticScan(node, method, pattern))
{
regexFinder = new RegexInsnFinder(node, method);
}
else
{
regexFinder.setMethod(node, method);
}
if (regexFinder.find(srchText).length > 0)
{ {
String desc2 = method.desc; String desc2 = method.desc;
try try