| 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 | |