1 | // Copyright (c) 2018, 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/kernel_fingerprints.h" |
6 | #include "vm/compiler/frontend/kernel_translation_helper.h" |
7 | |
8 | #define H (translation_helper_) |
9 | #define I Isolate::Current() |
10 | |
11 | namespace dart { |
12 | namespace kernel { |
13 | |
14 | class KernelFingerprintHelper : public KernelReaderHelper { |
15 | public: |
16 | KernelFingerprintHelper(Zone* zone, |
17 | TranslationHelper* translation_helper, |
18 | const Script& script, |
19 | const ExternalTypedData& data, |
20 | intptr_t data_program_offset) |
21 | : KernelReaderHelper(zone, |
22 | translation_helper, |
23 | script, |
24 | data, |
25 | data_program_offset), |
26 | hash_(0) {} |
27 | |
28 | virtual ~KernelFingerprintHelper() {} |
29 | uint32_t CalculateFieldFingerprint(); |
30 | uint32_t CalculateFunctionFingerprint(); |
31 | |
32 | static uint32_t CalculateHash(uint32_t current, uint32_t val) { |
33 | return current * 31 + val; |
34 | } |
35 | |
36 | private: |
37 | void BuildHash(uint32_t val); |
38 | void CalculateConstructorFingerprint(); |
39 | void CalculateArgumentsFingerprint(); |
40 | void CalculateVariableDeclarationFingerprint(); |
41 | void CalculateStatementListFingerprint(); |
42 | void CalculateListOfExpressionsFingerprint(); |
43 | void CalculateListOfDartTypesFingerprint(); |
44 | void CalculateListOfVariableDeclarationsFingerprint(); |
45 | void CalculateStringReferenceFingerprint(); |
46 | void CalculateListOfStringsFingerprint(); |
47 | void CalculateTypeParameterFingerprint(); |
48 | void CalculateTypeParametersListFingerprint(); |
49 | void CalculateCanonicalNameFingerprint(); |
50 | void CalculateInterfaceMemberNameFingerprint(); |
51 | void CalculateInitializerFingerprint(); |
52 | void CalculateDartTypeFingerprint(); |
53 | void CalculateOptionalDartTypeFingerprint(); |
54 | void CalculateInterfaceTypeFingerprint(bool simple); |
55 | void CalculateFunctionTypeFingerprint(bool simple); |
56 | void CalculateGetterNameFingerprint(); |
57 | void CalculateSetterNameFingerprint(); |
58 | void CalculateMethodNameFingerprint(); |
59 | void CalculateExpressionFingerprint(); |
60 | void CalculateStatementFingerprint(); |
61 | void CalculateFunctionNodeFingerprint(); |
62 | |
63 | uint32_t hash_; |
64 | |
65 | DISALLOW_COPY_AND_ASSIGN(KernelFingerprintHelper); |
66 | }; |
67 | |
68 | void KernelFingerprintHelper::BuildHash(uint32_t val) { |
69 | hash_ = CalculateHash(hash_, val); |
70 | } |
71 | |
72 | void KernelFingerprintHelper::CalculateConstructorFingerprint() { |
73 | ConstructorHelper helper(this); |
74 | |
75 | helper.ReadUntilExcluding(ConstructorHelper::kAnnotations); |
76 | CalculateListOfExpressionsFingerprint(); |
77 | CalculateFunctionNodeFingerprint(); |
78 | intptr_t len = ReadListLength(); |
79 | for (intptr_t i = 0; i < len; ++i) { |
80 | CalculateInitializerFingerprint(); |
81 | } |
82 | helper.SetJustRead(ConstructorHelper::kInitializers); |
83 | BuildHash(helper.flags_); |
84 | } |
85 | |
86 | void KernelFingerprintHelper::CalculateArgumentsFingerprint() { |
87 | BuildHash(ReadUInt()); // read argument count. |
88 | |
89 | CalculateListOfDartTypesFingerprint(); // read list of types. |
90 | CalculateListOfExpressionsFingerprint(); // read positionals. |
91 | |
92 | // List of named. |
93 | intptr_t list_length = ReadListLength(); // read list length. |
94 | for (intptr_t i = 0; i < list_length; ++i) { |
95 | CalculateStringReferenceFingerprint(); // read ith name index. |
96 | CalculateExpressionFingerprint(); // read ith expression. |
97 | } |
98 | } |
99 | |
100 | void KernelFingerprintHelper::CalculateVariableDeclarationFingerprint() { |
101 | VariableDeclarationHelper helper(this); |
102 | |
103 | helper.ReadUntilExcluding(VariableDeclarationHelper::kAnnotations); |
104 | CalculateListOfExpressionsFingerprint(); |
105 | helper.SetJustRead(VariableDeclarationHelper::kAnnotations); |
106 | |
107 | helper.ReadUntilExcluding(VariableDeclarationHelper::kType); |
108 | // We don't need to use the helper after this point. |
109 | CalculateDartTypeFingerprint(); |
110 | if (ReadTag() == kSomething) { |
111 | CalculateExpressionFingerprint(); |
112 | } |
113 | |
114 | BuildHash(helper.flags_); |
115 | } |
116 | |
117 | void KernelFingerprintHelper::CalculateStatementListFingerprint() { |
118 | intptr_t list_length = ReadListLength(); // read list length. |
119 | for (intptr_t i = 0; i < list_length; ++i) { |
120 | CalculateStatementFingerprint(); // read ith expression. |
121 | } |
122 | } |
123 | |
124 | void KernelFingerprintHelper::CalculateListOfExpressionsFingerprint() { |
125 | intptr_t list_length = ReadListLength(); // read list length. |
126 | for (intptr_t i = 0; i < list_length; ++i) { |
127 | CalculateExpressionFingerprint(); // read ith expression. |
128 | } |
129 | } |
130 | |
131 | void KernelFingerprintHelper::CalculateListOfDartTypesFingerprint() { |
132 | intptr_t list_length = ReadListLength(); // read list length. |
133 | for (intptr_t i = 0; i < list_length; ++i) { |
134 | CalculateDartTypeFingerprint(); // read ith type. |
135 | } |
136 | } |
137 | |
138 | void KernelFingerprintHelper::CalculateStringReferenceFingerprint() { |
139 | BuildHash( |
140 | H.DartString(ReadStringReference()).Hash()); // read ith string index. |
141 | } |
142 | |
143 | void KernelFingerprintHelper::CalculateListOfStringsFingerprint() { |
144 | intptr_t list_length = ReadListLength(); // read list length. |
145 | for (intptr_t i = 0; i < list_length; ++i) { |
146 | CalculateStringReferenceFingerprint(); // read ith string index. |
147 | } |
148 | } |
149 | |
150 | void KernelFingerprintHelper::CalculateListOfVariableDeclarationsFingerprint() { |
151 | intptr_t list_length = ReadListLength(); // read list length. |
152 | for (intptr_t i = 0; i < list_length; ++i) { |
153 | // read ith variable declaration. |
154 | CalculateVariableDeclarationFingerprint(); |
155 | } |
156 | } |
157 | |
158 | void KernelFingerprintHelper::CalculateTypeParameterFingerprint() { |
159 | TypeParameterHelper helper(this); |
160 | |
161 | helper.ReadUntilExcluding(TypeParameterHelper::kAnnotations); |
162 | CalculateListOfExpressionsFingerprint(); |
163 | helper.SetJustRead(TypeParameterHelper::kAnnotations); |
164 | |
165 | helper.ReadUntilExcluding(TypeParameterHelper::kVariance); |
166 | Variance variance = ReadVariance(); |
167 | BuildHash(variance); |
168 | helper.SetJustRead(TypeParameterHelper::kVariance); |
169 | |
170 | helper.ReadUntilExcluding(TypeParameterHelper::kBound); |
171 | // The helper isn't needed after this point. |
172 | CalculateDartTypeFingerprint(); |
173 | if (ReadTag() == kSomething) { |
174 | CalculateDartTypeFingerprint(); |
175 | } |
176 | BuildHash(helper.flags_); |
177 | } |
178 | |
179 | void KernelFingerprintHelper::CalculateTypeParametersListFingerprint() { |
180 | intptr_t list_length = ReadListLength(); // read list length. |
181 | for (intptr_t i = 0; i < list_length; ++i) { |
182 | CalculateTypeParameterFingerprint(); |
183 | } |
184 | } |
185 | |
186 | void KernelFingerprintHelper::CalculateCanonicalNameFingerprint() { |
187 | const StringIndex i = H.CanonicalNameString(ReadCanonicalNameReference()); |
188 | BuildHash(H.DartString(i).Hash()); |
189 | } |
190 | |
191 | void KernelFingerprintHelper::CalculateInterfaceMemberNameFingerprint() { |
192 | CalculateCanonicalNameFingerprint(); |
193 | ReadCanonicalNameReference(); // read target_origin_reference |
194 | } |
195 | |
196 | void KernelFingerprintHelper::CalculateInitializerFingerprint() { |
197 | Tag tag = ReadTag(); |
198 | ReadByte(); // read isSynthetic flag. |
199 | switch (tag) { |
200 | case kInvalidInitializer: |
201 | return; |
202 | case kFieldInitializer: |
203 | BuildHash(H.DartFieldName(ReadCanonicalNameReference()).Hash()); |
204 | CalculateExpressionFingerprint(); // read value. |
205 | return; |
206 | case kSuperInitializer: |
207 | ReadPosition(); // read position. |
208 | CalculateCanonicalNameFingerprint(); // read target_reference |
209 | CalculateArgumentsFingerprint(); // read arguments. |
210 | return; |
211 | case kRedirectingInitializer: |
212 | ReadPosition(); // read position. |
213 | CalculateCanonicalNameFingerprint(); // read target_reference |
214 | CalculateArgumentsFingerprint(); // read arguments. |
215 | return; |
216 | case kLocalInitializer: |
217 | CalculateVariableDeclarationFingerprint(); // read variable. |
218 | return; |
219 | case kAssertInitializer: |
220 | CalculateStatementFingerprint(); |
221 | return; |
222 | default: |
223 | ReportUnexpectedTag("initializer" , tag); |
224 | UNREACHABLE(); |
225 | } |
226 | } |
227 | |
228 | void KernelFingerprintHelper::CalculateDartTypeFingerprint() { |
229 | Tag tag = ReadTag(); |
230 | BuildHash(tag); |
231 | switch (tag) { |
232 | case kInvalidType: |
233 | case kDynamicType: |
234 | case kVoidType: |
235 | case kBottomType: |
236 | // those contain nothing. |
237 | break; |
238 | case kNeverType: |
239 | BuildHash(static_cast<uint32_t>(ReadNullability())); |
240 | break; |
241 | case kInterfaceType: |
242 | CalculateInterfaceTypeFingerprint(false); |
243 | break; |
244 | case kSimpleInterfaceType: |
245 | CalculateInterfaceTypeFingerprint(true); |
246 | break; |
247 | case kFunctionType: |
248 | CalculateFunctionTypeFingerprint(false); |
249 | break; |
250 | case kSimpleFunctionType: |
251 | CalculateFunctionTypeFingerprint(true); |
252 | break; |
253 | case kTypeParameterType: { |
254 | Nullability nullability = ReadNullability(); |
255 | BuildHash(static_cast<uint32_t>(nullability)); |
256 | ReadUInt(); // read index for parameter. |
257 | CalculateOptionalDartTypeFingerprint(); // read bound bound. |
258 | break; |
259 | } |
260 | default: |
261 | ReportUnexpectedTag("type" , tag); |
262 | UNREACHABLE(); |
263 | } |
264 | } |
265 | |
266 | void KernelFingerprintHelper::CalculateOptionalDartTypeFingerprint() { |
267 | Tag tag = ReadTag(); // read tag. |
268 | BuildHash(tag); |
269 | if (tag == kNothing) { |
270 | return; |
271 | } |
272 | ASSERT(tag == kSomething); |
273 | CalculateDartTypeFingerprint(); // read type. |
274 | } |
275 | |
276 | void KernelFingerprintHelper::CalculateInterfaceTypeFingerprint(bool simple) { |
277 | Nullability nullability = ReadNullability(); |
278 | BuildHash(static_cast<uint32_t>(nullability)); |
279 | NameIndex kernel_class = ReadCanonicalNameReference(); |
280 | ASSERT(H.IsClass(kernel_class)); |
281 | const String& class_name = H.DartClassName(kernel_class); |
282 | NameIndex kernel_library = H.CanonicalNameParent(kernel_class); |
283 | const String& library_name = |
284 | H.DartSymbolPlain(H.CanonicalNameString(kernel_library)); |
285 | BuildHash(class_name.Hash()); |
286 | BuildHash(library_name.Hash()); |
287 | if (!simple) { |
288 | CalculateListOfDartTypesFingerprint(); // read list of types. |
289 | } |
290 | } |
291 | |
292 | void KernelFingerprintHelper::CalculateFunctionTypeFingerprint(bool simple) { |
293 | Nullability nullability = ReadNullability(); |
294 | BuildHash(static_cast<uint32_t>(nullability)); |
295 | |
296 | if (!simple) { |
297 | CalculateTypeParametersListFingerprint(); // read type_parameters. |
298 | BuildHash(ReadUInt()); // read required parameter count. |
299 | BuildHash(ReadUInt()); // read total parameter count. |
300 | } |
301 | |
302 | CalculateListOfDartTypesFingerprint(); // read positional_parameters types. |
303 | |
304 | if (!simple) { |
305 | const intptr_t named_count = |
306 | ReadListLength(); // read named_parameters list length. |
307 | BuildHash(named_count); |
308 | for (intptr_t i = 0; i < named_count; ++i) { |
309 | // read string reference (i.e. named_parameters[i].name). |
310 | CalculateStringReferenceFingerprint(); |
311 | CalculateDartTypeFingerprint(); // read named_parameters[i].type. |
312 | BuildHash(ReadFlags()); // read flags. |
313 | } |
314 | } |
315 | |
316 | if (!simple) { |
317 | // TODO(bkonyi): include in hash. |
318 | SkipOptionalDartType(); // read typedef type. |
319 | } |
320 | |
321 | CalculateDartTypeFingerprint(); // read return type. |
322 | } |
323 | |
324 | void KernelFingerprintHelper::CalculateGetterNameFingerprint() { |
325 | const NameIndex name = ReadCanonicalNameReference(); |
326 | if (!H.IsRoot(name) && (H.IsGetter(name) || H.IsField(name))) { |
327 | BuildHash(H.DartGetterName(name).Hash()); |
328 | } |
329 | ReadCanonicalNameReference(); // read interface_target_origin_reference |
330 | } |
331 | |
332 | void KernelFingerprintHelper::CalculateSetterNameFingerprint() { |
333 | const NameIndex name = ReadCanonicalNameReference(); |
334 | if (!H.IsRoot(name)) { |
335 | BuildHash(H.DartSetterName(name).Hash()); |
336 | } |
337 | ReadCanonicalNameReference(); // read interface_target_origin_reference |
338 | } |
339 | |
340 | void KernelFingerprintHelper::CalculateMethodNameFingerprint() { |
341 | const NameIndex name = |
342 | ReadCanonicalNameReference(); // read interface_target_reference. |
343 | if (!H.IsRoot(name) && !H.IsField(name)) { |
344 | BuildHash(H.DartProcedureName(name).Hash()); |
345 | } |
346 | ReadCanonicalNameReference(); // read interface_target_origin_reference |
347 | } |
348 | |
349 | void KernelFingerprintHelper::CalculateExpressionFingerprint() { |
350 | uint8_t payload = 0; |
351 | Tag tag = ReadTag(&payload); |
352 | BuildHash(tag); |
353 | switch (tag) { |
354 | case kInvalidExpression: |
355 | ReadPosition(); |
356 | CalculateStringReferenceFingerprint(); |
357 | return; |
358 | case kVariableGet: |
359 | ReadPosition(); // read position. |
360 | ReadUInt(); // read kernel position. |
361 | ReadUInt(); // read relative variable index. |
362 | CalculateOptionalDartTypeFingerprint(); // read promoted type. |
363 | return; |
364 | case kSpecializedVariableGet: |
365 | ReadPosition(); // read position. |
366 | ReadUInt(); // read kernel position. |
367 | return; |
368 | case kVariableSet: |
369 | ReadPosition(); // read position. |
370 | ReadUInt(); // read kernel position. |
371 | ReadUInt(); // read relative variable index. |
372 | CalculateExpressionFingerprint(); // read expression. |
373 | return; |
374 | case kSpecializedVariableSet: |
375 | ReadPosition(); // read position. |
376 | ReadUInt(); // read kernel position. |
377 | CalculateExpressionFingerprint(); // read expression. |
378 | return; |
379 | case kPropertyGet: |
380 | ReadPosition(); // read position. |
381 | CalculateExpressionFingerprint(); // read receiver. |
382 | BuildHash(ReadNameAsGetterName().Hash()); // read name. |
383 | CalculateGetterNameFingerprint(); // read interface_target_reference. |
384 | return; |
385 | case kPropertySet: |
386 | ReadPosition(); // read position. |
387 | CalculateExpressionFingerprint(); // read receiver. |
388 | BuildHash(ReadNameAsSetterName().Hash()); // read name. |
389 | CalculateExpressionFingerprint(); // read value. |
390 | CalculateSetterNameFingerprint(); // read interface_target_reference. |
391 | return; |
392 | case kSuperPropertyGet: |
393 | ReadPosition(); // read position. |
394 | BuildHash(ReadNameAsGetterName().Hash()); // read name. |
395 | CalculateGetterNameFingerprint(); // read interface_target_reference. |
396 | return; |
397 | case kSuperPropertySet: |
398 | ReadPosition(); // read position. |
399 | BuildHash(ReadNameAsSetterName().Hash()); // read name. |
400 | CalculateExpressionFingerprint(); // read value. |
401 | CalculateSetterNameFingerprint(); // read interface_target_reference. |
402 | return; |
403 | case kDirectPropertyGet: |
404 | ReadPosition(); // read position. |
405 | CalculateExpressionFingerprint(); // read receiver. |
406 | CalculateInterfaceMemberNameFingerprint(); // read target_reference. |
407 | return; |
408 | case kDirectPropertySet: |
409 | ReadPosition(); // read position. |
410 | CalculateExpressionFingerprint(); // read receiver. |
411 | CalculateInterfaceMemberNameFingerprint(); // read target_reference. |
412 | CalculateExpressionFingerprint(); // read value· |
413 | return; |
414 | case kStaticGet: |
415 | ReadPosition(); // read position. |
416 | CalculateCanonicalNameFingerprint(); // read target_reference. |
417 | return; |
418 | case kStaticSet: |
419 | ReadPosition(); // read position. |
420 | CalculateCanonicalNameFingerprint(); // read target_reference. |
421 | CalculateExpressionFingerprint(); // read expression. |
422 | return; |
423 | case kMethodInvocation: |
424 | ReadPosition(); // read position. |
425 | CalculateExpressionFingerprint(); // read receiver. |
426 | BuildHash(ReadNameAsMethodName().Hash()); // read name. |
427 | CalculateArgumentsFingerprint(); // read arguments. |
428 | CalculateMethodNameFingerprint(); // read interface_target_reference. |
429 | return; |
430 | case kSuperMethodInvocation: |
431 | ReadPosition(); // read position. |
432 | BuildHash(ReadNameAsMethodName().Hash()); // read name. |
433 | CalculateArgumentsFingerprint(); // read arguments. |
434 | CalculateInterfaceMemberNameFingerprint(); // read target_reference. |
435 | return; |
436 | case kDirectMethodInvocation: |
437 | ReadPosition(); // read position. |
438 | CalculateExpressionFingerprint(); // read receiver. |
439 | CalculateInterfaceMemberNameFingerprint(); // read target_reference. |
440 | CalculateArgumentsFingerprint(); // read arguments. |
441 | return; |
442 | case kStaticInvocation: |
443 | ReadPosition(); // read position. |
444 | CalculateCanonicalNameFingerprint(); // read target_reference. |
445 | CalculateArgumentsFingerprint(); // read arguments. |
446 | return; |
447 | case kConstructorInvocation: |
448 | ReadPosition(); // read position. |
449 | CalculateCanonicalNameFingerprint(); // read target_reference. |
450 | CalculateArgumentsFingerprint(); // read arguments. |
451 | return; |
452 | case kNot: |
453 | CalculateExpressionFingerprint(); // read expression. |
454 | return; |
455 | case kNullCheck: |
456 | ReadPosition(); // read position. |
457 | CalculateExpressionFingerprint(); // read expression. |
458 | return; |
459 | case kLogicalExpression: |
460 | CalculateExpressionFingerprint(); // read left. |
461 | SkipBytes(1); // read operator. |
462 | CalculateExpressionFingerprint(); // read right. |
463 | return; |
464 | case kConditionalExpression: |
465 | CalculateExpressionFingerprint(); // read condition. |
466 | CalculateExpressionFingerprint(); // read then. |
467 | CalculateExpressionFingerprint(); // read otherwise. |
468 | CalculateOptionalDartTypeFingerprint(); // read unused static type. |
469 | return; |
470 | case kStringConcatenation: |
471 | ReadPosition(); // read position. |
472 | CalculateListOfExpressionsFingerprint(); // read list of expressions. |
473 | return; |
474 | case kIsExpression: |
475 | ReadPosition(); // read position. |
476 | if (translation_helper_.info().kernel_binary_version() >= 38) { |
477 | BuildHash(ReadFlags()); // read flags. |
478 | } |
479 | CalculateExpressionFingerprint(); // read operand. |
480 | CalculateDartTypeFingerprint(); // read type. |
481 | return; |
482 | case kAsExpression: |
483 | ReadPosition(); // read position. |
484 | BuildHash(ReadFlags()); // read flags. |
485 | CalculateExpressionFingerprint(); // read operand. |
486 | CalculateDartTypeFingerprint(); // read type. |
487 | return; |
488 | case kTypeLiteral: |
489 | CalculateDartTypeFingerprint(); // read type. |
490 | return; |
491 | case kThisExpression: |
492 | return; |
493 | case kRethrow: |
494 | ReadPosition(); // read position. |
495 | return; |
496 | case kThrow: |
497 | ReadPosition(); // read position. |
498 | CalculateExpressionFingerprint(); // read expression. |
499 | return; |
500 | case kListLiteral: |
501 | ReadPosition(); // read position. |
502 | CalculateDartTypeFingerprint(); // read type. |
503 | CalculateListOfExpressionsFingerprint(); // read list of expressions. |
504 | return; |
505 | case kSetLiteral: |
506 | // Set literals are currently desugared in the frontend and will not |
507 | // reach the VM. See http://dartbug.com/35124 for discussion. |
508 | UNREACHABLE(); |
509 | return; |
510 | case kMapLiteral: { |
511 | ReadPosition(); // read position. |
512 | CalculateDartTypeFingerprint(); // read type. |
513 | CalculateDartTypeFingerprint(); // read value type. |
514 | intptr_t list_length = ReadListLength(); // read list length. |
515 | for (intptr_t i = 0; i < list_length; ++i) { |
516 | CalculateExpressionFingerprint(); // read ith key. |
517 | CalculateExpressionFingerprint(); // read ith value. |
518 | } |
519 | return; |
520 | } |
521 | case kFunctionExpression: |
522 | ReadPosition(); // read position. |
523 | CalculateFunctionNodeFingerprint(); // read function node. |
524 | return; |
525 | case kLet: |
526 | CalculateVariableDeclarationFingerprint(); // read variable declaration. |
527 | CalculateExpressionFingerprint(); // read expression. |
528 | return; |
529 | case kBlockExpression: |
530 | CalculateStatementListFingerprint(); |
531 | CalculateExpressionFingerprint(); // read expression. |
532 | return; |
533 | case kInstantiation: |
534 | CalculateExpressionFingerprint(); // read expression. |
535 | CalculateListOfDartTypesFingerprint(); // read type arguments. |
536 | return; |
537 | case kBigIntLiteral: |
538 | CalculateStringReferenceFingerprint(); // read string reference. |
539 | return; |
540 | case kStringLiteral: |
541 | CalculateStringReferenceFingerprint(); // read string reference. |
542 | return; |
543 | case kSpecializedIntLiteral: |
544 | return; |
545 | case kNegativeIntLiteral: |
546 | BuildHash(ReadUInt()); // read value. |
547 | return; |
548 | case kPositiveIntLiteral: |
549 | BuildHash(ReadUInt()); // read value. |
550 | return; |
551 | case kDoubleLiteral: { |
552 | double value = ReadDouble(); // read value. |
553 | uint64_t data = bit_cast<uint64_t>(value); |
554 | BuildHash(static_cast<uint32_t>(data >> 32)); |
555 | BuildHash(static_cast<uint32_t>(data)); |
556 | return; |
557 | } |
558 | case kTrueLiteral: |
559 | return; |
560 | case kFalseLiteral: |
561 | return; |
562 | case kNullLiteral: |
563 | return; |
564 | case kConstantExpression: |
565 | ReadPosition(); |
566 | SkipDartType(); |
567 | SkipConstantReference(); |
568 | return; |
569 | case kLoadLibrary: |
570 | case kCheckLibraryIsLoaded: |
571 | ReadUInt(); // skip library index |
572 | return; |
573 | case kConstStaticInvocation: |
574 | case kConstConstructorInvocation: |
575 | case kConstListLiteral: |
576 | case kConstSetLiteral: |
577 | case kConstMapLiteral: |
578 | case kSymbolLiteral: |
579 | // Const invocations and const literals are removed by the |
580 | // constant evaluator. |
581 | case kListConcatenation: |
582 | case kSetConcatenation: |
583 | case kMapConcatenation: |
584 | case kInstanceCreation: |
585 | case kFileUriExpression: |
586 | // Collection concatenation, instance creation operations and |
587 | // in-expression URI changes are internal to the front end and |
588 | // removed by the constant evaluator. |
589 | default: |
590 | ReportUnexpectedTag("expression" , tag); |
591 | UNREACHABLE(); |
592 | } |
593 | } |
594 | |
595 | void KernelFingerprintHelper::CalculateStatementFingerprint() { |
596 | Tag tag = ReadTag(); // read tag. |
597 | BuildHash(tag); |
598 | switch (tag) { |
599 | case kExpressionStatement: |
600 | CalculateExpressionFingerprint(); // read expression. |
601 | return; |
602 | case kBlock: |
603 | CalculateStatementListFingerprint(); |
604 | return; |
605 | case kEmptyStatement: |
606 | return; |
607 | case kAssertBlock: |
608 | CalculateStatementListFingerprint(); |
609 | return; |
610 | case kAssertStatement: |
611 | CalculateExpressionFingerprint(); // Read condition. |
612 | ReadPosition(); // read condition start offset. |
613 | ReadPosition(); // read condition end offset. |
614 | if (ReadTag() == kSomething) { |
615 | CalculateExpressionFingerprint(); // read (rest of) message. |
616 | } |
617 | return; |
618 | case kLabeledStatement: |
619 | CalculateStatementFingerprint(); // read body. |
620 | return; |
621 | case kBreakStatement: |
622 | ReadPosition(); // read position. |
623 | ReadUInt(); // read target_index. |
624 | return; |
625 | case kWhileStatement: |
626 | ReadPosition(); // read position. |
627 | CalculateExpressionFingerprint(); // read condition. |
628 | CalculateStatementFingerprint(); // read body. |
629 | return; |
630 | case kDoStatement: |
631 | ReadPosition(); // read position. |
632 | CalculateStatementFingerprint(); // read body. |
633 | CalculateExpressionFingerprint(); // read condition. |
634 | return; |
635 | case kForStatement: { |
636 | ReadPosition(); // read position. |
637 | CalculateListOfVariableDeclarationsFingerprint(); // read variables. |
638 | Tag tag = ReadTag(); // Read first part of condition. |
639 | if (tag == kSomething) { |
640 | CalculateExpressionFingerprint(); // read rest of condition. |
641 | } |
642 | CalculateListOfExpressionsFingerprint(); // read updates. |
643 | CalculateStatementFingerprint(); // read body. |
644 | return; |
645 | } |
646 | case kForInStatement: |
647 | case kAsyncForInStatement: |
648 | ReadPosition(); // read position. |
649 | ReadPosition(); // read body position. |
650 | CalculateVariableDeclarationFingerprint(); // read variable. |
651 | CalculateExpressionFingerprint(); // read iterable. |
652 | CalculateStatementFingerprint(); // read body. |
653 | return; |
654 | case kSwitchStatement: { |
655 | ReadPosition(); // read position. |
656 | CalculateExpressionFingerprint(); // read condition. |
657 | int case_count = ReadListLength(); // read number of cases. |
658 | for (intptr_t i = 0; i < case_count; ++i) { |
659 | int expression_count = ReadListLength(); // read number of expressions. |
660 | for (intptr_t j = 0; j < expression_count; ++j) { |
661 | ReadPosition(); // read jth position. |
662 | CalculateExpressionFingerprint(); // read jth expression. |
663 | } |
664 | BuildHash(static_cast<uint32_t>(ReadBool())); // read is_default. |
665 | CalculateStatementFingerprint(); // read body. |
666 | } |
667 | return; |
668 | } |
669 | case kContinueSwitchStatement: |
670 | ReadPosition(); // read position. |
671 | ReadUInt(); // read target_index. |
672 | return; |
673 | case kIfStatement: |
674 | ReadPosition(); // read position. |
675 | CalculateExpressionFingerprint(); // read condition. |
676 | CalculateStatementFingerprint(); // read then. |
677 | CalculateStatementFingerprint(); // read otherwise. |
678 | return; |
679 | case kReturnStatement: { |
680 | ReadPosition(); // read position |
681 | Tag tag = ReadTag(); // read (first part of) expression. |
682 | BuildHash(tag); |
683 | if (tag == kSomething) { |
684 | CalculateExpressionFingerprint(); // read (rest of) expression. |
685 | } |
686 | return; |
687 | } |
688 | case kTryCatch: { |
689 | CalculateStatementFingerprint(); // read body. |
690 | BuildHash(ReadByte()); // read flags |
691 | intptr_t catch_count = ReadListLength(); // read number of catches. |
692 | for (intptr_t i = 0; i < catch_count; ++i) { |
693 | ReadPosition(); // read position. |
694 | CalculateDartTypeFingerprint(); // read guard. |
695 | tag = ReadTag(); // read first part of exception. |
696 | BuildHash(tag); |
697 | if (tag == kSomething) { |
698 | CalculateVariableDeclarationFingerprint(); // read exception. |
699 | } |
700 | tag = ReadTag(); // read first part of stack trace. |
701 | BuildHash(tag); |
702 | if (tag == kSomething) { |
703 | CalculateVariableDeclarationFingerprint(); // read stack trace. |
704 | } |
705 | CalculateStatementFingerprint(); // read body. |
706 | } |
707 | return; |
708 | } |
709 | case kTryFinally: |
710 | CalculateStatementFingerprint(); // read body. |
711 | CalculateStatementFingerprint(); // read finalizer. |
712 | return; |
713 | case kYieldStatement: { |
714 | ReadPosition(); // read position. |
715 | BuildHash(ReadByte()); // read flags. |
716 | CalculateExpressionFingerprint(); // read expression. |
717 | return; |
718 | } |
719 | case kVariableDeclaration: |
720 | CalculateVariableDeclarationFingerprint(); // read variable declaration. |
721 | return; |
722 | case kFunctionDeclaration: |
723 | ReadPosition(); // read position. |
724 | CalculateVariableDeclarationFingerprint(); // read variable. |
725 | CalculateFunctionNodeFingerprint(); // read function node. |
726 | return; |
727 | default: |
728 | ReportUnexpectedTag("statement" , tag); |
729 | UNREACHABLE(); |
730 | } |
731 | } |
732 | |
733 | uint32_t KernelFingerprintHelper::CalculateFieldFingerprint() { |
734 | hash_ = 0; |
735 | FieldHelper field_helper(this); |
736 | |
737 | field_helper.ReadUntilExcluding(FieldHelper::kName); |
738 | const String& name = ReadNameAsFieldName(); // read name. |
739 | field_helper.SetJustRead(FieldHelper::kName); |
740 | |
741 | field_helper.ReadUntilExcluding(FieldHelper::kType); |
742 | CalculateDartTypeFingerprint(); // read type. |
743 | field_helper.SetJustRead(FieldHelper::kType); |
744 | |
745 | if (ReadTag() == kSomething) { |
746 | if (PeekTag() == kFunctionExpression) { |
747 | AlternativeReadingScope alt(&reader_); |
748 | CalculateExpressionFingerprint(); |
749 | } |
750 | SkipExpression(); |
751 | } |
752 | |
753 | BuildHash(name.Hash()); |
754 | BuildHash(field_helper.flags_); |
755 | BuildHash(field_helper.annotation_count_); |
756 | return hash_; |
757 | } |
758 | |
759 | void KernelFingerprintHelper::CalculateFunctionNodeFingerprint() { |
760 | FunctionNodeHelper function_node_helper(this); |
761 | |
762 | function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters); |
763 | CalculateTypeParametersListFingerprint(); |
764 | function_node_helper.SetJustRead(FunctionNodeHelper::kTypeParameters); |
765 | |
766 | function_node_helper.ReadUntilExcluding( |
767 | FunctionNodeHelper::kPositionalParameters); |
768 | CalculateListOfVariableDeclarationsFingerprint(); // read positionals |
769 | CalculateListOfVariableDeclarationsFingerprint(); // read named |
770 | CalculateDartTypeFingerprint(); // read return type. |
771 | |
772 | if (ReadTag() == kSomething) { |
773 | CalculateStatementFingerprint(); // Read body. |
774 | } |
775 | BuildHash(function_node_helper.total_parameter_count_); |
776 | BuildHash(function_node_helper.required_parameter_count_); |
777 | } |
778 | |
779 | uint32_t KernelFingerprintHelper::CalculateFunctionFingerprint() { |
780 | hash_ = 0; |
781 | Tag tag = PeekTag(); |
782 | if (tag == kField) { |
783 | return CalculateFieldFingerprint(); |
784 | } else if (tag == kConstructor) { |
785 | CalculateConstructorFingerprint(); |
786 | return hash_; |
787 | } |
788 | ProcedureHelper procedure_helper(this); |
789 | procedure_helper.ReadUntilExcluding(ProcedureHelper::kName); |
790 | const String& name = ReadNameAsMethodName(); // Read name. |
791 | procedure_helper.SetJustRead(ProcedureHelper::kName); |
792 | |
793 | procedure_helper.ReadUntilExcluding(ProcedureHelper::kFunction); |
794 | if (ReadTag() == kSomething) { |
795 | CalculateFunctionNodeFingerprint(); |
796 | } |
797 | |
798 | BuildHash(procedure_helper.kind_); |
799 | BuildHash(procedure_helper.flags_); |
800 | BuildHash(procedure_helper.annotation_count_); |
801 | BuildHash(name.Hash()); |
802 | return hash_; |
803 | } |
804 | |
805 | uint32_t KernelSourceFingerprintHelper::CalculateClassFingerprint( |
806 | const Class& klass) { |
807 | Zone* zone = Thread::Current()->zone(); |
808 | |
809 | // Handle typedefs. |
810 | if (klass.IsTypedefClass()) { |
811 | const Function& func = Function::Handle(zone, klass.signature_function()); |
812 | return CalculateFunctionFingerprint(func); |
813 | } |
814 | |
815 | String& name = String::Handle(zone, klass.Name()); |
816 | const Array& fields = Array::Handle(zone, klass.fields()); |
817 | const Array& functions = Array::Handle(zone, klass.functions()); |
818 | const Array& interfaces = Array::Handle(zone, klass.interfaces()); |
819 | AbstractType& type = AbstractType::Handle(zone); |
820 | |
821 | uint32_t hash = 0; |
822 | hash = KernelFingerprintHelper::CalculateHash(hash, name.Hash()); |
823 | |
824 | type = klass.super_type(); |
825 | if (!type.IsNull()) { |
826 | name = type.Name(); |
827 | hash = KernelFingerprintHelper::CalculateHash(hash, name.Hash()); |
828 | } |
829 | |
830 | Field& field = Field::Handle(zone); |
831 | // Calculate fingerprint for the class fields. |
832 | for (intptr_t i = 0; i < fields.Length(); ++i) { |
833 | field ^= fields.At(i); |
834 | uint32_t fingerprint = CalculateFieldFingerprint(field); |
835 | hash = KernelFingerprintHelper::CalculateHash(hash, fingerprint); |
836 | } |
837 | |
838 | // Calculate fingerprint for the class functions. |
839 | Function& func = Function::Handle(zone); |
840 | for (intptr_t i = 0; i < functions.Length(); ++i) { |
841 | func ^= functions.At(i); |
842 | uint32_t fingerprint = CalculateFunctionFingerprint(func); |
843 | hash = KernelFingerprintHelper::CalculateHash(hash, fingerprint); |
844 | } |
845 | |
846 | // Calculate fingerprint for the interfaces. |
847 | for (intptr_t i = 0; i < interfaces.Length(); ++i) { |
848 | type ^= interfaces.At(i); |
849 | name = type.Name(); |
850 | hash = KernelFingerprintHelper::CalculateHash(hash, name.Hash()); |
851 | } |
852 | |
853 | return hash; |
854 | } |
855 | |
856 | uint32_t KernelSourceFingerprintHelper::CalculateFieldFingerprint( |
857 | const Field& field) { |
858 | Thread* thread = Thread::Current(); |
859 | Zone* zone = thread->zone(); |
860 | const Script& script = Script::Handle(zone, field.Script()); |
861 | |
862 | TranslationHelper translation_helper(thread); |
863 | translation_helper.InitFromScript(script); |
864 | |
865 | KernelFingerprintHelper helper( |
866 | zone, &translation_helper, script, |
867 | ExternalTypedData::Handle(zone, field.KernelData()), |
868 | field.KernelDataProgramOffset()); |
869 | helper.SetOffset(field.kernel_offset()); |
870 | return helper.CalculateFieldFingerprint(); |
871 | } |
872 | |
873 | uint32_t KernelSourceFingerprintHelper::CalculateFunctionFingerprint( |
874 | const Function& func) { |
875 | Thread* thread = Thread::Current(); |
876 | Zone* zone = thread->zone(); |
877 | const Script& script = Script::Handle(zone, func.script()); |
878 | |
879 | TranslationHelper translation_helper(thread); |
880 | translation_helper.InitFromScript(script); |
881 | |
882 | KernelFingerprintHelper helper( |
883 | zone, &translation_helper, script, |
884 | ExternalTypedData::Handle(zone, func.KernelData()), |
885 | func.KernelDataProgramOffset()); |
886 | helper.SetOffset(func.kernel_offset()); |
887 | return helper.CalculateFunctionFingerprint(); |
888 | } |
889 | |
890 | } // namespace kernel |
891 | } // namespace dart |
892 | |