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