1 | // Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file |
2 | // for details. All rights reserved. Use of this source code is governed by a |
3 | // BSD-style license that can be found in the LICENSE file. |
4 | |
5 | #include "vm/compiler/frontend/bytecode_fingerprints.h" |
6 | |
7 | #include "vm/compiler/frontend/bytecode_reader.h" |
8 | #include "vm/constants_kbc.h" |
9 | #include "vm/hash.h" |
10 | |
11 | namespace dart { |
12 | namespace kernel { |
13 | |
14 | static uint32_t CombineObject(uint32_t hash, const Object& obj) { |
15 | if (obj.IsAbstractType()) { |
16 | return CombineHashes(hash, AbstractType::Cast(obj).Hash()); |
17 | } else if (obj.IsClass()) { |
18 | return CombineHashes(hash, Class::Cast(obj).id()); |
19 | } else if (obj.IsFunction()) { |
20 | return CombineHashes( |
21 | hash, AbstractType::Handle(Function::Cast(obj).result_type()).Hash()); |
22 | } else if (obj.IsField()) { |
23 | return CombineHashes(hash, |
24 | AbstractType::Handle(Field::Cast(obj).type()).Hash()); |
25 | } else { |
26 | return CombineHashes(hash, static_cast<uint32_t>(obj.GetClassId())); |
27 | } |
28 | } |
29 | |
30 | typedef uint32_t (*Fp)(uint32_t fp, |
31 | const KBCInstr* instr, |
32 | const ObjectPool& pool, |
33 | int32_t value); |
34 | |
35 | static uint32_t Fp___(uint32_t fp, |
36 | const KBCInstr* instr, |
37 | const ObjectPool& pool, |
38 | int32_t value) { |
39 | return fp; |
40 | } |
41 | |
42 | static uint32_t Fptgt(uint32_t fp, |
43 | const KBCInstr* instr, |
44 | const ObjectPool& pool, |
45 | int32_t value) { |
46 | return CombineHashes(fp, value); |
47 | } |
48 | |
49 | static uint32_t Fplit(uint32_t fp, |
50 | const KBCInstr* instr, |
51 | const ObjectPool& pool, |
52 | int32_t value) { |
53 | return CombineObject(fp, Object::Handle(pool.ObjectAt(value))); |
54 | } |
55 | |
56 | static uint32_t Fpreg(uint32_t fp, |
57 | const KBCInstr* instr, |
58 | const ObjectPool& pool, |
59 | int32_t value) { |
60 | return CombineHashes(fp, value); |
61 | } |
62 | |
63 | static uint32_t Fpxeg(uint32_t fp, |
64 | const KBCInstr* instr, |
65 | const ObjectPool& pool, |
66 | int32_t value) { |
67 | return CombineHashes(fp, value); |
68 | } |
69 | |
70 | static uint32_t Fpnum(uint32_t fp, |
71 | const KBCInstr* instr, |
72 | const ObjectPool& pool, |
73 | int32_t value) { |
74 | return CombineHashes(fp, value); |
75 | } |
76 | |
77 | static uint32_t Fingerprint0(uint32_t fp, |
78 | const KBCInstr* instr, |
79 | const ObjectPool& pool, |
80 | Fp op1, |
81 | Fp op2, |
82 | Fp op3) { |
83 | return fp; |
84 | } |
85 | |
86 | static uint32_t FingerprintA(uint32_t fp, |
87 | const KBCInstr* instr, |
88 | const ObjectPool& pool, |
89 | Fp op1, |
90 | Fp op2, |
91 | Fp op3) { |
92 | fp = op1(fp, instr, pool, KernelBytecode::DecodeA(instr)); |
93 | return fp; |
94 | } |
95 | |
96 | static uint32_t FingerprintD(uint32_t fp, |
97 | const KBCInstr* instr, |
98 | const ObjectPool& pool, |
99 | Fp op1, |
100 | Fp op2, |
101 | Fp op3) { |
102 | fp = op1(fp, instr, pool, KernelBytecode::DecodeD(instr)); |
103 | return fp; |
104 | } |
105 | |
106 | static uint32_t FingerprintX(uint32_t fp, |
107 | const KBCInstr* instr, |
108 | const ObjectPool& pool, |
109 | Fp op1, |
110 | Fp op2, |
111 | Fp op3) { |
112 | fp = op1(fp, instr, pool, KernelBytecode::DecodeX(instr)); |
113 | return fp; |
114 | } |
115 | |
116 | static uint32_t FingerprintT(uint32_t fp, |
117 | const KBCInstr* instr, |
118 | const ObjectPool& pool, |
119 | Fp op1, |
120 | Fp op2, |
121 | Fp op3) { |
122 | fp = op1(fp, instr, pool, KernelBytecode::DecodeT(instr)); |
123 | return fp; |
124 | } |
125 | |
126 | static uint32_t FingerprintA_E(uint32_t fp, |
127 | const KBCInstr* instr, |
128 | const ObjectPool& pool, |
129 | Fp op1, |
130 | Fp op2, |
131 | Fp op3) { |
132 | fp = op1(fp, instr, pool, KernelBytecode::DecodeA(instr)); |
133 | fp = op2(fp, instr, pool, KernelBytecode::DecodeE(instr)); |
134 | return fp; |
135 | } |
136 | |
137 | static uint32_t FingerprintA_Y(uint32_t fp, |
138 | const KBCInstr* instr, |
139 | const ObjectPool& pool, |
140 | Fp op1, |
141 | Fp op2, |
142 | Fp op3) { |
143 | fp = op1(fp, instr, pool, KernelBytecode::DecodeA(instr)); |
144 | fp = op2(fp, instr, pool, KernelBytecode::DecodeY(instr)); |
145 | return fp; |
146 | } |
147 | |
148 | static uint32_t FingerprintD_F(uint32_t fp, |
149 | const KBCInstr* instr, |
150 | const ObjectPool& pool, |
151 | Fp op1, |
152 | Fp op2, |
153 | Fp op3) { |
154 | fp = op1(fp, instr, pool, KernelBytecode::DecodeD(instr)); |
155 | fp = op2(fp, instr, pool, KernelBytecode::DecodeF(instr)); |
156 | return fp; |
157 | } |
158 | |
159 | static uint32_t FingerprintA_B_C(uint32_t fp, |
160 | const KBCInstr* instr, |
161 | const ObjectPool& pool, |
162 | Fp op1, |
163 | Fp op2, |
164 | Fp op3) { |
165 | fp = op1(fp, instr, pool, KernelBytecode::DecodeA(instr)); |
166 | fp = op2(fp, instr, pool, KernelBytecode::DecodeB(instr)); |
167 | fp = op3(fp, instr, pool, KernelBytecode::DecodeC(instr)); |
168 | return fp; |
169 | } |
170 | |
171 | uint32_t BytecodeFingerprintHelper::CalculateFunctionFingerprint( |
172 | const Function& function) { |
173 | ASSERT(function.is_declared_in_bytecode()); |
174 | const intptr_t kHashBits = 30; |
175 | uint32_t fp = 0; |
176 | fp = CombineHashes(fp, String::Handle(function.UserVisibleName()).Hash()); |
177 | if (function.is_abstract()) { |
178 | return FinalizeHash(fp, kHashBits); |
179 | } |
180 | if (!function.HasBytecode()) { |
181 | kernel::BytecodeReader::ReadFunctionBytecode(Thread::Current(), function); |
182 | } |
183 | const Bytecode& code = Bytecode::Handle(function.bytecode()); |
184 | const ObjectPool& pool = ObjectPool::Handle(code.object_pool()); |
185 | const KBCInstr* const start = |
186 | reinterpret_cast<const KBCInstr*>(code.instructions()); |
187 | for (const KBCInstr* instr = start; (instr - start) < code.Size(); |
188 | instr = KernelBytecode::Next(instr)) { |
189 | const KernelBytecode::Opcode opcode = KernelBytecode::DecodeOpcode(instr); |
190 | fp = CombineHashes(fp, opcode); |
191 | switch (opcode) { |
192 | #define FINGERPRINT_BYTECODE(name, encoding, kind, op1, op2, op3) \ |
193 | case KernelBytecode::k##name: \ |
194 | fp = Fingerprint##encoding(fp, instr, pool, Fp##op1, Fp##op2, Fp##op3); \ |
195 | break; |
196 | KERNEL_BYTECODES_LIST(FINGERPRINT_BYTECODE) |
197 | #undef FINGERPRINT_BYTECODE |
198 | default: |
199 | UNREACHABLE(); |
200 | } |
201 | } |
202 | |
203 | return FinalizeHash(fp, kHashBits); |
204 | } |
205 | |
206 | } // namespace kernel |
207 | } // namespace dart |
208 | |