Я пытаюсь предотвратить бесполезность условных переходов, например, удалив:
if(1 > 10) {
return;
}
Поэтому я решил создать BasicInterpreter
, чтобы проверить, равен ли кадр перехода null
и если это так, удалите его.И это не null
, поэтому он не считает его бесполезным.
Код, который не работает:
Analyzer<BasicValue> an = new Analyzer<BasicValue>(new BasicInterpreter());
Frame<BasicValue>[] frames = an.analyze(cn.name, mn);
for (int i = 0; i < frames.length; i++) {
if ((mn.instructions.get(i) instanceof JumpInsnNode)) {
if (mn.instructions.get(i).getOpcode() >= IFEQ && mn.instructions.get(i).getOpcode() <= IF_ACMPNE) {
if(frames[i] == null) {
System.out.println("This jump is useless");
}
}
}
}
Затем я попытался получить некоторые значения стека для вычисления вручнуюно безуспешно (я обнаружил, что не могу перенести код для его использования при переходах ASM Получить точное значение из стекового фрейма ):
Analyzer<BasicValue> an = new Analyzer<BasicValue>(new BasicInterpreter());
Frame<BasicValue>[] frames = an.analyze(cn.name, mn);
for (int i = 0; i < frames.length; i++) {
if ((mn.instructions.get(i) instanceof JumpInsnNode)) {
if (mn.instructions.get(i).getOpcode() >= IFEQ && mn.instructions.get(i).getOpcode() <= IF_ACMPNE) {
// getStackSize() returns 2 so -> 0 and 1
frames[i].getStack(0); // this is probably 1
frames[i].getStack(1); // this is probably 10
// but it returns a BasicValue so I can't check if the code works or not (we cannot get values)
}
}
}
И последнее, что я попробовал, былочтобы получить размер инструкций, которые используются переходом для их удаления (конечно, он не определяет, является ли это бесполезным кодом, но я могу, по крайней мере, удалить его).
На самом деле я пытался создатьметод, который возвращает константу int, чтобы я мог определить, вызывается ли getValue в инструкциях перехода (если я обнаруживаю вызов, я, конечно, удаляю инструкции перехода и сам переход):
Пример:
if(1 > getValue()) { //getValue() returns 10
return;
}
Код:
Analyzer<BasicValue> an = new Analyzer<BasicValue>(new BasicInterpreter());
Frame<BasicValue>[] frames = an.analyze(cn.name, mn);
ArrayList<AbstractInsnNode> nodesR = new ArrayList<>();
for (int i = 0; i < frames.length; i++) {
if ((mn.instructions.get(i) instanceof JumpInsnNode)) {
if (mn.instructions.get(i).getOpcode() >= IFEQ && mn.instructions.get(i).getOpcode() <= IF_ACMPNE) {
ArrayList<AbstractInsnNode> toRemove = new ArrayList<>();
for (int ia = 1; ia < frames[i].getMaxStackSize() + 2; ia++) { // I started from 1 and added 2 to getMaxStackSize because I wasn't getting all the instructions
toRemove.add(mn.instructions.get(i - ia));
}
toRemove.add(mn.instructions.get(i)); // I add the jump to the list
for (AbstractInsnNode aaa : toRemove) {
if (aaa.getOpcode() == INVOKESTATIC) { // the invokestatic is getValue
for (AbstractInsnNode aaas : toRemove) {
nodesR.add(aaas);
}
break;
}
}
}
}
}
for (AbstractInsnNode aaas : nodesR) {
mn.instructions.remove(aaas);
}
} catch (AnalyzerException e) {
e.printStackTrace();
}
Этот код, вероятно, ужасен и не оптимизирован, но я попробовал МНОГО вещей без какого-либо успеха.GetMaxStackSize () не возвращает число, которое является на 100% правильным (иногда оно не требует добавления и т. Д., Поэтому оно удаляет инструкции, такие как метки и т. Д.).
Что я пытаюсь сделать:
Анализ метода и проверка того, будет ли условный переход всегда ложным (поэтому код внутри никогда не будет выполнен), затем удалите его.Я пробовал два разных способа:
- Используйте
BasicInterpreter
, чтобы проверить, будет ли этот переход выполняться с постоянными значениями, затем попробуйте, чтобы увидеть, будет ли он всегда ложным - Проверьте, еслипереход содержит определенный метод (например,
getValue()
, который возвращает 10 и сравнивает, если он меньше 1), затем удаляет его. Что я не понимаю: - Я думаю, что в каждой инструкции есть кадры и чтоон содержит таблицу локальных переменных и значения, которые использует фрейм - StackMap?- (например, если инструкция сравнится, если int меньше другого, она вернет [II], верно?
- Я не знаю, смогу ли я использовать
BasicInterpreter
, чтобы проверить, всегда ли два постоянных целых числавернуть тот же результат - StackMap = Stack? или он отличается от StackMap как часть стека, который содержит необходимые значения для инструкции?