• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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_RUNTIME_IMTABLE_INL_H_
18 #define ART_RUNTIME_IMTABLE_INL_H_
19 
20 #include "imtable.h"
21 
22 #include "art_method-inl.h"
23 #include "dex/dex_file.h"
24 #include "dex/utf.h"
25 
26 namespace art HIDDEN {
27 
28 static constexpr bool kImTableHashUseName = true;
29 static constexpr bool kImTableHashUseCoefficients = true;
30 
31 // Magic configuration that minimizes some common runtime calls.
32 static constexpr uint32_t kImTableHashCoefficientClass = 427;
33 static constexpr uint32_t kImTableHashCoefficientName = 16;
34 static constexpr uint32_t kImTableHashCoefficientSignature = 14;
35 
GetImtHashComponents(const DexFile & dex_file,uint32_t dex_method_index,uint32_t * class_hash,uint32_t * name_hash,uint32_t * signature_hash)36 inline void ImTable::GetImtHashComponents(const DexFile& dex_file,
37                                           uint32_t dex_method_index,
38                                           uint32_t* class_hash,
39                                           uint32_t* name_hash,
40                                           uint32_t* signature_hash) {
41   if (kImTableHashUseName) {
42     const dex::MethodId& method_id = dex_file.GetMethodId(dex_method_index);
43 
44     // Class descriptor for the class component.
45     *class_hash = ComputeModifiedUtf8Hash(dex_file.GetMethodDeclaringClassDescriptor(method_id));
46 
47     // Method name for the method component.
48     *name_hash = ComputeModifiedUtf8Hash(dex_file.GetMethodName(method_id));
49 
50     const dex::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id);
51 
52     // Read the proto for the signature component.
53     uint32_t tmp = ComputeModifiedUtf8Hash(
54         dex_file.GetTypeDescriptor(dex_file.GetTypeId(proto_id.return_type_idx_)));
55 
56     // Mix in the argument types.
57     // Note: we could consider just using the shorty. This would be faster, at the price of
58     //       potential collisions.
59     const dex::TypeList* param_types = dex_file.GetProtoParameters(proto_id);
60     if (param_types != nullptr) {
61       for (size_t i = 0; i != param_types->Size(); ++i) {
62         const dex::TypeItem& type = param_types->GetTypeItem(i);
63         tmp = 31 * tmp + ComputeModifiedUtf8Hash(
64             dex_file.GetTypeDescriptor(dex_file.GetTypeId(type.type_idx_)));
65       }
66     }
67 
68     *signature_hash = tmp;
69     return;
70   } else {
71     *class_hash = dex_method_index;
72     *name_hash = 0;
73     *signature_hash = 0;
74     return;
75   }
76 }
77 
GetImtIndexForAbstractMethod(const DexFile & dex_file,uint32_t dex_method_index)78 inline uint32_t ImTable::GetImtIndexForAbstractMethod(const DexFile& dex_file,
79                                                       uint32_t dex_method_index) {
80   uint32_t class_hash, name_hash, signature_hash;
81   GetImtHashComponents(dex_file, dex_method_index, &class_hash, &name_hash, &signature_hash);
82 
83   uint32_t mixed_hash;
84   if (!kImTableHashUseCoefficients) {
85     mixed_hash = class_hash + name_hash + signature_hash;
86   } else {
87     mixed_hash = kImTableHashCoefficientClass * class_hash +
88                  kImTableHashCoefficientName * name_hash +
89                  kImTableHashCoefficientSignature * signature_hash;
90   }
91 
92   return mixed_hash % ImTable::kSize;
93 }
94 
GetImtIndex(ArtMethod * method)95 inline uint32_t ImTable::GetImtIndex(ArtMethod* method) {
96   DCHECK(!method->IsCopied());
97   DCHECK(!method->IsProxyMethod());
98   if (!method->IsAbstract()) {
99     // For default methods, where we cannot store the imt_index, we use the
100     // method_index instead. We mask it with the closest power of two to
101     // simplify the interpreter.
102     return method->GetMethodIndex() & (ImTable::kSizeTruncToPowerOfTwo - 1);
103   }
104   return GetImtIndexForAbstractMethod(*method->GetDexFile(), method->GetDexMethodIndex());
105 }
106 
107 }  // namespace art
108 
109 #endif  // ART_RUNTIME_IMTABLE_INL_H_
110 
111