From dc2977b3d668479b65ae076fa4442362ba726f3a Mon Sep 17 00:00:00 2001 From: "Wei Zhang (Devinfra)" Date: Tue, 23 Apr 2024 21:54:24 -0700 Subject: [PATCH] Mark merged field final if all input fields are final Summary: If all the input fields are `final`, we keep them as final in the merged class. There seems to be a growing trend that Kotlin code tends to mark fields with `final` by default. Reviewed By: NTillmann Differential Revision: D56374098 fbshipit-source-id: 11309a1ed8b3bfac93e99d638a9cccc0beaf9b67 --- .../class-merging/ClassAssemblingUtils.cpp | 24 ++++++++++++++++--- service/class-merging/ClassAssemblingUtils.h | 4 ++-- service/class-merging/ModelMerger.cpp | 7 +++--- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/service/class-merging/ClassAssemblingUtils.cpp b/service/class-merging/ClassAssemblingUtils.cpp index ce72487091..70e49aaca8 100644 --- a/service/class-merging/ClassAssemblingUtils.cpp +++ b/service/class-merging/ClassAssemblingUtils.cpp @@ -104,11 +104,12 @@ DexClass* create_class(const DexType* type, return cls; } -std::vector create_merger_fields( - const DexType* owner, const std::vector& mergeable_fields) { +std::vector create_merger_fields(const DexType* owner, + const FieldsMap& fields_map) { std::vector res; + const auto& mergeable_fields = fields_map.begin()->second; size_t cnt = 0; - for (const auto f : mergeable_fields) { + for (const auto* f : mergeable_fields) { auto type = f->get_type(); std::string name; if (type == type::_byte() || type == type::_char() || @@ -147,6 +148,23 @@ std::vector create_merger_fields( cnt++; } + std::vector acc_final_map(mergeable_fields.size(), true); + for (const auto& fmap : fields_map) { + const auto& fields = fmap.second; + for (size_t i = 0; i < fields.size(); i++) { + redex_assert(acc_final_map.size() > i); + acc_final_map[i] = acc_final_map.at(i) && is_final(fields[i]); + } + } + + for (size_t i = 0; i < res.size(); i++) { + redex_assert(acc_final_map.size() > i); + if (acc_final_map[i]) { + set_final(res.at(i)); + TRACE(CLMG, 5, "marking merger field final %s", SHOW(res.at(i))); + } + } + TRACE(CLMG, 8, " created merger fields %zu ", res.size()); return res; } diff --git a/service/class-merging/ClassAssemblingUtils.h b/service/class-merging/ClassAssemblingUtils.h index 3e5faa0392..6a25267bf0 100644 --- a/service/class-merging/ClassAssemblingUtils.h +++ b/service/class-merging/ClassAssemblingUtils.h @@ -21,8 +21,8 @@ struct ModelSpec; constexpr const char* INTERNAL_TYPE_TAG_FIELD_NAME = "$t"; constexpr const char* EXTERNAL_TYPE_TAG_FIELD_NAME = "mTypeTag"; -std::vector create_merger_fields( - const DexType* owner, const std::vector& mergeable_fields); +std::vector create_merger_fields(const DexType* owner, + const FieldsMap& fields_map); void cook_merger_fields_lookup( const std::vector& new_fields, diff --git a/service/class-merging/ModelMerger.cpp b/service/class-merging/ModelMerger.cpp index 80c8288987..7a75a33611 100644 --- a/service/class-merging/ModelMerger.cpp +++ b/service/class-merging/ModelMerger.cpp @@ -504,10 +504,9 @@ const std::vector ModelMerger::empty_fields = std::vector(); void ModelMerger::update_merger_fields(const MergerType& merger) { - auto merger_fields = - merger.has_fields() - ? create_merger_fields(merger.type, merger.field_map.begin()->second) - : empty_fields; + auto merger_fields = merger.has_fields() + ? create_merger_fields(merger.type, merger.field_map) + : empty_fields; m_merger_fields[merger.type] = merger_fields; }