Replace StringBuilder append chain with strings concatenation
This commit is contained in:
@@ -13,5 +13,7 @@ public class Consts {
|
||||
public static final String CLASS_THROWABLE = "java.lang.Throwable";
|
||||
public static final String CLASS_ENUM = "java.lang.Enum";
|
||||
|
||||
public static final String CLASS_STRING_BUILDER = "java.lang.StringBuilder";
|
||||
|
||||
public static final String DALVIK_SIGNATURE = "dalvik.annotation.Signature";
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import jadx.utils.exceptions.CodegenException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@@ -213,7 +214,7 @@ public class InsnGen {
|
||||
|
||||
case RETURN:
|
||||
if (insn.getArgsCount() != 0)
|
||||
code.add("return " + arg(insn.getArg(0)));
|
||||
code.add("return ").add(arg(insn.getArg(0)));
|
||||
else
|
||||
code.add("return");
|
||||
break;
|
||||
@@ -227,7 +228,7 @@ public class InsnGen {
|
||||
break;
|
||||
|
||||
case THROW:
|
||||
code.add("throw " + arg(insn.getArg(0)));
|
||||
code.add("throw ").add(arg(insn.getArg(0)));
|
||||
break;
|
||||
|
||||
case CMP_L:
|
||||
@@ -281,7 +282,7 @@ public class InsnGen {
|
||||
code.add(ifield((IndexInsnNode) insn, 0));
|
||||
break;
|
||||
case IPUT:
|
||||
code.add(ifield((IndexInsnNode) insn, 1) + " = " + arg(insn.getArg(0)));
|
||||
code.add(ifield((IndexInsnNode) insn, 1)).add(" = ").add(arg(insn.getArg(0)));
|
||||
break;
|
||||
|
||||
case SGET:
|
||||
@@ -290,7 +291,18 @@ public class InsnGen {
|
||||
case SPUT:
|
||||
IndexInsnNode node = (IndexInsnNode) insn;
|
||||
fieldPut(node);
|
||||
code.add(sfield(node) + " = " + arg(node.getArg(0)));
|
||||
code.add(sfield(node)).add(" = ").add(arg(node.getArg(0)));
|
||||
break;
|
||||
|
||||
case STR_CONCAT:
|
||||
// TODO: wrap in braces only if necessary
|
||||
code.add('(');
|
||||
for (Iterator<InsnArg> it = insn.getArguments().iterator(); it.hasNext(); ) {
|
||||
code.add(arg(it.next()));
|
||||
if (it.hasNext())
|
||||
code.add(" + ");
|
||||
}
|
||||
code.add(')');
|
||||
break;
|
||||
|
||||
case MONITOR_ENTER:
|
||||
|
||||
@@ -49,6 +49,10 @@ public final class MethodInfo {
|
||||
return declClass.getFullName() + "." + name;
|
||||
}
|
||||
|
||||
|
||||
public String getFullId() {
|
||||
return declClass.getFullName() + "." + shortId;
|
||||
}
|
||||
/**
|
||||
* Method name and signature
|
||||
*/
|
||||
|
||||
@@ -51,6 +51,8 @@ public enum InsnType {
|
||||
BREAK,
|
||||
CONTINUE,
|
||||
|
||||
STR_CONCAT, // strings concatenation
|
||||
|
||||
TERNARY,
|
||||
ARGS, // just generate arguments
|
||||
|
||||
|
||||
@@ -65,12 +65,12 @@ public class MethodNode extends AttrNode implements ILoadable {
|
||||
private IContainer region;
|
||||
private List<ExceptionHandler> exceptionHandlers;
|
||||
|
||||
public MethodNode(ClassNode classNode, Method mth) {
|
||||
this.mthInfo = MethodInfo.fromDex(classNode.dex(), mth.getMethodIndex());
|
||||
public MethodNode(ClassNode classNode, Method mthData) {
|
||||
this.mthInfo = MethodInfo.fromDex(classNode.dex(), mthData.getMethodIndex());
|
||||
this.parentClass = classNode;
|
||||
this.accFlags = new AccessInfo(mth.getAccessFlags(), AFType.METHOD);
|
||||
this.methodData = mth;
|
||||
this.noCode = (methodData.getCodeOffset() == 0);
|
||||
this.accFlags = new AccessInfo(mthData.getAccessFlags(), AFType.METHOD);
|
||||
this.noCode = (mthData.getCodeOffset() == 0);
|
||||
this.methodData = (noCode ? null : mthData);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
package jadx.dex.visitors;
|
||||
|
||||
import jadx.Consts;
|
||||
import jadx.dex.attributes.AttributeFlag;
|
||||
import jadx.dex.info.MethodInfo;
|
||||
import jadx.dex.instructions.ArithNode;
|
||||
import jadx.dex.instructions.ArithOp;
|
||||
import jadx.dex.instructions.IfNode;
|
||||
import jadx.dex.instructions.InsnType;
|
||||
import jadx.dex.instructions.InvokeNode;
|
||||
import jadx.dex.instructions.args.InsnArg;
|
||||
import jadx.dex.instructions.args.InsnWrapArg;
|
||||
import jadx.dex.instructions.args.LiteralArg;
|
||||
import jadx.dex.instructions.args.RegisterArg;
|
||||
import jadx.dex.instructions.mods.ConstructorInsn;
|
||||
import jadx.dex.nodes.BlockNode;
|
||||
import jadx.dex.nodes.InsnNode;
|
||||
import jadx.dex.nodes.MethodNode;
|
||||
@@ -16,6 +20,7 @@ import jadx.utils.BlockUtils;
|
||||
import jadx.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -154,12 +159,49 @@ public class CodeShrinker extends AbstractVisitor {
|
||||
}
|
||||
break;
|
||||
|
||||
case INVOKE:
|
||||
MethodInfo callMth = ((InvokeNode) insn).getCallMth();
|
||||
if (callMth.getDeclClass().getFullName().equals(Consts.CLASS_STRING_BUILDER)
|
||||
&& callMth.getShortId().equals("toString()")
|
||||
&& insn.getArg(0).isInsnWrap()) {
|
||||
List<InsnNode> chain = flattenInsnChain(insn);
|
||||
if (chain.size() > 1 && chain.get(0).getType() == InsnType.CONSTRUCTOR) {
|
||||
ConstructorInsn constr = (ConstructorInsn) chain.get(0);
|
||||
if (constr.getClassType().getFullName().equals(Consts.CLASS_STRING_BUILDER)
|
||||
&& constr.getArgsCount() == 0) {
|
||||
int len = chain.size();
|
||||
InsnNode concatInsn = new InsnNode(InsnType.STR_CONCAT, len - 1);
|
||||
for (int i = 1; i < len; i++) {
|
||||
concatInsn.addArg(chain.get(i).getArg(1));
|
||||
}
|
||||
concatInsn.setResult(insn.getResult());
|
||||
return concatInsn;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static List<InsnNode> flattenInsnChain(InsnNode insn) {
|
||||
List<InsnNode> chain = new ArrayList<InsnNode>();
|
||||
InsnArg i = insn.getArg(0);
|
||||
while (i.isInsnWrap()) {
|
||||
InsnNode wrapInsn = ((InsnWrapArg) i).getWrapInsn();
|
||||
chain.add(wrapInsn);
|
||||
if(wrapInsn.getArgsCount() == 0)
|
||||
break;
|
||||
|
||||
i = wrapInsn.getArg(0);
|
||||
}
|
||||
Collections.reverse(chain);
|
||||
return chain;
|
||||
}
|
||||
|
||||
public static InsnArg inlineArgument(MethodNode mth, RegisterArg arg) {
|
||||
InsnNode assignInsn = arg.getAssignInsn();
|
||||
if (assignInsn == null)
|
||||
|
||||
Reference in New Issue
Block a user