core: replace 'move' instruction instead argument inline
This commit is contained in:
@@ -77,7 +77,7 @@ public abstract class InsnArg extends Typed {
|
||||
return parentInsn;
|
||||
}
|
||||
|
||||
public void setParentInsn(InsnNode parentInsn) {
|
||||
public void setParentInsn(@Nullable InsnNode parentInsn) {
|
||||
this.parentInsn = parentInsn;
|
||||
}
|
||||
|
||||
@@ -88,7 +88,6 @@ public abstract class InsnArg extends Typed {
|
||||
}
|
||||
if (parent == insn) {
|
||||
LOG.debug("Can't wrap instruction info itself: {}", insn);
|
||||
Thread.dumpStack();
|
||||
return null;
|
||||
}
|
||||
int i = getArgIndex(parent, this);
|
||||
|
||||
@@ -23,6 +23,8 @@ import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class CodeShrinker extends AbstractVisitor {
|
||||
|
||||
@Override
|
||||
@@ -227,15 +229,16 @@ public class CodeShrinker extends AbstractVisitor {
|
||||
if (assignBlock != null
|
||||
&& assignInsn != arg.getParentInsn()
|
||||
&& canMoveBetweenBlocks(assignInsn, assignBlock, block, argsInfo.getInsn())) {
|
||||
arg.wrapInstruction(assignInsn);
|
||||
InsnList.remove(assignBlock, assignInsn);
|
||||
if (inline(arg, assignInsn, assignBlock, mth)) {
|
||||
InsnList.remove(assignBlock, assignInsn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!wrapList.isEmpty()) {
|
||||
for (WrapInfo wrapInfo : wrapList) {
|
||||
wrapInfo.getArg().wrapInstruction(wrapInfo.getInsn());
|
||||
inline(wrapInfo.getArg(), wrapInfo.getInsn(), block, mth);
|
||||
}
|
||||
for (WrapInfo wrapInfo : wrapList) {
|
||||
insnList.remove(wrapInfo.getInsn());
|
||||
@@ -243,6 +246,29 @@ public class CodeShrinker extends AbstractVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean inline(RegisterArg arg, InsnNode insn, @Nullable BlockNode block, MethodNode mth) {
|
||||
InsnNode parentInsn = arg.getParentInsn();
|
||||
// replace move instruction if needed
|
||||
if (parentInsn != null && parentInsn.getType() == InsnType.MOVE) {
|
||||
if (block == null) {
|
||||
block = BlockUtils.getBlockByInsn(mth, parentInsn);
|
||||
}
|
||||
if (block != null) {
|
||||
int index = InsnList.getIndex(block.getInstructions(), parentInsn);
|
||||
if (index != -1) {
|
||||
insn.setResult(parentInsn.getResult());
|
||||
insn.copyAttributesFrom(parentInsn);
|
||||
insn.setOffset(parentInsn.getOffset());
|
||||
|
||||
block.getInstructions().set(index, insn);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// simple case
|
||||
return arg.wrapInstruction(insn) != null;
|
||||
}
|
||||
|
||||
private static boolean canMoveBetweenBlocks(InsnNode assignInsn, BlockNode assignBlock,
|
||||
BlockNode useBlock, InsnNode useInsn) {
|
||||
if (!BlockUtils.isPathExists(assignBlock, useBlock)) {
|
||||
@@ -300,7 +326,7 @@ public class CodeShrinker extends AbstractVisitor {
|
||||
for (RegisterArg rarg : list) {
|
||||
InsnNode ai = rarg.getAssignInsn();
|
||||
if (ai != assignInsn && ai != null && ai != rarg.getParentInsn()) {
|
||||
rarg.wrapInstruction(ai);
|
||||
inline(rarg, ai, null, mth);
|
||||
}
|
||||
}
|
||||
// remove method args
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package jadx.tests.smali;
|
||||
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.tests.api.SmaliTest;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static jadx.tests.api.utils.JadxMatchers.containsOne;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
public class TestInlineVarArg extends SmaliTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
noDebugInfo();
|
||||
ClassNode cls = getClassNodeFromSmali("TestInlineVarArg");
|
||||
String code = cls.getCode().toString();
|
||||
|
||||
assertThat(code, containsOne("f(\"a\", \"b\", \"c\");"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
.class public LTestInlineVarArg;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
.method public static varargs f([Ljava/lang/String;)V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public test()V
|
||||
.registers 5
|
||||
|
||||
const/4 v2, 0x3
|
||||
|
||||
new-array v1, v2, [Ljava/lang/String;
|
||||
|
||||
move-object v0, v1
|
||||
|
||||
const/4 v2, 0x0
|
||||
|
||||
const-string v3, "a"
|
||||
|
||||
aput-object v3, v0, v2
|
||||
|
||||
const/4 v2, 0x1
|
||||
|
||||
const-string v3, "b"
|
||||
|
||||
aput-object v3, v0, v2
|
||||
|
||||
const/4 v2, 0x2
|
||||
|
||||
const-string v3, "c"
|
||||
|
||||
aput-object v3, v0, v2
|
||||
|
||||
move-object v1, v0
|
||||
|
||||
invoke-static {v1}, LTestInlineVarArg;->f([Ljava/lang/String;)V
|
||||
|
||||
return-void
|
||||
.end method
|
||||
Reference in New Issue
Block a user