Skip to content

Commit afeefae

Browse files
thezhangweimeta-codesync[bot]
authored andcommitted
Relax can delete class check for ifields on anonymous classes
Summary: The synthesized ifields of Kotlin lambda classes can be kept by overly conservative keep rules. It's not necessary to drop the majority of them from the merging targets because of that. Reviewed By: wsanville Differential Revision: D90085706 fbshipit-source-id: 089bb30b713345e5c5f01652b80111a20c7f94e8
1 parent 176304e commit afeefae

File tree

4 files changed

+29
-10
lines changed

4 files changed

+29
-10
lines changed

libredex/TypeUtil.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,14 @@ bool is_kotlin_non_capturing_lambda(const DexClass* cls) {
598598
return false;
599599
}
600600

601+
bool is_kotlin_internal_type(const DexType* type) {
602+
return type == type::kotlin_jvm_internal_Lambda() ||
603+
type == type::kotlin_coroutines_jvm_internal_ContinuationImpl() ||
604+
type ==
605+
type::kotlin_coroutines_jvm_internal_RestrictedSuspendLambda() ||
606+
type == type::kotlin_coroutines_jvm_internal_SuspendLambda();
607+
}
608+
601609
bool is_min_sdk_acceptable_impl(const DexType* source_type,
602610
const DexType* cur_type,
603611
const DexType* target_type,

libredex/TypeUtil.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,8 @@ bool is_kotlin_class(DexClass* cls);
291291

292292
bool is_kotlin_function_interface(const DexType* type);
293293

294+
bool is_kotlin_internal_type(const DexType* type);
295+
294296
/*
295297
* Return true if the cls is kotlin non capturing lambda.
296298
*/

libredex/WellKnownTypes.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,13 @@
4141
"Ldalvik/annotation/optimization/NeverCompile;") \
4242
FOR_EACH(dalvik_annotation_optimization_NeverInline, \
4343
"Ldalvik/annotation/optimization/NeverInline;") \
44-
FOR_EACH(kotlin_jvm_internal_Lambda, "Lkotlin/jvm/internal/Lambda;")
44+
FOR_EACH(kotlin_jvm_internal_Lambda, "Lkotlin/jvm/internal/Lambda;") \
45+
FOR_EACH(kotlin_coroutines_jvm_internal_ContinuationImpl, \
46+
"Lkotlin/coroutines/jvm/internal/ContinuationImpl;") \
47+
FOR_EACH(kotlin_coroutines_jvm_internal_RestrictedSuspendLambda, \
48+
"Lkotlin/coroutines/jvm/internal/RestrictedSuspendLambda;") \
49+
FOR_EACH(kotlin_coroutines_jvm_internal_SuspendLambda, \
50+
"Lkotlin/coroutines/jvm/internal/SuspendLambda;")
4551

4652
#define PRIMITIVE_PSEUDO_TYPE_FIELDS \
4753
FOR_EACH(Void_TYPE, "Ljava/lang/Void;.TYPE:Ljava/lang/Class;") \

opt/class-merging/ModelSpecGenerator.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ namespace {
2828
* overly-conservative rules. So we loose the checking for the constructors of
2929
* anonymous classes.
3030
*/
31-
bool can_delete_class(const DexClass* cls, bool is_anonymous_class) {
31+
bool can_delete_class(const DexClass* cls,
32+
bool is_anonymous_class,
33+
bool is_kotlin_internal_subtype) {
3234
if (!can_delete(cls)) {
3335
return false;
3436
}
@@ -38,15 +40,15 @@ bool can_delete_class(const DexClass* cls, bool is_anonymous_class) {
3840
return false;
3941
}
4042
const auto& dmethods = cls->get_dmethods();
41-
if (std::any_of(dmethods.begin(), dmethods.end(),
42-
[&is_anonymous_class](const DexMethod* m) {
43-
return (!is_anonymous_class || !is_constructor(m)) &&
44-
!can_delete(m);
45-
})) {
43+
if (!is_anonymous_class &&
44+
std::any_of(dmethods.begin(), dmethods.end(), [](const DexMethod* m) {
45+
return (!is_constructor(m)) && !can_delete(m);
46+
})) {
4647
return false;
4748
}
4849
const auto& ifields = cls->get_ifields();
49-
if (std::any_of(ifields.begin(), ifields.end(),
50+
if (!is_kotlin_internal_subtype &&
51+
std::any_of(ifields.begin(), ifields.end(),
5052
[](const DexField* f) { return !can_delete(f); })) {
5153
return false;
5254
}
@@ -156,11 +158,12 @@ void find_all_mergeables_and_roots(const TypeSystem& type_system,
156158
if (!children.empty()) {
157159
continue;
158160
}
159-
if (!can_delete_class(cls, is_anonymous_class)) {
161+
auto* super_cls = cls->get_super_class();
162+
bool is_kotlin_internal_type = type::is_kotlin_internal_type(super_cls);
163+
if (!can_delete_class(cls, is_anonymous_class, is_kotlin_internal_type)) {
160164
continue;
161165
}
162166
auto* intfs = cls->get_interfaces();
163-
auto* super_cls = cls->get_super_class();
164167
if (super_cls != type::java_lang_Object()) {
165168
parent_children[super_cls].push_back(cur_type);
166169
} else if (!intfs->empty()) {

0 commit comments

Comments
 (0)