Skip to content

Commit

Permalink
feat: inline lambdas by instance field (#1800)
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Mar 24, 2023
1 parent 77892f4 commit 157e702
Show file tree
Hide file tree
Showing 23 changed files with 200 additions and 58 deletions.
8 changes: 8 additions & 0 deletions jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ public class JadxCLIArgs {
@Parameter(names = { "--no-inline-methods" }, description = "disable methods inline")
protected boolean inlineMethods = true;

@Parameter(names = { "--no-inline-kotlin-lambda" }, description = "disable inline for Kotlin lambdas")
protected boolean allowInlineKotlinLambda = true;

@Parameter(names = "--no-finally", description = "don't extract finally block")
protected boolean extractFinally = true;

Expand Down Expand Up @@ -287,6 +290,7 @@ public JadxArgs toJadxArgs() {
args.setInsertDebugLines(addDebugLines);
args.setInlineAnonymousClasses(inlineAnonymousClasses);
args.setInlineMethods(inlineMethods);
args.setAllowInlineKotlinLambda(allowInlineKotlinLambda);
args.setExtractFinally(extractFinally);
args.setRenameFlags(renameFlags);
args.setFsCaseSensitive(fsCaseSensitive);
Expand Down Expand Up @@ -368,6 +372,10 @@ public boolean isInlineMethods() {
return inlineMethods;
}

public boolean isAllowInlineKotlinLambda() {
return allowInlineKotlinLambda;
}

public boolean isExtractFinally() {
return extractFinally;
}
Expand Down
9 changes: 9 additions & 0 deletions jadx-core/src/main/java/jadx/api/JadxArgs.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public class JadxArgs {
private boolean extractFinally = true;
private boolean inlineAnonymousClasses = true;
private boolean inlineMethods = true;
private boolean allowInlineKotlinLambda = true;

private boolean skipResources = false;
private boolean skipSources = false;
Expand Down Expand Up @@ -263,6 +264,14 @@ public void setInlineMethods(boolean inlineMethods) {
this.inlineMethods = inlineMethods;
}

public boolean isAllowInlineKotlinLambda() {
return allowInlineKotlinLambda;
}

public void setAllowInlineKotlinLambda(boolean allowInlineKotlinLambda) {
this.allowInlineKotlinLambda = allowInlineKotlinLambda;
}

public boolean isExtractFinally() {
return extractFinally;
}
Expand Down
35 changes: 28 additions & 7 deletions jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import jadx.api.plugins.input.data.annotations.EncodedValue;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.FieldInitInsnAttr;
import jadx.core.dex.attributes.nodes.FieldReplaceAttr;
import jadx.core.dex.attributes.nodes.GenericInfoAttr;
import jadx.core.dex.attributes.nodes.LoopLabelAttr;
Expand Down Expand Up @@ -210,7 +211,31 @@ private void instanceField(ICodeWriter code, FieldInfo field, InsnArg arg) throw
}
}

protected void staticField(ICodeWriter code, FieldInfo field) throws CodegenException {
FieldNode fieldNode = root.resolveField(field);
if (fieldNode != null
&& fieldNode.contains(AFlag.INLINE_INSTANCE_FIELD)
&& fieldNode.getParentClass().contains(AType.ANONYMOUS_CLASS)) {
FieldInitInsnAttr initInsnAttr = fieldNode.get(AType.FIELD_INIT_INSN);
if (initInsnAttr != null) {
InsnNode insn = initInsnAttr.getInsn();
if (insn instanceof ConstructorInsn) {
fieldNode.add(AFlag.DONT_GENERATE);
inlineAnonymousConstructor(code, fieldNode.getParentClass(), (ConstructorInsn) insn);
return;
}
}
}
makeStaticFieldAccess(code, field, fieldNode, mgen.getClassGen());
}

public static void makeStaticFieldAccess(ICodeWriter code, FieldInfo field, ClassGen clsGen) {
FieldNode fieldNode = clsGen.getClassNode().root().resolveField(field);
makeStaticFieldAccess(code, field, fieldNode, clsGen);
}

private static void makeStaticFieldAccess(ICodeWriter code,
FieldInfo field, @Nullable FieldNode fieldNode, ClassGen clsGen) {
ClassInfo declClass = field.getDeclClass();
// TODO
boolean fieldFromThisClass = clsGen.getClassNode().getClassInfo().equals(declClass);
Expand All @@ -221,7 +246,6 @@ public static void makeStaticFieldAccess(ICodeWriter code, FieldInfo field, Clas
}
code.add('.');
}
FieldNode fieldNode = clsGen.getClassNode().root().resolveField(field);
if (fieldNode != null) {
code.attachAnnotation(fieldNode);
}
Expand All @@ -232,10 +256,6 @@ public static void makeStaticFieldAccess(ICodeWriter code, FieldInfo field, Clas
}
}

protected void staticField(ICodeWriter code, FieldInfo field) {
makeStaticFieldAccess(code, field, mgen.getClassGen());
}

public void useClass(ICodeWriter code, ArgType type) {
mgen.getClassGen().useClass(code, type);
}
Expand Down Expand Up @@ -695,9 +715,7 @@ private void filledNewArray(FilledNewArrayNode insn, ICodeWriter code) throws Co
private void makeConstructor(ConstructorInsn insn, ICodeWriter code) throws CodegenException {
ClassNode cls = mth.root().resolveClass(insn.getClassType());
if (cls != null && cls.isAnonymous() && !fallback) {
cls.ensureProcessed();
inlineAnonymousConstructor(code, cls, insn);
mth.getParentClass().addInlinedClass(cls);
return;
}
if (insn.isSelf()) {
Expand Down Expand Up @@ -748,6 +766,7 @@ private void makeConstructor(ConstructorInsn insn, ICodeWriter code) throws Code
}

private void inlineAnonymousConstructor(ICodeWriter code, ClassNode cls, ConstructorInsn insn) throws CodegenException {
cls.ensureProcessed();
if (this.mth.getParentClass() == cls) {
cls.remove(AType.ANONYMOUS_CLASS);
cls.remove(AFlag.DONT_GENERATE);
Expand Down Expand Up @@ -786,6 +805,8 @@ private void inlineAnonymousConstructor(ICodeWriter code, ClassNode cls, Constru
ClassGen classGen = new ClassGen(cls, mgen.getClassGen().getParentGen());
classGen.setOuterNameGen(mgen.getNameGen());
classGen.addClassBody(code, true);

mth.getParentClass().addInlinedClass(cls);
}

private void makeInvoke(InvokeNode insn, ICodeWriter code) throws CodegenException {
Expand Down
2 changes: 1 addition & 1 deletion jadx-core/src/main/java/jadx/core/codegen/RegionGen.java
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ public void makeSwitch(SwitchRegion sw, ICodeWriter code) throws CodegenExceptio
code.startLine('}');
}

private void addCaseKey(ICodeWriter code, InsnArg arg, Object k) {
private void addCaseKey(ICodeWriter code, InsnArg arg, Object k) throws CodegenException {
if (k instanceof FieldNode) {
FieldNode fn = (FieldNode) k;
if (fn.getParentClass().isEnum()) {
Expand Down
2 changes: 2 additions & 0 deletions jadx-core/src/main/java/jadx/core/dex/attributes/AFlag.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ public enum AFlag {
SKIP_FIRST_ARG,
SKIP_ARG, // skip argument in invoke call
NO_SKIP_ARGS,

ANONYMOUS_CONSTRUCTOR,
INLINE_INSTANCE_FIELD,

THIS,
SUPER,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@

public class AnonymousClassAttr extends PinnedAttribute {

public enum InlineType {
CONSTRUCTOR,
INSTANCE_FIELD,
}

private final ClassNode outerCls;
private final ArgType baseType;
private final InlineType inlineType;

public AnonymousClassAttr(ClassNode outerCls, ArgType baseType) {
public AnonymousClassAttr(ClassNode outerCls, ArgType baseType, InlineType inlineType) {
this.outerCls = outerCls;
this.baseType = baseType;
this.inlineType = inlineType;
}

public ClassNode getOuterCls() {
Expand All @@ -23,13 +30,17 @@ public ArgType getBaseType() {
return baseType;
}

public InlineType getInlineType() {
return inlineType;
}

@Override
public AType<AnonymousClassAttr> getAttrType() {
return AType.ANONYMOUS_CLASS;
}

@Override
public String toString() {
return "AnonymousClass{" + outerCls + ", base: " + baseType + '}';
return "AnonymousClass{" + outerCls + ", base: " + baseType + ", inline type: " + inlineType + '}';
}
}
13 changes: 13 additions & 0 deletions jadx-core/src/main/java/jadx/core/dex/info/AccessInfo.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package jadx.core.dex.info;

import org.intellij.lang.annotations.MagicConstant;

import jadx.api.plugins.input.data.AccessFlags;
import jadx.core.Consts;
import jadx.core.utils.exceptions.JadxRuntimeException;
Expand All @@ -20,10 +22,21 @@ public AccessInfo(int accessFlags, AFType type) {
this.type = type;
}

@MagicConstant(valuesFromClass = AccessFlags.class)
public boolean containsFlag(int flag) {
return (accFlags & flag) != 0;
}

@MagicConstant(valuesFromClass = AccessFlags.class)
public boolean containsFlags(int... flags) {
for (int flag : flags) {
if ((accFlags & flag) == 0) {
return false;
}
}
return true;
}

public AccessInfo remove(int flag) {
if (containsFlag(flag)) {
return new AccessInfo(accFlags & ~flag, type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,14 @@ private static List<MethodNode> getConstructorsList(ClassNode cls) {
return list;
}

private static void addFieldInitAttr(MethodNode mth, FieldNode field, InsnNode insn) {
InsnNode assignInsn = InsnNode.wrapArg(insn.getArg(0));
private static void addFieldInitAttr(MethodNode mth, FieldNode field, IndexInsnNode putInsn) {
InsnNode assignInsn;
InsnArg fldArg = putInsn.getArg(0);
if (fldArg.isInsnWrap()) {
assignInsn = ((InsnWrapArg) fldArg).getWrapInsn();
} else {
assignInsn = InsnNode.wrapArg(fldArg);
}
field.addAttr(new FieldInitInsnAttr(mth, assignInsn));
}
}
Loading

0 comments on commit 157e702

Please sign in to comment.