From dcacafd97c475782d6bb3171c08040d76d14f851 Mon Sep 17 00:00:00 2001 From: teble Date: Wed, 11 Oct 2023 23:12:02 +0800 Subject: [PATCH] Optimize AnnotationMatcher processing performance --- Core/dexkit/analyze.cpp | 18 ++++---- Core/dexkit/dex_item.cpp | 79 +++++++++++++++++++------------- Core/dexkit/dex_item_matcher.cpp | 18 +++++--- Core/dexkit/include/analyze.h | 15 ++---- Core/dexkit/include/dex_item.h | 10 ++-- 5 files changed, 79 insertions(+), 61 deletions(-) diff --git a/Core/dexkit/analyze.cpp b/Core/dexkit/analyze.cpp index 164e529e..b296f519 100644 --- a/Core/dexkit/analyze.cpp +++ b/Core/dexkit/analyze.cpp @@ -26,19 +26,18 @@ AnalyzeRet Analyze(const schema::ClassMatcher *matcher, int dex_depth) { ret.declare_class.insert(ret.declare_class.end(), result.declare_class.begin(), result.declare_class.end()); } if (matcher->annotations()) { + ret.need_flags |= kClassAnnotation; // class 的注解必定存在于本 dex 中 auto result = Analyze(matcher->annotations(), dex_depth); ret.need_flags |= result.need_flags; ret.declare_class.insert(ret.declare_class.end(), result.declare_class.begin(), result.declare_class.end()); } if (matcher->fields()) { - ret.need_flags |= kClassField; auto result = Analyze(matcher->fields(), dex_depth); ret.need_flags |= result.need_flags; ret.declare_class.insert(ret.declare_class.end(), result.declare_class.begin(), result.declare_class.end()); } if (matcher->methods()) { - ret.need_flags |= kClassMethod; auto result = Analyze(matcher->methods(), dex_depth); ret.need_flags |= result.need_flags; ret.declare_class.insert(ret.declare_class.end(), result.declare_class.begin(), result.declare_class.end()); @@ -65,6 +64,7 @@ AnalyzeRet Analyze(const schema::FieldMatcher *matcher, int dex_depth) { ret.declare_class.insert(ret.declare_class.end(), result.declare_class.begin(), result.declare_class.end()); } if (matcher->annotations()) { + ret.need_flags |= kFieldAnnotation; // field 的注解必定存在于本 dex 中 auto result = Analyze(matcher->annotations(), dex_depth); ret.need_flags |= result.need_flags; @@ -115,6 +115,7 @@ AnalyzeRet Analyze(const schema::MethodMatcher *matcher, int dex_depth) { ret.declare_class.insert(ret.declare_class.end(), result.declare_class.begin(), result.declare_class.end()); } if (matcher->annotations()) { + ret.need_flags |= kMethodAnnotation; // method 的注解必定存在于本 dex 中 auto result = Analyze(matcher->annotations(), dex_depth); ret.need_flags |= result.need_flags; @@ -157,7 +158,7 @@ AnalyzeRet Analyze(const schema::MethodMatcher *matcher, int dex_depth) { AnalyzeRet Analyze(const schema::AnnotationEncodeArrayMatcher *matcher, int dex_depth) { if (!matcher) return {}; - AnalyzeRet ret{.need_flags = kAnnotation}; + AnalyzeRet ret{}; if (matcher->values()) { for (auto i = 0; i < matcher->values()->size(); ++i) { auto type = matcher->values_type()->Get(i); @@ -196,7 +197,7 @@ AnalyzeRet Analyze(const schema::AnnotationEncodeArrayMatcher *matcher, int dex_ AnalyzeRet Analyze(const schema::AnnotationElementMatcher *matcher, int dex_depth) { if (!matcher) return {}; - AnalyzeRet ret{.need_flags = kAnnotation}; + AnalyzeRet ret{}; if (matcher->value()) { switch (matcher->value_type()) { case schema::AnnotationEncodeValueMatcher::ClassMatcher: { @@ -232,7 +233,7 @@ AnalyzeRet Analyze(const schema::AnnotationElementMatcher *matcher, int dex_dept AnalyzeRet Analyze(const schema::AnnotationElementsMatcher *matcher, int dex_depth) { if (!matcher) return {}; - AnalyzeRet ret{.need_flags = kAnnotation}; + AnalyzeRet ret{}; if (matcher->elements()) { for (auto i = 0; i < matcher->elements()->size(); ++i) { auto result = Analyze(matcher->elements()->Get(i), dex_depth); @@ -245,7 +246,7 @@ AnalyzeRet Analyze(const schema::AnnotationElementsMatcher *matcher, int dex_dep AnalyzeRet Analyze(const schema::AnnotationMatcher *matcher, int dex_depth) { if (!matcher) return {}; - AnalyzeRet ret{.need_flags = kAnnotation}; + AnalyzeRet ret{}; if (matcher->type()) { auto result = Analyze(matcher->type(), dex_depth + 1); ret.need_flags |= result.need_flags; @@ -261,7 +262,7 @@ AnalyzeRet Analyze(const schema::AnnotationMatcher *matcher, int dex_depth) { AnalyzeRet Analyze(const schema::AnnotationsMatcher *matcher, int dex_depth) { if (!matcher) return {}; - AnalyzeRet ret{.need_flags = kAnnotation}; + AnalyzeRet ret{}; if (matcher->annotations()) { for (auto i = 0; i < matcher->annotations()->size(); ++i) { auto result = Analyze(matcher->annotations()->Get(i), dex_depth); @@ -274,7 +275,7 @@ AnalyzeRet Analyze(const schema::AnnotationsMatcher *matcher, int dex_depth) { AnalyzeRet Analyze(const schema::InterfacesMatcher *matcher, int dex_depth) { if (!matcher) return {}; - AnalyzeRet ret{.need_flags = kInterface}; + AnalyzeRet ret{}; if (matcher->interfaces()) { for (auto i = 0; i < matcher->interfaces()->size(); ++i) { auto result = Analyze(matcher->interfaces()->Get(i), dex_depth); @@ -322,6 +323,7 @@ AnalyzeRet Analyze(const schema::ParameterMatcher *matcher, int dex_depth) { ret.declare_class.insert(ret.declare_class.end(), result.declare_class.begin(), result.declare_class.end()); } if (matcher->annotations()) { + ret.need_flags |= kParamAnnotation; auto result = Analyze(matcher->annotations(), dex_depth); ret.need_flags |= result.need_flags; ret.declare_class.insert(ret.declare_class.end(), result.declare_class.begin(), result.declare_class.end()); diff --git a/Core/dexkit/dex_item.cpp b/Core/dexkit/dex_item.cpp index f2164195..48014c23 100644 --- a/Core/dexkit/dex_item.cpp +++ b/Core/dexkit/dex_item.cpp @@ -216,7 +216,11 @@ void DexItem::InitCache(uint32_t init_flags) { bool need_method_invoking = init_flags & kMethodInvoking && (dex_flag & kMethodInvoking) == 0; bool need_method_caller = init_flags & kCallerMethod && (dex_flag & kCallerMethod) == 0; bool need_field_rw_method = init_flags & kRwFieldMethod && (dex_flag & kRwFieldMethod) == 0; - bool need_annotation = init_flags & kAnnotation && (dex_flag & kAnnotation) == 0; + bool need_class_annotation = init_flags & kClassAnnotation && (dex_flag & kClassAnnotation) == 0; + bool need_field_annotation = init_flags & kFieldAnnotation && (dex_flag & kFieldAnnotation) == 0; + bool need_method_annotation = init_flags & kMethodAnnotation && (dex_flag & kMethodAnnotation) == 0; + bool need_param_annotation = init_flags & kParamAnnotation && (dex_flag & kParamAnnotation) == 0; + bool need_annotation = need_class_annotation || need_field_annotation || need_method_annotation || need_param_annotation; bool need_method_using_number = init_flags & kUsingNumber && (dex_flag & kUsingNumber) == 0; if (need_op_seq) { @@ -346,42 +350,55 @@ void DexItem::InitCache(uint32_t init_flags) { } if (need_annotation) { - class_annotations.resize(reader.TypeIds().size()); - field_annotations.resize(reader.FieldIds().size()); - method_annotations.resize(reader.MethodIds().size()); - method_parameter_annotations.resize(reader.MethodIds().size()); + if (need_class_annotation) { + class_annotations.resize(reader.TypeIds().size()); + } + if (need_field_annotation) { + field_annotations.resize(reader.FieldIds().size()); + } + if (need_method_annotation) { + method_annotations.resize(reader.MethodIds().size()); + } + if (need_param_annotation) { + method_parameter_annotations.resize(reader.MethodIds().size()); + } + for (auto &class_def: reader.ClassDefs()) { if (class_def.annotations_off == 0) { continue; } - auto annotations = reader.ExtractAnnotations(class_def.annotations_off); - if (annotations->class_annotation) { - auto &class_annotation = class_annotations[class_def.class_idx]; - for (auto &annotation: annotations->class_annotation->annotations) { - class_annotation.emplace_back(annotation); - } + auto dex_annotations = reader.dataPtr(class_def.annotations_off); + if (need_class_annotation) { + class_annotations[class_def.class_idx] = reader.ExtractAnnotationSet(dex_annotations->class_annotations_off); } - for (auto value: annotations->field_annotations) { - auto &field_annotation = field_annotations[value->field_decl->orig_index]; - for (auto &annotation: value->annotations->annotations) { - field_annotation.emplace_back(annotation); + auto *ptr = reinterpret_cast(dex_annotations + 1); + if (need_field_annotation) { + for (dex::u4 i = 0; i < dex_annotations->fields_size; ++i) { + auto dex_field_annotation = reinterpret_cast(ptr); + field_annotations[dex_field_annotation->field_idx] = reader.ExtractAnnotationSet(dex_field_annotation->annotations_off); + ptr += sizeof(dex::FieldAnnotationsItem); } + } else { + ptr += dex_annotations->fields_size * sizeof(dex::FieldAnnotationsItem); } - for (auto value: annotations->method_annotations) { - auto &method_annotation = method_annotations[value->method_decl->orig_index]; - for (auto &annotation: value->annotations->annotations) { - method_annotation.emplace_back(annotation); + if (need_method_annotation) { + for (dex::u4 i = 0; i < dex_annotations->methods_size; ++i) { + auto dex_method_annotation = reinterpret_cast(ptr); + method_annotations[dex_method_annotation->method_idx] = reader.ExtractAnnotationSet(dex_method_annotation->annotations_off); + ptr += sizeof(dex::MethodAnnotationsItem); } + } else { + ptr += dex_annotations->methods_size * sizeof(dex::MethodAnnotationsItem); } - for (auto value: annotations->param_annotations) { - auto &method_parameter_annotation = method_parameter_annotations[value->method_decl->orig_index]; - for (auto &annotation: value->annotations->annotations) { - std::vector ann_vec; - ann_vec.reserve(annotation->annotations.size()); - for (auto ¶meter_annotation: annotation->annotations) { - ann_vec.emplace_back(parameter_annotation); + if (need_param_annotation) { + for (dex::u4 i = 0; i < dex_annotations->parameters_size; ++i) { + auto dex_parameter_annotation = reinterpret_cast(ptr); + auto dex_annotation_set_ref_list = reader.dataPtr(dex_parameter_annotation->annotations_off); + for (dex::u4 j = 0; j < dex_annotation_set_ref_list->size; ++j) { + auto dex_annotation_set_ref_item = dex_annotation_set_ref_list->list[j]; + method_parameter_annotations[dex_parameter_annotation->method_idx].emplace_back(reader.ExtractAnnotationSet(dex_annotation_set_ref_item.annotations_off)); } - method_parameter_annotation.emplace_back(ann_vec); + ptr += sizeof(dex::ParameterAnnotationsItem); } } } @@ -661,7 +678,7 @@ DexItem::GetClassAnnotationBeans(uint32_t class_idx) { } auto annotationSet = this->class_annotations[class_idx]; std::vector beans; - for (auto annotation: annotationSet) { + for (auto annotation: annotationSet->annotations) { AnnotationBean bean = GetAnnotationBean(annotation); beans.emplace_back(std::move(bean)); } @@ -697,7 +714,7 @@ DexItem::GetMethodAnnotationBeans(uint32_t method_idx) { } auto annotationSet = this->method_annotations[method_idx]; std::vector beans; - for (auto annotation: annotationSet) { + for (auto annotation: annotationSet->annotations) { AnnotationBean bean = GetAnnotationBean(annotation); beans.emplace_back(std::move(bean)); } @@ -733,7 +750,7 @@ DexItem::GetFieldAnnotationBeans(uint32_t field_idx) { } auto annotationSet = this->field_annotations[field_idx]; std::vector beans; - for (auto annotation: annotationSet) { + for (auto annotation: annotationSet->annotations) { AnnotationBean bean = GetAnnotationBean(annotation); beans.emplace_back(std::move(bean)); } @@ -746,7 +763,7 @@ DexItem::GetParameterAnnotationBeans(uint32_t method_idx) { std::vector> beans; for (auto &annotationSet: param_annotations) { std::vector annotationBeans; - for (auto annotation: annotationSet) { + for (auto annotation: annotationSet->annotations) { AnnotationBean bean = GetAnnotationBean(annotation); annotationBeans.emplace_back(std::move(bean)); } diff --git a/Core/dexkit/dex_item_matcher.cpp b/Core/dexkit/dex_item_matcher.cpp index a9755eae..ae5261ed 100644 --- a/Core/dexkit/dex_item_matcher.cpp +++ b/Core/dexkit/dex_item_matcher.cpp @@ -154,14 +154,20 @@ bool DexItem::IsAnnotationMatched(const ir::Annotation *annotation, const schema if (matcher == nullptr) { return true; } + if (annotation == nullptr) { + return false; + } if (!IsClassMatched(annotation->type->orig_index, matcher->type())) { return false; } - auto type_annotations = this->class_annotations[annotation->type->orig_index]; + auto m_class_annotations = this->class_annotations[annotation->type->orig_index]; if (matcher->target_element_types() || (uint8_t) matcher->policy()) { + if (m_class_annotations == nullptr) { + return false; + } ir::Annotation *retention_annotation = nullptr; ir::Annotation *target_annotation = nullptr; - for (auto ann: type_annotations) { + for (auto ann: m_class_annotations->annotations) { if (ann->type->orig_index == this->annotation_retention_class_id) { retention_annotation = ann; } else if (ann->type->orig_index == this->annotation_target_class_id) { @@ -208,11 +214,11 @@ bool DexItem::IsAnnotationMatched(const ir::Annotation *annotation, const schema return true; } -bool DexItem::IsAnnotationsMatched(const std::vector &annotationSet, const schema::AnnotationsMatcher *matcher) { +bool DexItem::IsAnnotationsMatched(const ir::AnnotationSet *annotationSet, const schema::AnnotationsMatcher *matcher) { if (matcher == nullptr) { return true; } - auto annotation_set_size = annotationSet.size(); + auto annotation_set_size = annotationSet == nullptr ? 0 : annotationSet->annotations.size(); if (matcher->annotation_count()) { if (annotation_set_size < matcher->annotation_count()->min() || annotation_set_size > matcher->annotation_count()->max()) { @@ -238,13 +244,13 @@ bool DexItem::IsAnnotationsMatched(const std::vector &annotati if (annotation_matches.size() > annotation_set_size) { return false; } - Hungarian hungarian(annotationSet, annotation_matches, IsAnnotationMatched); + Hungarian hungarian(annotationSet->annotations, annotation_matches, IsAnnotationMatched); auto count = hungarian.solve(); if (count != annotation_matches.size()) { return false; } if (matcher->match_type() == schema::MatchType::Equal) { - if (count != annotationSet.size()) { + if (count != annotation_set_size) { return false; } } diff --git a/Core/dexkit/include/analyze.h b/Core/dexkit/include/analyze.h index 5001943f..abc5503d 100644 --- a/Core/dexkit/include/analyze.h +++ b/Core/dexkit/include/analyze.h @@ -10,18 +10,11 @@ namespace dexkit { -// must init before use -const uint32_t kString = 0x0001; -const uint32_t kClass = 0x0002; -const uint32_t kField = 0x0004; -const uint32_t kMethod = 0x0008; - -const uint32_t kInterface = 0x0010; -const uint32_t kClassField = 0x0020; -const uint32_t kClassMethod = 0x0040; - // optional init -const uint32_t kAnnotation = 0x0080; +const uint32_t kClassAnnotation = 0x0010; +const uint32_t kFieldAnnotation = 0x0020; +const uint32_t kMethodAnnotation = 0x0040; +const uint32_t kParamAnnotation = 0x0080; // code const uint32_t kUsingString = 0x0100; diff --git a/Core/dexkit/include/dex_item.h b/Core/dexkit/include/dex_item.h index 8bf13cfa..66154b0b 100644 --- a/Core/dexkit/include/dex_item.h +++ b/Core/dexkit/include/dex_item.h @@ -183,7 +183,7 @@ class DexItem { ); bool IsAnnotationMatched(const ir::Annotation *annotation, const schema::AnnotationMatcher *matcher); - bool IsAnnotationsMatched(const std::vector &annotationSet, const schema::AnnotationsMatcher *matcher); + bool IsAnnotationsMatched(const ir::AnnotationSet *annotationSet, const schema::AnnotationsMatcher *matcher); bool IsAnnotationEncodeValueMatched(const ir::EncodedValue *encodedValue, schema::AnnotationEncodeValueMatcher type, const void *value); bool IsAnnotationEncodeArrayMatcher(const std::vector &encodedValues, const dexkit::schema::AnnotationEncodeArrayMatcher *matcher); bool IsAnnotationElementMatched(const ir::AnnotationElement *annotationElement, const schema::AnnotationElementMatcher *matcher); @@ -256,10 +256,10 @@ class DexItem { // method parameter types std::vector proto_type_list; std::vector>> method_opcode_seq; - std::vector> class_annotations; - std::vector> method_annotations; - std::vector> field_annotations; - std::vector>> method_parameter_annotations; + std::vector class_annotations; + std::vector method_annotations; + std::vector field_annotations; + std::vector> method_parameter_annotations; std::vector>> method_cross_info; std::vector>> field_cross_info;