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