fix: inline assignment instruction from same block (#820)
This commit is contained in:
@@ -65,6 +65,7 @@ public abstract class InsnArg extends Typed {
|
||||
}
|
||||
|
||||
private static InsnWrapArg wrap(InsnNode insn) {
|
||||
insn.add(AFlag.WRAPPED);
|
||||
return new InsnWrapArg(insn);
|
||||
}
|
||||
|
||||
@@ -140,9 +141,17 @@ public abstract class InsnArg extends Typed {
|
||||
InsnArg arg;
|
||||
InsnType type = insn.getType();
|
||||
if (type == InsnType.CONST || type == InsnType.MOVE) {
|
||||
arg = insn.getArg(0);
|
||||
insn.add(AFlag.REMOVE);
|
||||
insn.add(AFlag.DONT_GENERATE);
|
||||
if (insn.contains(AFlag.FORCE_ASSIGN_INLINE)) {
|
||||
RegisterArg resArg = insn.getResult();
|
||||
arg = wrap(insn);
|
||||
if (resArg != null) {
|
||||
arg.setType(resArg.getType());
|
||||
}
|
||||
} else {
|
||||
arg = insn.getArg(0);
|
||||
insn.add(AFlag.REMOVE);
|
||||
insn.add(AFlag.DONT_GENERATE);
|
||||
}
|
||||
} else {
|
||||
arg = wrapArg(insn);
|
||||
}
|
||||
@@ -156,8 +165,6 @@ public abstract class InsnArg extends Typed {
|
||||
public static InsnArg wrapArg(InsnNode insn) {
|
||||
RegisterArg resArg = insn.getResult();
|
||||
InsnArg arg = wrap(insn);
|
||||
insn.add(AFlag.WRAPPED);
|
||||
|
||||
switch (insn.getType()) {
|
||||
case CONST:
|
||||
case MOVE:
|
||||
|
||||
@@ -100,10 +100,6 @@ public class CodeShrinkVisitor extends AbstractVisitor {
|
||||
|
||||
int assignPos = insnList.getIndex(assignInsn);
|
||||
if (assignPos != -1) {
|
||||
if (assignInline) {
|
||||
// TODO?
|
||||
return;
|
||||
}
|
||||
WrapInfo wrapInfo = argsInfo.checkInline(assignPos, arg);
|
||||
if (wrapInfo != null) {
|
||||
wrapList.add(wrapInfo);
|
||||
@@ -123,25 +119,19 @@ public class CodeShrinkVisitor extends AbstractVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
private static void assignInline(MethodNode mth, RegisterArg arg, InsnNode assignInsn, BlockNode assignBlock) {
|
||||
private static boolean assignInline(MethodNode mth, RegisterArg arg, InsnNode assignInsn, BlockNode assignBlock) {
|
||||
RegisterArg useArg = arg.getSVar().getUseList().get(0);
|
||||
InsnNode useInsn = useArg.getParentInsn();
|
||||
if (useInsn == null || useInsn.contains(AFlag.DONT_GENERATE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
InsnArg replaceArg;
|
||||
InsnType assignInsnType = assignInsn.getType();
|
||||
if (assignInsnType == InsnType.MOVE || assignInsnType == InsnType.CONST) {
|
||||
replaceArg = assignInsn.getArg(0).duplicate();
|
||||
} else {
|
||||
replaceArg = InsnArg.wrapArg(assignInsn.copy());
|
||||
return false;
|
||||
}
|
||||
InsnArg replaceArg = InsnArg.wrapInsnIntoArg(assignInsn.copy());
|
||||
useInsn.replaceArg(useArg, replaceArg);
|
||||
|
||||
assignInsn.add(AFlag.REMOVE);
|
||||
assignInsn.add(AFlag.DONT_GENERATE);
|
||||
InsnRemover.remove(mth, assignBlock, assignInsn);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean inline(MethodNode mth, RegisterArg arg, InsnNode insn, BlockNode block) {
|
||||
@@ -149,6 +139,9 @@ public class CodeShrinkVisitor extends AbstractVisitor {
|
||||
if (parentInsn != null && parentInsn.getType() == InsnType.RETURN) {
|
||||
parentInsn.setSourceLine(insn.getSourceLine());
|
||||
}
|
||||
if (insn.contains(AFlag.FORCE_ASSIGN_INLINE)) {
|
||||
return assignInline(mth, arg, insn, block);
|
||||
}
|
||||
boolean replaced = arg.wrapInstruction(mth, insn) != null;
|
||||
if (replaced) {
|
||||
InsnList.remove(block, insn);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package jadx.tests.integration.conditions;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jadx.tests.api.SmaliTest;
|
||||
|
||||
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
|
||||
|
||||
/**
|
||||
* Issue #820
|
||||
*/
|
||||
public class TestInnerAssign3 extends SmaliTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
disableCompilation();
|
||||
assertThat(getClassNodeFromSmali())
|
||||
.code()
|
||||
.containsOne("(testMethod = (testClass1 = null).testMethod()) == null")
|
||||
.containsOne("testClass1.testField != null");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
.class public Lconditions/TestInnerAssign3;
|
||||
.super LTestSuper;
|
||||
.source "Test.java"
|
||||
|
||||
.method public test()V
|
||||
.locals 5
|
||||
|
||||
const/4 v0, 0
|
||||
const/4 v1, 0
|
||||
const/4 v4, 0
|
||||
|
||||
if-eqz v4, :cond_0
|
||||
|
||||
const/4 v2, 0
|
||||
|
||||
invoke-virtual {v2}, LTestClass1;->testMethod()LTestClass2;
|
||||
|
||||
move-result-object v0
|
||||
|
||||
if-eqz v0, :cond_0
|
||||
|
||||
if-eq v1, v0, :cond_0
|
||||
|
||||
iget-object v3, v2, LTestClass1;->testField:LTestClass3;
|
||||
|
||||
if-eqz v3, :cond_0
|
||||
|
||||
:cond_0
|
||||
return-void
|
||||
.end method
|
||||
Reference in New Issue
Block a user