Commit 35ee0a25 authored by Skylot's avatar Skylot

Replace StringBuilder append chain with strings concatenation

parent 60615d01
......@@ -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
......
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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment