Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
qq_39073359
jadx
提交
081a0e21
J
jadx
项目概览
qq_39073359
/
jadx
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jadx
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
081a0e21
编写于
1月 17, 2022
作者:
S
Skylot
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix: precalculate class deps for inline methods (#1339)
上级
9ac9c052
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
123 addition
and
32 deletion
+123
-32
jadx-core/src/main/java/jadx/core/Jadx.java
jadx-core/src/main/java/jadx/core/Jadx.java
+2
-0
jadx-core/src/main/java/jadx/core/ProcessClass.java
jadx-core/src/main/java/jadx/core/ProcessClass.java
+4
-17
jadx-core/src/main/java/jadx/core/dex/attributes/AFlag.java
jadx-core/src/main/java/jadx/core/dex/attributes/AFlag.java
+2
-0
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
+12
-0
jadx-core/src/main/java/jadx/core/dex/visitors/FixAccessModifiers.java
.../main/java/jadx/core/dex/visitors/FixAccessModifiers.java
+1
-1
jadx-core/src/main/java/jadx/core/dex/visitors/MarkMethodsForInline.java
...ain/java/jadx/core/dex/visitors/MarkMethodsForInline.java
+6
-11
jadx-core/src/main/java/jadx/core/dex/visitors/ProcessAnonymous.java
...rc/main/java/jadx/core/dex/visitors/ProcessAnonymous.java
+8
-1
jadx-core/src/main/java/jadx/core/dex/visitors/ProcessMethodsForInline.java
.../java/jadx/core/dex/visitors/ProcessMethodsForInline.java
+60
-0
jadx-core/src/main/java/jadx/core/utils/ListUtils.java
jadx-core/src/main/java/jadx/core/utils/ListUtils.java
+28
-2
未找到文件。
jadx-core/src/main/java/jadx/core/Jadx.java
浏览文件 @
081a0e21
...
...
@@ -38,6 +38,7 @@ import jadx.core.dex.visitors.OverrideMethodVisitor;
import
jadx.core.dex.visitors.PrepareForCodeGen
;
import
jadx.core.dex.visitors.ProcessAnonymous
;
import
jadx.core.dex.visitors.ProcessInstructionsVisitor
;
import
jadx.core.dex.visitors.ProcessMethodsForInline
;
import
jadx.core.dex.visitors.ReSugarCode
;
import
jadx.core.dex.visitors.ShadowFieldVisitor
;
import
jadx.core.dex.visitors.SignatureProcessor
;
...
...
@@ -89,6 +90,7 @@ public class Jadx {
passes
.
add
(
new
RenameVisitor
());
passes
.
add
(
new
UsageInfoVisitor
());
passes
.
add
(
new
ProcessAnonymous
());
passes
.
add
(
new
ProcessMethodsForInline
());
return
passes
;
}
...
...
jadx-core/src/main/java/jadx/core/ProcessClass.java
浏览文件 @
081a0e21
package
jadx.core
;
import
java.util.ArrayList
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.Nullable
;
...
...
@@ -94,21 +89,13 @@ public final class ProcessClass {
return
generateCode
(
topParentClass
);
}
try
{
Set
<
ClassNode
>
useIn
=
new
HashSet
<>(
cls
.
getUseIn
());
List
<
ClassNode
>
usedInDeps
=
new
ArrayList
<>();
for
(
ClassNode
depCls
:
cls
.
getDependencies
())
{
if
(
useIn
.
contains
(
depCls
))
{
// postpone to resolve cross dependencies
usedInDeps
.
add
(
depCls
);
}
else
{
process
(
depCls
,
false
);
}
process
(
depCls
,
false
);
}
if
(!
usedInDeps
.
isEmpty
())
{
// process current class before its usage
if
(!
cls
.
getCodegenDeps
().
isEmpty
())
{
process
(
cls
,
false
);
for
(
ClassNode
depCls
:
usedInDeps
)
{
process
(
depCls
,
false
);
for
(
ClassNode
codegenDep
:
cls
.
getCodegenDeps
()
)
{
process
(
codegenDep
,
false
);
}
}
ICodeInfo
code
=
process
(
cls
,
true
);
...
...
jadx-core/src/main/java/jadx/core/dex/attributes/AFlag.java
浏览文件 @
081a0e21
...
...
@@ -79,6 +79,8 @@ public enum AFlag {
REQUEST_IF_REGION_OPTIMIZE
,
// run if region visitor again
RERUN_SSA_TRANSFORM
,
METHOD_CANDIDATE_FOR_INLINE
,
// Class processing flags
RESTART_CODEGEN
,
// codegen must be executed again
RELOAD_AT_CODEGEN_STAGE
,
// class can't be analyzed at 'process' stage => unload before 'codegen' stage
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
浏览文件 @
081a0e21
...
...
@@ -78,6 +78,10 @@ public class ClassNode extends NotificationAttrNode implements ILoadable, ICodeN
* Top level classes used in this class (only for top level classes, empty for inners)
*/
private
List
<
ClassNode
>
dependencies
=
Collections
.
emptyList
();
/**
* Top level classes needed for code generation stage
*/
private
List
<
ClassNode
>
codegenDeps
=
Collections
.
emptyList
();
/**
* Classes which uses this class
*/
...
...
@@ -735,6 +739,14 @@ public class ClassNode extends NotificationAttrNode implements ILoadable, ICodeN
this
.
dependencies
=
dependencies
;
}
public
List
<
ClassNode
>
getCodegenDeps
()
{
return
codegenDeps
;
}
public
void
setCodegenDeps
(
List
<
ClassNode
>
codegenDeps
)
{
this
.
codegenDeps
=
codegenDeps
;
}
public
List
<
ClassNode
>
getUseIn
()
{
return
useIn
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/FixAccessModifiers.java
浏览文件 @
081a0e21
...
...
@@ -86,7 +86,7 @@ public class FixAccessModifiers extends AbstractVisitor {
if
(!
accessFlags
.
isPublic
())
{
// if class is used in inlinable method => make it public
for
(
MethodNode
useMth
:
cls
.
getUseInMth
())
{
boolean
canInline
=
MarkMethodsForInline
.
canInline
(
useMth
)
||
useMth
.
contains
(
AType
.
METHOD_INLINE
);
boolean
canInline
=
useMth
.
contains
(
AFlag
.
METHOD_CANDIDATE_FOR_INLINE
)
||
useMth
.
contains
(
AType
.
METHOD_INLINE
);
if
(
canInline
&&
!
useMth
.
getUseIn
().
isEmpty
())
{
return
AccessFlags
.
PUBLIC
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/MarkMethodsForInline.java
浏览文件 @
081a0e21
...
...
@@ -10,7 +10,6 @@ import jadx.core.Consts;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.attributes.nodes.MethodInlineAttr
;
import
jadx.core.dex.info.AccessInfo
;
import
jadx.core.dex.info.FieldInfo
;
import
jadx.core.dex.instructions.IndexInsnNode
;
import
jadx.core.dex.instructions.InsnType
;
...
...
@@ -47,7 +46,7 @@ public class MarkMethodsForInline extends AbstractVisitor {
if
(
mia
!=
null
)
{
return
mia
;
}
if
(
canInline
(
mth
))
{
if
(
mth
.
contains
(
AFlag
.
METHOD_CANDIDATE_FOR_INLINE
))
{
if
(
mth
.
getBasicBlocks
()
==
null
)
{
return
null
;
}
...
...
@@ -59,14 +58,6 @@ public class MarkMethodsForInline extends AbstractVisitor {
return
MethodInlineAttr
.
inlineNotNeeded
(
mth
);
}
public
static
boolean
canInline
(
MethodNode
mth
)
{
if
(
mth
.
isNoCode
()
||
mth
.
contains
(
AFlag
.
DONT_GENERATE
))
{
return
false
;
}
AccessInfo
accessFlags
=
mth
.
getAccessFlags
();
return
accessFlags
.
isSynthetic
()
&&
accessFlags
.
isStatic
();
}
@Nullable
private
static
MethodInlineAttr
inlineMth
(
MethodNode
mth
)
{
List
<
InsnNode
>
insns
=
BlockUtils
.
collectInsnsWithLimit
(
mth
.
getBasicBlocks
(),
2
);
...
...
@@ -79,7 +70,11 @@ public class MarkMethodsForInline extends AbstractVisitor {
if
(
insn
.
getType
()
==
InsnType
.
RETURN
&&
insn
.
getArgsCount
()
==
1
)
{
// synthetic field getter
// set arg from 'return' instruction
return
addInlineAttr
(
mth
,
InsnNode
.
wrapArg
(
insn
.
getArg
(
0
)));
InsnArg
arg
=
insn
.
getArg
(
0
);
if
(!
arg
.
isInsnWrap
())
{
return
null
;
}
return
addInlineAttr
(
mth
,
((
InsnWrapArg
)
arg
).
getWrapInsn
());
}
// method invoke
return
addInlineAttr
(
mth
,
insn
);
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/ProcessAnonymous.java
浏览文件 @
081a0e21
...
...
@@ -66,8 +66,15 @@ public class ProcessAnonymous extends AbstractVisitor {
// actual usage of outer class will be removed at anonymous class process,
// see ModVisitor.processAnonymousConstructor method
ClassNode
outerCls
=
anonymousConstructor
.
getUseIn
().
get
(
0
).
getParentClass
();
ListUtils
.
safeRemove
(
cls
.
getDependencies
(),
outerCls
);
ClassNode
topOuterCls
=
outerCls
.
getTopParentClass
();
ListUtils
.
safeRemove
(
cls
.
getDependencies
(),
topOuterCls
);
ListUtils
.
safeRemove
(
outerCls
.
getUseIn
(),
cls
);
// move dependency to codegen stage
if
(
cls
.
isTopClass
())
{
topOuterCls
.
setDependencies
(
ListUtils
.
safeRemoveAndTrim
(
topOuterCls
.
getDependencies
(),
cls
));
topOuterCls
.
setCodegenDeps
(
ListUtils
.
safeAdd
(
topOuterCls
.
getCodegenDeps
(),
cls
));
}
}
/**
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/ProcessMethodsForInline.java
0 → 100644
浏览文件 @
081a0e21
package
jadx.core.dex.visitors
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.info.AccessInfo
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.nodes.RootNode
;
import
jadx.core.dex.visitors.usage.UsageInfoVisitor
;
import
jadx.core.utils.ListUtils
;
import
jadx.core.utils.exceptions.JadxException
;
@JadxVisitor
(
name
=
"ProcessMethodsForInline"
,
desc
=
"Mark methods for future inline"
,
runAfter
=
{
UsageInfoVisitor
.
class
}
)
public
class
ProcessMethodsForInline
extends
AbstractVisitor
{
private
boolean
inlineMethods
;
@Override
public
void
init
(
RootNode
root
)
{
inlineMethods
=
root
.
getArgs
().
isInlineMethods
();
}
@Override
public
boolean
visit
(
ClassNode
cls
)
throws
JadxException
{
if
(!
inlineMethods
)
{
return
false
;
}
for
(
MethodNode
mth
:
cls
.
getMethods
())
{
if
(
canInline
(
mth
))
{
mth
.
add
(
AFlag
.
METHOD_CANDIDATE_FOR_INLINE
);
fixClassDependencies
(
mth
);
}
}
return
true
;
}
private
static
boolean
canInline
(
MethodNode
mth
)
{
if
(
mth
.
isNoCode
()
||
mth
.
contains
(
AFlag
.
DONT_GENERATE
))
{
return
false
;
}
AccessInfo
accessFlags
=
mth
.
getAccessFlags
();
boolean
isSynthetic
=
accessFlags
.
isSynthetic
()
||
mth
.
getName
().
contains
(
"$"
);
return
isSynthetic
&&
accessFlags
.
isStatic
();
}
private
static
void
fixClassDependencies
(
MethodNode
mth
)
{
ClassNode
parentClass
=
mth
.
getTopParentClass
();
for
(
MethodNode
useInMth
:
mth
.
getUseIn
())
{
// remove possible cross dependency to force class with inline method to be processed before its
// usage
ClassNode
useTopCls
=
useInMth
.
getTopParentClass
();
parentClass
.
setDependencies
(
ListUtils
.
safeRemoveAndTrim
(
parentClass
.
getDependencies
(),
useTopCls
));
}
}
}
jadx-core/src/main/java/jadx/core/utils/ListUtils.java
浏览文件 @
081a0e21
...
...
@@ -63,8 +63,12 @@ public class ListUtils {
newList
.
add
(
newObj
);
return
newList
;
}
list
.
remove
(
oldObj
);
list
.
add
(
newObj
);
int
idx
=
list
.
indexOf
(
oldObj
);
if
(
idx
!=
-
1
)
{
list
.
set
(
idx
,
newObj
);
}
else
{
list
.
add
(
newObj
);
}
return
list
;
}
...
...
@@ -74,6 +78,28 @@ public class ListUtils {
}
}
public
static
<
T
>
List
<
T
>
safeRemoveAndTrim
(
List
<
T
>
list
,
T
obj
)
{
if
(
list
==
null
||
list
.
isEmpty
())
{
return
list
;
}
if
(
list
.
remove
(
obj
))
{
if
(
list
.
isEmpty
())
{
return
Collections
.
emptyList
();
}
}
return
list
;
}
public
static
<
T
>
List
<
T
>
safeAdd
(
List
<
T
>
list
,
T
obj
)
{
if
(
list
==
null
||
list
.
isEmpty
())
{
List
<
T
>
newList
=
new
ArrayList
<>(
1
);
newList
.
add
(
obj
);
return
newList
;
}
list
.
add
(
obj
);
return
list
;
}
/**
* Search exactly one element in list by filter
*
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录