fix: don't inline constants into lambdas
This commit is contained in:
@@ -1016,9 +1016,14 @@ public class InsnGen {
|
||||
int startArg = customNode.getHandleType() == MethodHandleType.INVOKE_STATIC ? 0 : 1; // skip 'this' arg
|
||||
int callArg = 0;
|
||||
for (int i = startArg; i < extArgsCount; i++) {
|
||||
RegisterArg extArg = (RegisterArg) customNode.getArg(i);
|
||||
RegisterArg callRegArg = callArgs.get(callArg++);
|
||||
callRegArg.getSVar().setCodeVar(extArg.getSVar().getCodeVar());
|
||||
InsnArg arg = customNode.getArg(i);
|
||||
if (arg.isRegister()) {
|
||||
RegisterArg extArg = (RegisterArg) arg;
|
||||
RegisterArg callRegArg = callArgs.get(callArg++);
|
||||
callRegArg.getSVar().setCodeVar(extArg.getSVar().getCodeVar());
|
||||
} else {
|
||||
throw new JadxRuntimeException("Unexpected argument type in lambda call: " + arg.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
code.add(" -> {");
|
||||
code.incIndent();
|
||||
@@ -1075,27 +1080,23 @@ public class InsnGen {
|
||||
}
|
||||
int argsCount = insn.getArgsCount();
|
||||
code.add('(');
|
||||
SkipMethodArgsAttr skipAttr = mthNode == null ? null : mthNode.get(AType.SKIP_MTH_ARGS);
|
||||
boolean firstArg = true;
|
||||
if (k < argsCount) {
|
||||
for (int i = k; i < argsCount; i++) {
|
||||
InsnArg arg = insn.getArg(i);
|
||||
if (arg.contains(AFlag.SKIP_ARG)) {
|
||||
if (arg.contains(AFlag.SKIP_ARG) || (skipAttr != null && skipAttr.isSkip(i - startArgNum))) {
|
||||
continue;
|
||||
}
|
||||
int argOrigPos = i - startArgNum;
|
||||
if (SkipMethodArgsAttr.isSkip(mthNode, argOrigPos)) {
|
||||
continue;
|
||||
}
|
||||
if (!firstArg) {
|
||||
code.add(", ");
|
||||
} else {
|
||||
if (firstArg) {
|
||||
firstArg = false;
|
||||
} else {
|
||||
code.add(", ");
|
||||
}
|
||||
if (i == argsCount - 1 && processVarArg(code, insn, arg)) {
|
||||
continue;
|
||||
}
|
||||
addArg(code, arg, false);
|
||||
firstArg = false;
|
||||
}
|
||||
}
|
||||
code.add(')');
|
||||
|
||||
@@ -16,6 +16,7 @@ import jadx.core.dex.instructions.args.LiteralArg;
|
||||
import jadx.core.dex.instructions.args.PrimitiveType;
|
||||
import jadx.core.dex.instructions.args.RegisterArg;
|
||||
import jadx.core.dex.instructions.args.SSAVar;
|
||||
import jadx.core.dex.instructions.mods.ConstructorInsn;
|
||||
import jadx.core.dex.nodes.BlockNode;
|
||||
import jadx.core.dex.nodes.FieldNode;
|
||||
import jadx.core.dex.nodes.InsnNode;
|
||||
@@ -178,7 +179,7 @@ public class ConstInlineVisitor extends AbstractVisitor {
|
||||
List<RegisterArg> useList = new ArrayList<>(ssaVar.getUseList());
|
||||
int replaceCount = 0;
|
||||
for (RegisterArg arg : useList) {
|
||||
if (canInline(arg) && replaceArg(mth, arg, constArg, constInsn)) {
|
||||
if (canInline(mth, arg) && replaceArg(mth, arg, constArg, constInsn)) {
|
||||
replaceCount++;
|
||||
}
|
||||
}
|
||||
@@ -204,8 +205,8 @@ public class ConstInlineVisitor extends AbstractVisitor {
|
||||
}
|
||||
|
||||
@SuppressWarnings("RedundantIfStatement")
|
||||
private static boolean canInline(RegisterArg arg) {
|
||||
if (arg.contains(AFlag.DONT_INLINE_CONST)) {
|
||||
private static boolean canInline(MethodNode mth, RegisterArg arg) {
|
||||
if (arg.contains(AFlag.DONT_INLINE_CONST) || arg.contains(AFlag.DONT_INLINE)) {
|
||||
return false;
|
||||
}
|
||||
InsnNode parentInsn = arg.getParentInsn();
|
||||
@@ -219,6 +220,14 @@ public class ConstInlineVisitor extends AbstractVisitor {
|
||||
// don't inline vars used in finally block
|
||||
return false;
|
||||
}
|
||||
if (parentInsn.getType() == InsnType.CONSTRUCTOR) {
|
||||
// don't inline into anonymous call if it can be inlined later
|
||||
ConstructorInsn ctrInsn = (ConstructorInsn) parentInsn;
|
||||
MethodNode ctrMth = mth.root().getMethodUtils().resolveMethod(ctrInsn);
|
||||
if (ctrMth != null && ctrMth.contains(AFlag.METHOD_CANDIDATE_FOR_INLINE)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package jadx.tests.integration.java8;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import jadx.tests.api.IntegrationTest;
|
||||
import jadx.tests.api.extensions.profiles.TestProfile;
|
||||
import jadx.tests.api.extensions.profiles.TestWithProfiles;
|
||||
|
||||
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
|
||||
|
||||
public class TestLambdaExtVar2 extends IntegrationTest {
|
||||
|
||||
public static class TestCls {
|
||||
|
||||
public void test(List<String> list) {
|
||||
String space = " ";
|
||||
list.removeIf(s -> s.equals(space) || s.contains(space));
|
||||
}
|
||||
|
||||
public void check() {
|
||||
List<String> list = new ArrayList<>(Arrays.asList("a", " ", "b", "r "));
|
||||
test(list);
|
||||
assertThat(list).isEqualTo(Arrays.asList("a", "b"));
|
||||
}
|
||||
}
|
||||
|
||||
@TestWithProfiles({ TestProfile.DX_J8, TestProfile.D8_J11, TestProfile.JAVA11 })
|
||||
public void test() {
|
||||
assertThat(getClassNode(TestCls.class))
|
||||
.code()
|
||||
.doesNotContain("lambda$")
|
||||
.containsOne("String space = \" \";")
|
||||
.containsOne("s.equals(space) || s.contains(space)");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user