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
11namespace dart {
12namespace kernel {
13
14class 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
68void KernelFingerprintHelper::BuildHash(uint32_t val) {
69 hash_ = CalculateHash(hash_, val);
70}
71
72void 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
86void 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
100void 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
117void 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
124void 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
131void 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
138void KernelFingerprintHelper::CalculateStringReferenceFingerprint() {
139 BuildHash(
140 H.DartString(ReadStringReference()).Hash()); // read ith string index.
141}
142
143void 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
150void 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
158void 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
179void 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
186void KernelFingerprintHelper::CalculateCanonicalNameFingerprint() {
187 const StringIndex i = H.CanonicalNameString(ReadCanonicalNameReference());
188 BuildHash(H.DartString(i).Hash());
189}
190
191void KernelFingerprintHelper::CalculateInterfaceMemberNameFingerprint() {
192 CalculateCanonicalNameFingerprint();
193 ReadCanonicalNameReference(); // read target_origin_reference
194}
195
196void 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
228void 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
266void 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
276void 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
292void 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
324void 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
332void 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
340void 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
349void 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
595void 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
733uint32_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
759void 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
779uint32_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
805uint32_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
856uint32_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
873uint32_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