1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_LIBDEXFILE_DEX_PROTO_REFERENCE_H_ 18 #define ART_LIBDEXFILE_DEX_PROTO_REFERENCE_H_ 19 20 #include <stdint.h> 21 22 #include <android-base/logging.h> 23 #include <string_view> 24 25 #include "dex/dex_file-inl.h" 26 #include "dex/dex_file_reference.h" 27 #include "dex/dex_file_types.h" 28 29 namespace art { 30 31 // A proto is located by its DexFile and the proto_ids_ table index into that DexFile. 32 class ProtoReference : public DexFileReference { 33 public: ProtoReference(const DexFile * file,dex::ProtoIndex index)34 ProtoReference(const DexFile* file, dex::ProtoIndex index) 35 : DexFileReference(file, index.index_) {} 36 ProtoIndex()37 dex::ProtoIndex ProtoIndex() const { 38 return dex::ProtoIndex(index); 39 } 40 ProtoId()41 const dex::ProtoId& ProtoId() const { 42 return dex_file->GetProtoId(ProtoIndex()); 43 } 44 ReturnType()45 std::string_view ReturnType() const { 46 return dex_file->GetTypeDescriptorView(dex_file->GetTypeId(ProtoId().return_type_idx_)); 47 } 48 }; 49 50 struct ProtoReferenceValueComparator { operatorProtoReferenceValueComparator51 bool operator()(const ProtoReference& lhs, const ProtoReference& rhs) const { 52 if (lhs.dex_file == rhs.dex_file) { 53 DCHECK_EQ(lhs.index < rhs.index, SlowCompare(lhs, rhs)); 54 55 return lhs.index < rhs.index; 56 } else { 57 return SlowCompare(lhs, rhs); 58 } 59 } 60 SlowCompareProtoReferenceValueComparator61 bool SlowCompare(const ProtoReference& lhs, const ProtoReference& rhs) const { 62 // Compare return type first. 63 const dex::ProtoId& prid1 = lhs.ProtoId(); 64 const dex::ProtoId& prid2 = rhs.ProtoId(); 65 int return_type_diff = DexFile::CompareDescriptors(lhs.ReturnType(), rhs.ReturnType()); 66 if (return_type_diff != 0) { 67 return return_type_diff < 0; 68 } 69 // And then compare parameters lexicographically. 70 const dex::TypeList* params1 = lhs.dex_file->GetProtoParameters(prid1); 71 size_t param1_size = (params1 != nullptr) ? params1->Size() : 0u; 72 const dex::TypeList* params2 = rhs.dex_file->GetProtoParameters(prid2); 73 size_t param2_size = (params2 != nullptr) ? params2->Size() : 0u; 74 for (size_t i = 0, num = std::min(param1_size, param2_size); i != num; ++i) { 75 std::string_view l_param = lhs.dex_file->GetTypeDescriptorView( 76 lhs.dex_file->GetTypeId(params1->GetTypeItem(i).type_idx_)); 77 std::string_view r_param = rhs.dex_file->GetTypeDescriptorView( 78 rhs.dex_file->GetTypeId(params2->GetTypeItem(i).type_idx_)); 79 80 int param_diff = DexFile::CompareDescriptors(l_param, r_param); 81 if (param_diff != 0) { 82 return param_diff < 0; 83 } 84 } 85 return param1_size < param2_size; 86 } 87 }; 88 89 } // namespace art 90 91 #endif // ART_LIBDEXFILE_DEX_PROTO_REFERENCE_H_ 92