fix: improve StringBuilder elimination (#2148)
This commit is contained in:
@@ -132,6 +132,10 @@ public abstract class InsnArg extends Typed {
|
||||
}
|
||||
InsnArg arg = wrapInsnIntoArg(insn);
|
||||
InsnArg oldArg = parent.getArg(i);
|
||||
if (arg.getType() == ArgType.UNKNOWN) {
|
||||
// restore arg type if wrapped insn missing result
|
||||
arg.setType(oldArg.getType());
|
||||
}
|
||||
parent.setArg(i, arg);
|
||||
InsnRemover.unbindArgUsage(mth, oldArg);
|
||||
if (unbind) {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package jadx.core.dex.instructions.args;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import jadx.core.dex.instructions.ConstStringNode;
|
||||
@@ -75,10 +73,18 @@ public final class InsnWrapArg extends InsnArg {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (wrappedInsn.getType() == InsnType.CONST_STR && Objects.equals(type, ArgType.STRING)) {
|
||||
public String toShortString() {
|
||||
if (wrappedInsn.getType() == InsnType.CONST_STR) {
|
||||
return "(\"" + ((ConstStringNode) wrappedInsn).getString() + "\")";
|
||||
}
|
||||
return "(wrap: " + type + " : " + wrappedInsn + ')';
|
||||
return "(wrap:" + type + ":" + wrappedInsn.getType() + ')';
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (wrappedInsn.getType() == InsnType.CONST_STR) {
|
||||
return "(\"" + ((ConstStringNode) wrappedInsn).getString() + "\")";
|
||||
}
|
||||
return "(wrap:" + type + ":" + wrappedInsn + ')';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,7 +402,8 @@ public class SimplifyVisitor extends AbstractVisitor {
|
||||
}
|
||||
}
|
||||
if (!stringArgFound) {
|
||||
mth.addDebugComment("TODO: convert one arg to string using `String.valueOf()`, args: " + args);
|
||||
String argStr = Utils.listToString(args, InsnArg::toShortString);
|
||||
mth.addDebugComment("TODO: convert one arg to string using `String.valueOf()`, args: " + argStr);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -625,7 +626,9 @@ public class SimplifyVisitor extends AbstractVisitor {
|
||||
for (int i = 1; i < argsCount; i++) {
|
||||
concat.addArg(wrap.getArg(i));
|
||||
}
|
||||
return ArithNode.oneArgOp(ArithOp.ADD, fArg, InsnArg.wrapArg(concat));
|
||||
InsnArg concatArg = InsnArg.wrapArg(concat);
|
||||
concatArg.setType(ArgType.STRING);
|
||||
return ArithNode.oneArgOp(ArithOp.ADD, fArg, concatArg);
|
||||
} catch (Exception e) {
|
||||
LOG.debug("Can't convert field arith insn: {}, mth: {}", insn, mth, e);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package jadx.core.dex.visitors.shrink;
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -64,12 +63,9 @@ public class CodeShrinkVisitor extends AbstractVisitor {
|
||||
List<WrapInfo> wrapList = new ArrayList<>();
|
||||
for (ArgsInfo argsInfo : argsList) {
|
||||
List<RegisterArg> args = argsInfo.getArgs();
|
||||
if (!args.isEmpty()) {
|
||||
ListIterator<RegisterArg> it = args.listIterator(args.size());
|
||||
while (it.hasPrevious()) {
|
||||
RegisterArg arg = it.previous();
|
||||
checkInline(mth, block, insnList, wrapList, argsInfo, arg);
|
||||
}
|
||||
for (int i = args.size() - 1; i >= 0; i--) {
|
||||
RegisterArg arg = args.get(i);
|
||||
checkInline(mth, block, insnList, wrapList, argsInfo, arg);
|
||||
}
|
||||
}
|
||||
if (!wrapList.isEmpty()) {
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package jadx.tests.integration.others;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jadx.tests.api.IntegrationTest;
|
||||
|
||||
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
|
||||
|
||||
public class TestStringBuilderElimination5 extends IntegrationTest {
|
||||
|
||||
public static class TestCls {
|
||||
@SuppressWarnings("StringConcatenationInLoop")
|
||||
public static String test(long[] a) {
|
||||
String s = "";
|
||||
final char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
||||
for (int i = a.length - 1; i >= 0; i--) {
|
||||
s += hexChars[(int) (a[i] >>> 60) & 0x0f];
|
||||
s += hexChars[(int) (a[i] >>> 56) & 0x0f];
|
||||
s += hexChars[(int) (a[i] >>> 52) & 0x0f];
|
||||
s += hexChars[(int) (a[i] >>> 48) & 0x0f];
|
||||
s += hexChars[(int) (a[i] >>> 44) & 0x0f];
|
||||
s += hexChars[(int) (a[i] >>> 40) & 0x0f];
|
||||
s += hexChars[(int) (a[i] >>> 36) & 0x0f];
|
||||
s += hexChars[(int) (a[i] >>> 32) & 0x0f];
|
||||
s += hexChars[(int) (a[i] >>> 28) & 0x0f];
|
||||
s += hexChars[(int) (a[i] >>> 24) & 0x0f];
|
||||
s += hexChars[(int) (a[i] >>> 20) & 0x0f];
|
||||
s += hexChars[(int) (a[i] >>> 16) & 0x0f];
|
||||
s += hexChars[(int) (a[i] >>> 12) & 0x0f];
|
||||
s += hexChars[(int) (a[i] >>> 8) & 0x0f];
|
||||
s += hexChars[(int) (a[i] >>> 4) & 0x0f];
|
||||
s += hexChars[(int) (a[i]) & 0x0f];
|
||||
s += " ";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
assertThat(getClassNode(TestCls.class))
|
||||
.code()
|
||||
.doesNotContain(".append(");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user