1 /*
2  * Copyright (C) 2013 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_METHOD_REFERENCE_H_
18 #define ART_LIBDEXFILE_DEX_METHOD_REFERENCE_H_
19 
20 #include <stdint.h>
21 #include <string>
22 #include "dex/dex_file.h"
23 #include "dex/dex_file_reference.h"
24 #include "dex/proto_reference.h"
25 
26 namespace art {
27 
28 // A method is uniquely located by its DexFile and the method_ids_ table index into that DexFile
29 class MethodReference : public DexFileReference {
30  public:
MethodReference(const DexFile * file,uint32_t index)31   MethodReference(const DexFile* file, uint32_t index) : DexFileReference(file, index) {}
32   std::string PrettyMethod(bool with_signature = true) const {
33     return dex_file->PrettyMethod(index, with_signature);
34   }
GetMethodId()35   const dex::MethodId& GetMethodId() const {
36     return dex_file->GetMethodId(index);
37   }
GetProtoReference()38   const art::ProtoReference GetProtoReference() const {
39     return ProtoReference(dex_file, GetMethodId().proto_idx_);
40   }
41 };
42 
43 // Compare the actual referenced method signatures. Used for method reference deduplication.
44 struct MethodReferenceValueComparator {
operatorMethodReferenceValueComparator45   bool operator()(MethodReference mr1, MethodReference mr2) const {
46     if (mr1.dex_file == mr2.dex_file) {
47       DCHECK_EQ(mr1.index < mr2.index, SlowCompare(mr1, mr2));
48       return mr1.index < mr2.index;
49     } else {
50       return SlowCompare(mr1, mr2);
51     }
52   }
53 
SlowCompareMethodReferenceValueComparator54   bool SlowCompare(MethodReference mr1, MethodReference mr2) const {
55     // The order is the same as for method ids in a single dex file.
56     // Compare the class descriptors first.
57     const dex::MethodId& mid1 = mr1.GetMethodId();
58     const dex::MethodId& mid2 = mr2.GetMethodId();
59     int descriptor_diff = DexFile::CompareDescriptors(
60         mr1.dex_file->GetTypeDescriptorView(mid1.class_idx_),
61         mr2.dex_file->GetTypeDescriptorView(mid2.class_idx_));
62     if (descriptor_diff != 0) {
63       return descriptor_diff < 0;
64     }
65     // Compare names second.
66     int name_diff = DexFile::CompareMemberNames(mr1.dex_file->GetMethodNameView(mid1),
67                                                 mr2.dex_file->GetMethodNameView(mid2));
68     if (name_diff != 0) {
69       return name_diff < 0;
70     }
71     // Then compare protos.
72     return ProtoReferenceValueComparator()(mr1.GetProtoReference(), mr2.GetProtoReference());
73   }
74 };
75 
76 }  // namespace art
77 
78 #endif  // ART_LIBDEXFILE_DEX_METHOD_REFERENCE_H_
79