Skip to content

Commit

Permalink
Optimize AnnotationMatcher processing performance
Browse files Browse the repository at this point in the history
  • Loading branch information
teble committed Oct 11, 2023
1 parent 5b0b12c commit dcacafd
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 61 deletions.
18 changes: 10 additions & 8 deletions Core/dexkit/analyze.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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: {
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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());
Expand Down
79 changes: 48 additions & 31 deletions Core/dexkit/dex_item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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<dex::AnnotationsDirectoryItem>(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<const dex::u1 *>(dex_annotations + 1);
if (need_field_annotation) {
for (dex::u4 i = 0; i < dex_annotations->fields_size; ++i) {
auto dex_field_annotation = reinterpret_cast<const dex::FieldAnnotationsItem *>(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<const dex::MethodAnnotationsItem *>(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<ir::Annotation *> ann_vec;
ann_vec.reserve(annotation->annotations.size());
for (auto &parameter_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<const dex::ParameterAnnotationsItem *>(ptr);
auto dex_annotation_set_ref_list = reader.dataPtr<dex::AnnotationSetRefList>(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);
}
}
}
Expand Down Expand Up @@ -661,7 +678,7 @@ DexItem::GetClassAnnotationBeans(uint32_t class_idx) {
}
auto annotationSet = this->class_annotations[class_idx];
std::vector<AnnotationBean> beans;
for (auto annotation: annotationSet) {
for (auto annotation: annotationSet->annotations) {
AnnotationBean bean = GetAnnotationBean(annotation);
beans.emplace_back(std::move(bean));
}
Expand Down Expand Up @@ -697,7 +714,7 @@ DexItem::GetMethodAnnotationBeans(uint32_t method_idx) {
}
auto annotationSet = this->method_annotations[method_idx];
std::vector<AnnotationBean> beans;
for (auto annotation: annotationSet) {
for (auto annotation: annotationSet->annotations) {
AnnotationBean bean = GetAnnotationBean(annotation);
beans.emplace_back(std::move(bean));
}
Expand Down Expand Up @@ -733,7 +750,7 @@ DexItem::GetFieldAnnotationBeans(uint32_t field_idx) {
}
auto annotationSet = this->field_annotations[field_idx];
std::vector<AnnotationBean> beans;
for (auto annotation: annotationSet) {
for (auto annotation: annotationSet->annotations) {
AnnotationBean bean = GetAnnotationBean(annotation);
beans.emplace_back(std::move(bean));
}
Expand All @@ -746,7 +763,7 @@ DexItem::GetParameterAnnotationBeans(uint32_t method_idx) {
std::vector<std::vector<AnnotationBean>> beans;
for (auto &annotationSet: param_annotations) {
std::vector<AnnotationBean> annotationBeans;
for (auto annotation: annotationSet) {
for (auto annotation: annotationSet->annotations) {
AnnotationBean bean = GetAnnotationBean(annotation);
annotationBeans.emplace_back(std::move(bean));
}
Expand Down
18 changes: 12 additions & 6 deletions Core/dexkit/dex_item_matcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -208,11 +214,11 @@ bool DexItem::IsAnnotationMatched(const ir::Annotation *annotation, const schema
return true;
}

bool DexItem::IsAnnotationsMatched(const std::vector<ir::Annotation *> &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()) {
Expand All @@ -238,13 +244,13 @@ bool DexItem::IsAnnotationsMatched(const std::vector<ir::Annotation *> &annotati
if (annotation_matches.size() > annotation_set_size) {
return false;
}
Hungarian<ir::Annotation *, const schema::AnnotationMatcher *> hungarian(annotationSet, annotation_matches, IsAnnotationMatched);
Hungarian<ir::Annotation *, const schema::AnnotationMatcher *> 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;
}
}
Expand Down
15 changes: 4 additions & 11 deletions Core/dexkit/include/analyze.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
10 changes: 5 additions & 5 deletions Core/dexkit/include/dex_item.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ class DexItem {
);

bool IsAnnotationMatched(const ir::Annotation *annotation, const schema::AnnotationMatcher *matcher);
bool IsAnnotationsMatched(const std::vector<ir::Annotation *> &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<ir::EncodedValue *> &encodedValues, const dexkit::schema::AnnotationEncodeArrayMatcher *matcher);
bool IsAnnotationElementMatched(const ir::AnnotationElement *annotationElement, const schema::AnnotationElementMatcher *matcher);
Expand Down Expand Up @@ -256,10 +256,10 @@ class DexItem {
// method parameter types
std::vector<const dex::TypeList *> proto_type_list;
std::vector<std::optional<std::vector<uint8_t /*opcode*/>>> method_opcode_seq;
std::vector<std::vector<ir::Annotation *>> class_annotations;
std::vector<std::vector<ir::Annotation *>> method_annotations;
std::vector<std::vector<ir::Annotation *>> field_annotations;
std::vector<std::vector<std::vector<ir::Annotation *>>> method_parameter_annotations;
std::vector<ir::AnnotationSet *> class_annotations;
std::vector<ir::AnnotationSet *> method_annotations;
std::vector<ir::AnnotationSet *> field_annotations;
std::vector<std::vector<ir::AnnotationSet *>> method_parameter_annotations;

std::vector<std::optional<std::pair<uint16_t, uint32_t>>> method_cross_info;
std::vector<std::optional<std::pair<uint16_t, uint32_t>>> field_cross_info;
Expand Down

0 comments on commit dcacafd

Please sign in to comment.