| // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| #include "vm/compiler/frontend/kernel_fingerprints.h" |
| #include "vm/compiler/frontend/kernel_translation_helper.h" |
| |
| #define H (translation_helper_) |
| #define I Isolate::Current() |
| |
| namespace dart { |
| namespace kernel { |
| |
| class KernelFingerprintHelper : public KernelReaderHelper { |
| public: |
| KernelFingerprintHelper(Zone* zone, |
| TranslationHelper* translation_helper, |
| const Script& script, |
| const ExternalTypedData& data, |
| intptr_t data_program_offset) |
| : KernelReaderHelper(zone, |
| translation_helper, |
| script, |
| data, |
| data_program_offset), |
| hash_(0) {} |
| |
| virtual ~KernelFingerprintHelper() {} |
| uint32_t CalculateFieldFingerprint(); |
| uint32_t CalculateFunctionFingerprint(); |
| |
| static uint32_t CalculateHash(uint32_t current, uint32_t val) { |
| return current * 31 + val; |
| } |
| |
| private: |
| void BuildHash(uint32_t val); |
| void CalculateConstructorFingerprint(); |
| void CalculateArgumentsFingerprint(); |
| void CalculateVariableDeclarationFingerprint(); |
| void CalculateStatementListFingerprint(); |
| void CalculateListOfExpressionsFingerprint(); |
| void CalculateListOfDartTypesFingerprint(); |
| void CalculateListOfVariableDeclarationsFingerprint(); |
| void CalculateStringReferenceFingerprint(); |
| void CalculateListOfStringsFingerprint(); |
| void CalculateTypeParameterFingerprint(); |
| void CalculateTypeParametersListFingerprint(); |
| void CalculateCanonicalNameFingerprint(); |
| void CalculateInterfaceMemberNameFingerprint(); |
| void CalculateInitializerFingerprint(); |
| void CalculateDartTypeFingerprint(); |
| void CalculateOptionalDartTypeFingerprint(); |
| void CalculateInterfaceTypeFingerprint(bool simple); |
| void CalculateFunctionTypeFingerprint(bool simple); |
| void CalculateGetterNameFingerprint(); |
| void CalculateSetterNameFingerprint(); |
| void CalculateMethodNameFingerprint(); |
| void CalculateExpressionFingerprint(); |
| void CalculateStatementFingerprint(); |
| void CalculateFunctionNodeFingerprint(); |
| |
| uint32_t hash_; |
| |
| DISALLOW_COPY_AND_ASSIGN(KernelFingerprintHelper); |
| }; |
| |
| void KernelFingerprintHelper::BuildHash(uint32_t val) { |
| hash_ = CalculateHash(hash_, val); |
| } |
| |
| void KernelFingerprintHelper::CalculateConstructorFingerprint() { |
| ConstructorHelper helper(this); |
| |
| helper.ReadUntilExcluding(ConstructorHelper::kAnnotations); |
| CalculateListOfExpressionsFingerprint(); |
| CalculateFunctionNodeFingerprint(); |
| intptr_t len = ReadListLength(); |
| for (intptr_t i = 0; i < len; ++i) { |
| CalculateInitializerFingerprint(); |
| } |
| helper.SetJustRead(ConstructorHelper::kInitializers); |
| BuildHash(helper.flags_); |
| } |
| |
| void KernelFingerprintHelper::CalculateArgumentsFingerprint() { |
| BuildHash(ReadUInt()); // read argument count. |
| |
| CalculateListOfDartTypesFingerprint(); // read list of types. |
| CalculateListOfExpressionsFingerprint(); // read positionals. |
| |
| // List of named. |
| intptr_t list_length = ReadListLength(); // read list length. |
| for (intptr_t i = 0; i < list_length; ++i) { |
| CalculateStringReferenceFingerprint(); // read ith name index. |
| CalculateExpressionFingerprint(); // read ith expression. |
| } |
| } |
| |
| void KernelFingerprintHelper::CalculateVariableDeclarationFingerprint() { |
| VariableDeclarationHelper helper(this); |
| |
| helper.ReadUntilExcluding(VariableDeclarationHelper::kAnnotations); |
| CalculateListOfExpressionsFingerprint(); |
| helper.SetJustRead(VariableDeclarationHelper::kAnnotations); |
| |
| helper.ReadUntilExcluding(VariableDeclarationHelper::kType); |
| // We don't need to use the helper after this point. |
| CalculateDartTypeFingerprint(); |
| if (ReadTag() == kSomething) { |
| CalculateExpressionFingerprint(); |
| } |
| |
| BuildHash(helper.flags_); |
| } |
| |
| void KernelFingerprintHelper::CalculateStatementListFingerprint() { |
| intptr_t list_length = ReadListLength(); // read list length. |
| for (intptr_t i = 0; i < list_length; ++i) { |
| CalculateStatementFingerprint(); // read ith expression. |
| } |
| } |
| |
| void KernelFingerprintHelper::CalculateListOfExpressionsFingerprint() { |
| intptr_t list_length = ReadListLength(); // read list length. |
| for (intptr_t i = 0; i < list_length; ++i) { |
| CalculateExpressionFingerprint(); // read ith expression. |
| } |
| } |
| |
| void KernelFingerprintHelper::CalculateListOfDartTypesFingerprint() { |
| intptr_t list_length = ReadListLength(); // read list length. |
| for (intptr_t i = 0; i < list_length; ++i) { |
| CalculateDartTypeFingerprint(); // read ith type. |
| } |
| } |
| |
| void KernelFingerprintHelper::CalculateStringReferenceFingerprint() { |
| BuildHash( |
| H.DartString(ReadStringReference()).Hash()); // read ith string index. |
| } |
| |
| void KernelFingerprintHelper::CalculateListOfStringsFingerprint() { |
| intptr_t list_length = ReadListLength(); // read list length. |
| for (intptr_t i = 0; i < list_length; ++i) { |
| CalculateStringReferenceFingerprint(); // read ith string index. |
| } |
| } |
| |
| void KernelFingerprintHelper::CalculateListOfVariableDeclarationsFingerprint() { |
| intptr_t list_length = ReadListLength(); // read list length. |
| for (intptr_t i = 0; i < list_length; ++i) { |
| // read ith variable declaration. |
| CalculateVariableDeclarationFingerprint(); |
| } |
| } |
| |
| void KernelFingerprintHelper::CalculateTypeParameterFingerprint() { |
| TypeParameterHelper helper(this); |
| |
| helper.ReadUntilExcluding(TypeParameterHelper::kAnnotations); |
| CalculateListOfExpressionsFingerprint(); |
| helper.SetJustRead(TypeParameterHelper::kAnnotations); |
| |
| helper.ReadUntilExcluding(TypeParameterHelper::kVariance); |
| Variance variance = ReadVariance(); |
| BuildHash(variance); |
| helper.SetJustRead(TypeParameterHelper::kVariance); |
| |
| helper.ReadUntilExcluding(TypeParameterHelper::kBound); |
| // The helper isn't needed after this point. |
| CalculateDartTypeFingerprint(); |
| if (ReadTag() == kSomething) { |
| CalculateDartTypeFingerprint(); |
| } |
| BuildHash(helper.flags_); |
| } |
| |
| void KernelFingerprintHelper::CalculateTypeParametersListFingerprint() { |
| intptr_t list_length = ReadListLength(); // read list length. |
| for (intptr_t i = 0; i < list_length; ++i) { |
| CalculateTypeParameterFingerprint(); |
| } |
| } |
| |
| void KernelFingerprintHelper::CalculateCanonicalNameFingerprint() { |
| const StringIndex i = H.CanonicalNameString(ReadCanonicalNameReference()); |
| BuildHash(H.DartString(i).Hash()); |
| } |
| |
| void KernelFingerprintHelper::CalculateInterfaceMemberNameFingerprint() { |
| CalculateCanonicalNameFingerprint(); |
| ReadCanonicalNameReference(); // read target_origin_reference |
| } |
| |
| void KernelFingerprintHelper::CalculateInitializerFingerprint() { |
| Tag tag = ReadTag(); |
| ReadByte(); // read isSynthetic flag. |
| switch (tag) { |
| case kInvalidInitializer: |
| return; |
| case kFieldInitializer: |
| BuildHash(H.DartFieldName(ReadCanonicalNameReference()).Hash()); |
| CalculateExpressionFingerprint(); // read value. |
| return; |
| case kSuperInitializer: |
| ReadPosition(); // read position. |
| CalculateCanonicalNameFingerprint(); // read target_reference |
| CalculateArgumentsFingerprint(); // read arguments. |
| return; |
| case kRedirectingInitializer: |
| ReadPosition(); // read position. |
| CalculateCanonicalNameFingerprint(); // read target_reference |
| CalculateArgumentsFingerprint(); // read arguments. |
| return; |
| case kLocalInitializer: |
| CalculateVariableDeclarationFingerprint(); // read variable. |
| return; |
| case kAssertInitializer: |
| CalculateStatementFingerprint(); |
| return; |
| default: |
| ReportUnexpectedTag("initializer", tag); |
| UNREACHABLE(); |
| } |
| } |
| |
| void KernelFingerprintHelper::CalculateDartTypeFingerprint() { |
| Tag tag = ReadTag(); |
| BuildHash(tag); |
| switch (tag) { |
| case kInvalidType: |
| case kDynamicType: |
| case kVoidType: |
| case kBottomType: |
| // those contain nothing. |
| break; |
| case kNeverType: |
| BuildHash(static_cast<uint32_t>(ReadNullability())); |
| break; |
| case kInterfaceType: |
| CalculateInterfaceTypeFingerprint(false); |
| break; |
| case kSimpleInterfaceType: |
| CalculateInterfaceTypeFingerprint(true); |
| break; |
| case kFunctionType: |
| CalculateFunctionTypeFingerprint(false); |
| break; |
| case kSimpleFunctionType: |
| CalculateFunctionTypeFingerprint(true); |
| break; |
| case kTypeParameterType: { |
| Nullability nullability = ReadNullability(); |
| BuildHash(static_cast<uint32_t>(nullability)); |
| ReadUInt(); // read index for parameter. |
| CalculateOptionalDartTypeFingerprint(); // read bound bound. |
| break; |
| } |
| default: |
| ReportUnexpectedTag("type", tag); |
| UNREACHABLE(); |
| } |
| } |
| |
| void KernelFingerprintHelper::CalculateOptionalDartTypeFingerprint() { |
| Tag tag = ReadTag(); // read tag. |
| BuildHash(tag); |
| if (tag == kNothing) { |
| return; |
| } |
| ASSERT(tag == kSomething); |
| CalculateDartTypeFingerprint(); // read type. |
| } |
| |
| void KernelFingerprintHelper::CalculateInterfaceTypeFingerprint(bool simple) { |
| Nullability nullability = ReadNullability(); |
| BuildHash(static_cast<uint32_t>(nullability)); |
| NameIndex kernel_class = ReadCanonicalNameReference(); |
| ASSERT(H.IsClass(kernel_class)); |
| const String& class_name = H.DartClassName(kernel_class); |
| NameIndex kernel_library = H.CanonicalNameParent(kernel_class); |
| const String& library_name = |
| H.DartSymbolPlain(H.CanonicalNameString(kernel_library)); |
| BuildHash(class_name.Hash()); |
| BuildHash(library_name.Hash()); |
| if (!simple) { |
| CalculateListOfDartTypesFingerprint(); // read list of types. |
| } |
| } |
| |
| void KernelFingerprintHelper::CalculateFunctionTypeFingerprint(bool simple) { |
| Nullability nullability = ReadNullability(); |
| BuildHash(static_cast<uint32_t>(nullability)); |
| |
| if (!simple) { |
| CalculateTypeParametersListFingerprint(); // read type_parameters. |
| BuildHash(ReadUInt()); // read required parameter count. |
| BuildHash(ReadUInt()); // read total parameter count. |
| } |
| |
| CalculateListOfDartTypesFingerprint(); // read positional_parameters types. |
| |
| if (!simple) { |
| const intptr_t named_count = |
| ReadListLength(); // read named_parameters list length. |
| BuildHash(named_count); |
| for (intptr_t i = 0; i < named_count; ++i) { |
| // read string reference (i.e. named_parameters[i].name). |
| CalculateStringReferenceFingerprint(); |
| CalculateDartTypeFingerprint(); // read named_parameters[i].type. |
| BuildHash(ReadFlags()); // read flags. |
| } |
| } |
| |
| if (!simple) { |
| // TODO(bkonyi): include in hash. |
| SkipOptionalDartType(); // read typedef type. |
| } |
| |
| CalculateDartTypeFingerprint(); // read return type. |
| } |
| |
| void KernelFingerprintHelper::CalculateGetterNameFingerprint() { |
| const NameIndex name = ReadCanonicalNameReference(); |
| if (!H.IsRoot(name) && (H.IsGetter(name) || H.IsField(name))) { |
| BuildHash(H.DartGetterName(name).Hash()); |
| } |
| ReadCanonicalNameReference(); // read interface_target_origin_reference |
| } |
| |
| void KernelFingerprintHelper::CalculateSetterNameFingerprint() { |
| const NameIndex name = ReadCanonicalNameReference(); |
| if (!H.IsRoot(name)) { |
| BuildHash(H.DartSetterName(name).Hash()); |
| } |
| ReadCanonicalNameReference(); // read interface_target_origin_reference |
| } |
| |
| void KernelFingerprintHelper::CalculateMethodNameFingerprint() { |
| const NameIndex name = |
| ReadCanonicalNameReference(); // read interface_target_reference. |
| if (!H.IsRoot(name) && !H.IsField(name)) { |
| BuildHash(H.DartProcedureName(name).Hash()); |
| } |
| ReadCanonicalNameReference(); // read interface_target_origin_reference |
| } |
| |
| void KernelFingerprintHelper::CalculateExpressionFingerprint() { |
| uint8_t payload = 0; |
| Tag tag = ReadTag(&payload); |
| BuildHash(tag); |
| switch (tag) { |
| case kInvalidExpression: |
| ReadPosition(); |
| CalculateStringReferenceFingerprint(); |
| return; |
| case kVariableGet: |
| ReadPosition(); // read position. |
| ReadUInt(); // read kernel position. |
| ReadUInt(); // read relative variable index. |
| CalculateOptionalDartTypeFingerprint(); // read promoted type. |
| return; |
| case kSpecializedVariableGet: |
| ReadPosition(); // read position. |
| ReadUInt(); // read kernel position. |
| return; |
| case kVariableSet: |
| ReadPosition(); // read position. |
| ReadUInt(); // read kernel position. |
| ReadUInt(); // read relative variable index. |
| CalculateExpressionFingerprint(); // read expression. |
| return; |
| case kSpecializedVariableSet: |
| ReadPosition(); // read position. |
| ReadUInt(); // read kernel position. |
| CalculateExpressionFingerprint(); // read expression. |
| return; |
| case kPropertyGet: |
| ReadPosition(); // read position. |
| CalculateExpressionFingerprint(); // read receiver. |
| BuildHash(ReadNameAsGetterName().Hash()); // read name. |
| CalculateGetterNameFingerprint(); // read interface_target_reference. |
| return; |
| case kPropertySet: |
| ReadPosition(); // read position. |
| CalculateExpressionFingerprint(); // read receiver. |
| BuildHash(ReadNameAsSetterName().Hash()); // read name. |
| CalculateExpressionFingerprint(); // read value. |
| CalculateSetterNameFingerprint(); // read interface_target_reference. |
| return; |
| case kSuperPropertyGet: |
| ReadPosition(); // read position. |
| BuildHash(ReadNameAsGetterName().Hash()); // read name. |
| CalculateGetterNameFingerprint(); // read interface_target_reference. |
| return; |
| case kSuperPropertySet: |
| ReadPosition(); // read position. |
| BuildHash(ReadNameAsSetterName().Hash()); // read name. |
| CalculateExpressionFingerprint(); // read value. |
| CalculateSetterNameFingerprint(); // read interface_target_reference. |
| return; |
| case kDirectPropertyGet: |
| ReadPosition(); // read position. |
| CalculateExpressionFingerprint(); // read receiver. |
| CalculateInterfaceMemberNameFingerprint(); // read target_reference. |
| return; |
| case kDirectPropertySet: |
| ReadPosition(); // read position. |
| CalculateExpressionFingerprint(); // read receiver. |
| CalculateInterfaceMemberNameFingerprint(); // read target_reference. |
| CalculateExpressionFingerprint(); // read value· |
| return; |
| case kStaticGet: |
| ReadPosition(); // read position. |
| CalculateCanonicalNameFingerprint(); // read target_reference. |
| return; |
| case kStaticSet: |
| ReadPosition(); // read position. |
| CalculateCanonicalNameFingerprint(); // read target_reference. |
| CalculateExpressionFingerprint(); // read expression. |
| return; |
| case kMethodInvocation: |
| ReadPosition(); // read position. |
| CalculateExpressionFingerprint(); // read receiver. |
| BuildHash(ReadNameAsMethodName().Hash()); // read name. |
| CalculateArgumentsFingerprint(); // read arguments. |
| CalculateMethodNameFingerprint(); // read interface_target_reference. |
| return; |
| case kSuperMethodInvocation: |
| ReadPosition(); // read position. |
| BuildHash(ReadNameAsMethodName().Hash()); // read name. |
| CalculateArgumentsFingerprint(); // read arguments. |
| CalculateInterfaceMemberNameFingerprint(); // read target_reference. |
| return; |
| case kDirectMethodInvocation: |
| ReadPosition(); // read position. |
| CalculateExpressionFingerprint(); // read receiver. |
| CalculateInterfaceMemberNameFingerprint(); // read target_reference. |
| CalculateArgumentsFingerprint(); // read arguments. |
| return; |
| case kStaticInvocation: |
| ReadPosition(); // read position. |
| CalculateCanonicalNameFingerprint(); // read target_reference. |
| CalculateArgumentsFingerprint(); // read arguments. |
| return; |
| case kConstructorInvocation: |
| ReadPosition(); // read position. |
| CalculateCanonicalNameFingerprint(); // read target_reference. |
| CalculateArgumentsFingerprint(); // read arguments. |
| return; |
| case kNot: |
| CalculateExpressionFingerprint(); // read expression. |
| return; |
| case kNullCheck: |
| ReadPosition(); // read position. |
| CalculateExpressionFingerprint(); // read expression. |
| return; |
| case kLogicalExpression: |
| CalculateExpressionFingerprint(); // read left. |
| SkipBytes(1); // read operator. |
| CalculateExpressionFingerprint(); // read right. |
| return; |
| case kConditionalExpression: |
| CalculateExpressionFingerprint(); // read condition. |
| CalculateExpressionFingerprint(); // read then. |
| CalculateExpressionFingerprint(); // read otherwise. |
| CalculateOptionalDartTypeFingerprint(); // read unused static type. |
| return; |
| case kStringConcatenation: |
| ReadPosition(); // read position. |
| CalculateListOfExpressionsFingerprint(); // read list of expressions. |
| return; |
| case kIsExpression: |
| ReadPosition(); // read position. |
| if (translation_helper_.info().kernel_binary_version() >= 38) { |
| BuildHash(ReadFlags()); // read flags. |
| } |
| CalculateExpressionFingerprint(); // read operand. |
| CalculateDartTypeFingerprint(); // read type. |
| return; |
| case kAsExpression: |
| ReadPosition(); // read position. |
| BuildHash(ReadFlags()); // read flags. |
| CalculateExpressionFingerprint(); // read operand. |
| CalculateDartTypeFingerprint(); // read type. |
| return; |
| case kTypeLiteral: |
| CalculateDartTypeFingerprint(); // read type. |
| return; |
| case kThisExpression: |
| return; |
| case kRethrow: |
| ReadPosition(); // read position. |
| return; |
| case kThrow: |
| ReadPosition(); // read position. |
| CalculateExpressionFingerprint(); // read expression. |
| return; |
| case kListLiteral: |
| ReadPosition(); // read position. |
| CalculateDartTypeFingerprint(); // read type. |
| CalculateListOfExpressionsFingerprint(); // read list of expressions. |
| return; |
| case kSetLiteral: |
| // Set literals are currently desugared in the frontend and will not |
| // reach the VM. See http://dartbug.com/35124 for discussion. |
| UNREACHABLE(); |
| return; |
| case kMapLiteral: { |
| ReadPosition(); // read position. |
| CalculateDartTypeFingerprint(); // read type. |
| CalculateDartTypeFingerprint(); // read value type. |
| intptr_t list_length = ReadListLength(); // read list length. |
| for (intptr_t i = 0; i < list_length; ++i) { |
| CalculateExpressionFingerprint(); // read ith key. |
| CalculateExpressionFingerprint(); // read ith value. |
| } |
| return; |
| } |
| case kFunctionExpression: |
| ReadPosition(); // read position. |
| CalculateFunctionNodeFingerprint(); // read function node. |
| return; |
| case kLet: |
| CalculateVariableDeclarationFingerprint(); // read variable declaration. |
| CalculateExpressionFingerprint(); // read expression. |
| return; |
| case kBlockExpression: |
| CalculateStatementListFingerprint(); |
| CalculateExpressionFingerprint(); // read expression. |
| return; |
| case kInstantiation: |
| CalculateExpressionFingerprint(); // read expression. |
| CalculateListOfDartTypesFingerprint(); // read type arguments. |
| return; |
| case kBigIntLiteral: |
| CalculateStringReferenceFingerprint(); // read string reference. |
| return; |
| case kStringLiteral: |
| CalculateStringReferenceFingerprint(); // read string reference. |
| return; |
| case kSpecializedIntLiteral: |
| return; |
| case kNegativeIntLiteral: |
| BuildHash(ReadUInt()); // read value. |
| return; |
| case kPositiveIntLiteral: |
| BuildHash(ReadUInt()); // read value. |
| return; |
| case kDoubleLiteral: { |
| double value = ReadDouble(); // read value. |
| uint64_t data = bit_cast<uint64_t>(value); |
| BuildHash(static_cast<uint32_t>(data >> 32)); |
| BuildHash(static_cast<uint32_t>(data)); |
| return; |
| } |
| case kTrueLiteral: |
| return; |
| case kFalseLiteral: |
| return; |
| case kNullLiteral: |
| return; |
| case kConstantExpression: |
| ReadPosition(); |
| SkipDartType(); |
| SkipConstantReference(); |
| return; |
| case kLoadLibrary: |
| case kCheckLibraryIsLoaded: |
| ReadUInt(); // skip library index |
| return; |
| case kConstStaticInvocation: |
| case kConstConstructorInvocation: |
| case kConstListLiteral: |
| case kConstSetLiteral: |
| case kConstMapLiteral: |
| case kSymbolLiteral: |
| // Const invocations and const literals are removed by the |
| // constant evaluator. |
| case kListConcatenation: |
| case kSetConcatenation: |
| case kMapConcatenation: |
| case kInstanceCreation: |
| case kFileUriExpression: |
| // Collection concatenation, instance creation operations and |
| // in-expression URI changes are internal to the front end and |
| // removed by the constant evaluator. |
| default: |
| ReportUnexpectedTag("expression", tag); |
| UNREACHABLE(); |
| } |
| } |
| |
| void KernelFingerprintHelper::CalculateStatementFingerprint() { |
| Tag tag = ReadTag(); // read tag. |
| BuildHash(tag); |
| switch (tag) { |
| case kExpressionStatement: |
| CalculateExpressionFingerprint(); // read expression. |
| return; |
| case kBlock: |
| CalculateStatementListFingerprint(); |
| return; |
| case kEmptyStatement: |
| return; |
| case kAssertBlock: |
| CalculateStatementListFingerprint(); |
| return; |
| case kAssertStatement: |
| CalculateExpressionFingerprint(); // Read condition. |
| ReadPosition(); // read condition start offset. |
| ReadPosition(); // read condition end offset. |
| if (ReadTag() == kSomething) { |
| CalculateExpressionFingerprint(); // read (rest of) message. |
| } |
| return; |
| case kLabeledStatement: |
| CalculateStatementFingerprint(); // read body. |
| return; |
| case kBreakStatement: |
| ReadPosition(); // read position. |
| ReadUInt(); // read target_index. |
| return; |
| case kWhileStatement: |
| ReadPosition(); // read position. |
| CalculateExpressionFingerprint(); // read condition. |
| CalculateStatementFingerprint(); // read body. |
| return; |
| case kDoStatement: |
| ReadPosition(); // read position. |
| CalculateStatementFingerprint(); // read body. |
| CalculateExpressionFingerprint(); // read condition. |
| return; |
| case kForStatement: { |
| ReadPosition(); // read position. |
| CalculateListOfVariableDeclarationsFingerprint(); // read variables. |
| Tag tag = ReadTag(); // Read first part of condition. |
| if (tag == kSomething) { |
| CalculateExpressionFingerprint(); // read rest of condition. |
| } |
| CalculateListOfExpressionsFingerprint(); // read updates. |
| CalculateStatementFingerprint(); // read body. |
| return; |
| } |
| case kForInStatement: |
| case kAsyncForInStatement: |
| ReadPosition(); // read position. |
| ReadPosition(); // read body position. |
| CalculateVariableDeclarationFingerprint(); // read variable. |
| CalculateExpressionFingerprint(); // read iterable. |
| CalculateStatementFingerprint(); // read body. |
| return; |
| case kSwitchStatement: { |
| ReadPosition(); // read position. |
| CalculateExpressionFingerprint(); // read condition. |
| int case_count = ReadListLength(); // read number of cases. |
| for (intptr_t i = 0; i < case_count; ++i) { |
| int expression_count = ReadListLength(); // read number of expressions. |
| for (intptr_t j = 0; j < expression_count; ++j) { |
| ReadPosition(); // read jth position. |
| CalculateExpressionFingerprint(); // read jth expression. |
| } |
| BuildHash(static_cast<uint32_t>(ReadBool())); // read is_default. |
| CalculateStatementFingerprint(); // read body. |
| } |
| return; |
| } |
| case kContinueSwitchStatement: |
| ReadPosition(); // read position. |
| ReadUInt(); // read target_index. |
| return; |
| case kIfStatement: |
| ReadPosition(); // read position. |
| CalculateExpressionFingerprint(); // read condition. |
| CalculateStatementFingerprint(); // read then. |
| CalculateStatementFingerprint(); // read otherwise. |
| return; |
| case kReturnStatement: { |
| ReadPosition(); // read position |
| Tag tag = ReadTag(); // read (first part of) expression. |
| BuildHash(tag); |
| if (tag == kSomething) { |
| CalculateExpressionFingerprint(); // read (rest of) expression. |
| } |
| return; |
| } |
| case kTryCatch: { |
| CalculateStatementFingerprint(); // read body. |
| BuildHash(ReadByte()); // read flags |
| intptr_t catch_count = ReadListLength(); // read number of catches. |
| for (intptr_t i = 0; i < catch_count; ++i) { |
| ReadPosition(); // read position. |
| CalculateDartTypeFingerprint(); // read guard. |
| tag = ReadTag(); // read first part of exception. |
| BuildHash(tag); |
| if (tag == kSomething) { |
| CalculateVariableDeclarationFingerprint(); // read exception. |
| } |
| tag = ReadTag(); // read first part of stack trace. |
| BuildHash(tag); |
| if (tag == kSomething) { |
| CalculateVariableDeclarationFingerprint(); // read stack trace. |
| } |
| CalculateStatementFingerprint(); // read body. |
| } |
| return; |
| } |
| case kTryFinally: |
| CalculateStatementFingerprint(); // read body. |
| CalculateStatementFingerprint(); // read finalizer. |
| return; |
| case kYieldStatement: { |
| ReadPosition(); // read position. |
| BuildHash(ReadByte()); // read flags. |
| CalculateExpressionFingerprint(); // read expression. |
| return; |
| } |
| case kVariableDeclaration: |
| CalculateVariableDeclarationFingerprint(); // read variable declaration. |
| return; |
| case kFunctionDeclaration: |
| ReadPosition(); // read position. |
| CalculateVariableDeclarationFingerprint(); // read variable. |
| CalculateFunctionNodeFingerprint(); // read function node. |
| return; |
| default: |
| ReportUnexpectedTag("statement", tag); |
| UNREACHABLE(); |
| } |
| } |
| |
| uint32_t KernelFingerprintHelper::CalculateFieldFingerprint() { |
| hash_ = 0; |
| FieldHelper field_helper(this); |
| |
| field_helper.ReadUntilExcluding(FieldHelper::kName); |
| const String& name = ReadNameAsFieldName(); // read name. |
| field_helper.SetJustRead(FieldHelper::kName); |
| |
| field_helper.ReadUntilExcluding(FieldHelper::kType); |
| CalculateDartTypeFingerprint(); // read type. |
| field_helper.SetJustRead(FieldHelper::kType); |
| |
| if (ReadTag() == kSomething) { |
| if (PeekTag() == kFunctionExpression) { |
| AlternativeReadingScope alt(&reader_); |
| CalculateExpressionFingerprint(); |
| } |
| SkipExpression(); |
| } |
| |
| BuildHash(name.Hash()); |
| BuildHash(field_helper.flags_); |
| BuildHash(field_helper.annotation_count_); |
| return hash_; |
| } |
| |
| void KernelFingerprintHelper::CalculateFunctionNodeFingerprint() { |
| FunctionNodeHelper function_node_helper(this); |
| |
| function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters); |
| CalculateTypeParametersListFingerprint(); |
| function_node_helper.SetJustRead(FunctionNodeHelper::kTypeParameters); |
| |
| function_node_helper.ReadUntilExcluding( |
| FunctionNodeHelper::kPositionalParameters); |
| CalculateListOfVariableDeclarationsFingerprint(); // read positionals |
| CalculateListOfVariableDeclarationsFingerprint(); // read named |
| CalculateDartTypeFingerprint(); // read return type. |
| |
| if (ReadTag() == kSomething) { |
| CalculateStatementFingerprint(); // Read body. |
| } |
| BuildHash(function_node_helper.total_parameter_count_); |
| BuildHash(function_node_helper.required_parameter_count_); |
| } |
| |
| uint32_t KernelFingerprintHelper::CalculateFunctionFingerprint() { |
| hash_ = 0; |
| Tag tag = PeekTag(); |
| if (tag == kField) { |
| return CalculateFieldFingerprint(); |
| } else if (tag == kConstructor) { |
| CalculateConstructorFingerprint(); |
| return hash_; |
| } |
| ProcedureHelper procedure_helper(this); |
| procedure_helper.ReadUntilExcluding(ProcedureHelper::kName); |
| const String& name = ReadNameAsMethodName(); // Read name. |
| procedure_helper.SetJustRead(ProcedureHelper::kName); |
| |
| procedure_helper.ReadUntilExcluding(ProcedureHelper::kFunction); |
| if (ReadTag() == kSomething) { |
| CalculateFunctionNodeFingerprint(); |
| } |
| |
| BuildHash(procedure_helper.kind_); |
| BuildHash(procedure_helper.flags_); |
| BuildHash(procedure_helper.annotation_count_); |
| BuildHash(name.Hash()); |
| return hash_; |
| } |
| |
| uint32_t KernelSourceFingerprintHelper::CalculateClassFingerprint( |
| const Class& klass) { |
| Zone* zone = Thread::Current()->zone(); |
| |
| // Handle typedefs. |
| if (klass.IsTypedefClass()) { |
| const Function& func = Function::Handle(zone, klass.signature_function()); |
| return CalculateFunctionFingerprint(func); |
| } |
| |
| String& name = String::Handle(zone, klass.Name()); |
| const Array& fields = Array::Handle(zone, klass.fields()); |
| const Array& functions = Array::Handle(zone, klass.functions()); |
| const Array& interfaces = Array::Handle(zone, klass.interfaces()); |
| AbstractType& type = AbstractType::Handle(zone); |
| |
| uint32_t hash = 0; |
| hash = KernelFingerprintHelper::CalculateHash(hash, name.Hash()); |
| |
| type = klass.super_type(); |
| if (!type.IsNull()) { |
| name = type.Name(); |
| hash = KernelFingerprintHelper::CalculateHash(hash, name.Hash()); |
| } |
| |
| Field& field = Field::Handle(zone); |
| // Calculate fingerprint for the class fields. |
| for (intptr_t i = 0; i < fields.Length(); ++i) { |
| field ^= fields.At(i); |
| uint32_t fingerprint = CalculateFieldFingerprint(field); |
| hash = KernelFingerprintHelper::CalculateHash(hash, fingerprint); |
| } |
| |
| // Calculate fingerprint for the class functions. |
| Function& func = Function::Handle(zone); |
| for (intptr_t i = 0; i < functions.Length(); ++i) { |
| func ^= functions.At(i); |
| uint32_t fingerprint = CalculateFunctionFingerprint(func); |
| hash = KernelFingerprintHelper::CalculateHash(hash, fingerprint); |
| } |
| |
| // Calculate fingerprint for the interfaces. |
| for (intptr_t i = 0; i < interfaces.Length(); ++i) { |
| type ^= interfaces.At(i); |
| name = type.Name(); |
| hash = KernelFingerprintHelper::CalculateHash(hash, name.Hash()); |
| } |
| |
| return hash; |
| } |
| |
| uint32_t KernelSourceFingerprintHelper::CalculateFieldFingerprint( |
| const Field& field) { |
| Thread* thread = Thread::Current(); |
| Zone* zone = thread->zone(); |
| const Script& script = Script::Handle(zone, field.Script()); |
| |
| TranslationHelper translation_helper(thread); |
| translation_helper.InitFromScript(script); |
| |
| KernelFingerprintHelper helper( |
| zone, &translation_helper, script, |
| ExternalTypedData::Handle(zone, field.KernelData()), |
| field.KernelDataProgramOffset()); |
| helper.SetOffset(field.kernel_offset()); |
| return helper.CalculateFieldFingerprint(); |
| } |
| |
| uint32_t KernelSourceFingerprintHelper::CalculateFunctionFingerprint( |
| const Function& func) { |
| Thread* thread = Thread::Current(); |
| Zone* zone = thread->zone(); |
| const Script& script = Script::Handle(zone, func.script()); |
| |
| TranslationHelper translation_helper(thread); |
| translation_helper.InitFromScript(script); |
| |
| KernelFingerprintHelper helper( |
| zone, &translation_helper, script, |
| ExternalTypedData::Handle(zone, func.KernelData()), |
| func.KernelDataProgramOffset()); |
| helper.SetOffset(func.kernel_offset()); |
| return helper.CalculateFunctionFingerprint(); |
| } |
| |
| } // namespace kernel |
| } // namespace dart |