| // 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. |
| |
| #ifndef RUNTIME_VM_COMPILER_FRONTEND_KERNEL_TRANSLATION_HELPER_H_ |
| #define RUNTIME_VM_COMPILER_FRONTEND_KERNEL_TRANSLATION_HELPER_H_ |
| |
| #if defined(DART_PRECOMPILED_RUNTIME) |
| #error "AOT runtime should not use compiler sources (including header files)" |
| #endif // defined(DART_PRECOMPILED_RUNTIME) |
| |
| #include "vm/compiler/backend/il.h" // For CompileType. |
| #include "vm/kernel.h" |
| #include "vm/kernel_binary.h" |
| #include "vm/object.h" |
| |
| namespace dart { |
| namespace kernel { |
| |
| class ConstantReader; |
| class KernelReaderHelper; |
| class TypeTranslator; |
| |
| class TranslationHelper { |
| public: |
| explicit TranslationHelper(Thread* thread); |
| |
| TranslationHelper(Thread* thread, Heap::Space space); |
| |
| virtual ~TranslationHelper() {} |
| |
| void Reset(); |
| |
| void InitFromScript(const Script& script); |
| |
| void InitFromKernelProgramInfo(const KernelProgramInfo& info); |
| |
| Thread* thread() { return thread_; } |
| |
| Zone* zone() { return zone_; } |
| |
| Isolate* isolate() { return isolate_; } |
| |
| IsolateGroup* isolate_group() { return isolate_group_; } |
| |
| Heap::Space allocation_space() { return allocation_space_; } |
| |
| // Access to strings. |
| const TypedData& string_offsets() const { return string_offsets_; } |
| void SetStringOffsets(const TypedData& string_offsets); |
| |
| const ExternalTypedData& string_data() const { return string_data_; } |
| void SetStringData(const ExternalTypedData& string_data); |
| |
| const TypedData& canonical_names() const { return canonical_names_; } |
| void SetCanonicalNames(const TypedData& canonical_names); |
| |
| const ExternalTypedData& metadata_payloads() const { |
| return metadata_payloads_; |
| } |
| void SetMetadataPayloads(const ExternalTypedData& metadata_payloads); |
| |
| const ExternalTypedData& metadata_mappings() const { |
| return metadata_mappings_; |
| } |
| void SetMetadataMappings(const ExternalTypedData& metadata_mappings); |
| |
| // Access to previously evaluated constants from the constants table. |
| const Array& constants() { return constants_; } |
| void SetConstants(const Array& constants); |
| |
| // Access to the raw bytes of the constants table. |
| const ExternalTypedData& constants_table() const { return constants_table_; } |
| void SetConstantsTable(const ExternalTypedData& constants_table); |
| |
| KernelProgramInfo& info() { return info_; } |
| |
| GrowableObjectArrayPtr EnsurePotentialPragmaFunctions(); |
| |
| void AddPotentialExtensionLibrary(const Library& library); |
| GrowableObjectArrayPtr GetPotentialExtensionLibraries(); |
| |
| void SetKernelProgramInfo(const KernelProgramInfo& info); |
| const KernelProgramInfo& GetKernelProgramInfo() const { return info_; } |
| |
| intptr_t StringOffset(StringIndex index) const; |
| intptr_t StringSize(StringIndex index) const; |
| |
| // The address of the backing store of the string with a given index. If the |
| // backing store is in the VM's heap this address is not safe for GC (call the |
| // function and use the result within a NoSafepointScope). |
| uint8_t* StringBuffer(StringIndex index) const; |
| |
| uint8_t CharacterAt(StringIndex string_index, intptr_t index); |
| bool StringEquals(StringIndex string_index, const char* other); |
| |
| // Accessors and predicates for canonical names. |
| NameIndex CanonicalNameParent(NameIndex name); |
| StringIndex CanonicalNameString(NameIndex name); |
| bool IsAdministrative(NameIndex name); |
| bool IsPrivate(NameIndex name); |
| bool IsRoot(NameIndex name); |
| bool IsLibrary(NameIndex name); |
| bool IsClass(NameIndex name); |
| bool IsMember(NameIndex name); |
| bool IsConstructor(NameIndex name); |
| bool IsProcedure(NameIndex name); |
| bool IsMethod(NameIndex name); |
| bool IsGetter(NameIndex name); |
| bool IsSetter(NameIndex name); |
| bool IsFactory(NameIndex name); |
| bool IsField(NameIndex name); |
| |
| // For a member (field, constructor, or procedure) return the canonical name |
| // of the enclosing class or library. |
| NameIndex EnclosingName(NameIndex name); |
| |
| InstancePtr Canonicalize(const Instance& instance); |
| |
| const String& DartString(const char* content) { |
| return DartString(content, allocation_space_); |
| } |
| const String& DartString(const char* content, Heap::Space space); |
| |
| String& DartString(StringIndex index) { |
| return DartString(index, allocation_space_); |
| } |
| String& DartString(StringIndex string_index, Heap::Space space); |
| |
| String& DartString(const uint8_t* utf8_array, |
| intptr_t len, |
| Heap::Space space); |
| |
| const String& DartString(const GrowableHandlePtrArray<const String>& pieces); |
| |
| const String& DartSymbolPlain(const char* content) const; |
| String& DartSymbolPlain(StringIndex string_index) const; |
| const String& DartSymbolObfuscate(const char* content) const; |
| String& DartSymbolObfuscate(StringIndex string_index) const; |
| |
| String& DartIdentifier(const Library& lib, StringIndex string_index); |
| |
| const String& DartClassName(NameIndex kernel_class); |
| |
| const String& DartConstructorName(NameIndex constructor); |
| |
| const String& DartProcedureName(NameIndex procedure); |
| |
| const String& DartSetterName(NameIndex setter); |
| const String& DartSetterName(NameIndex parent, StringIndex setter); |
| |
| const String& DartGetterName(NameIndex getter); |
| const String& DartGetterName(NameIndex parent, StringIndex getter); |
| |
| const String& DartFieldName(NameIndex field); |
| const String& DartFieldName(NameIndex parent, StringIndex field); |
| |
| const String& DartMethodName(NameIndex method); |
| const String& DartMethodName(NameIndex parent, StringIndex method); |
| |
| const String& DartFactoryName(NameIndex factory); |
| |
| // A subclass overrides these when reading in the Kernel program in order to |
| // support recursive type expressions (e.g. for "implements X" ... |
| // annotations). |
| virtual LibraryPtr LookupLibraryByKernelLibrary(NameIndex library); |
| virtual ClassPtr LookupClassByKernelClass(NameIndex klass); |
| |
| FieldPtr LookupFieldByKernelField(NameIndex field); |
| FieldPtr LookupFieldByKernelGetterOrSetter(NameIndex field, |
| bool required = true); |
| FunctionPtr LookupStaticMethodByKernelProcedure(NameIndex procedure, |
| bool required = true); |
| FunctionPtr LookupConstructorByKernelConstructor(NameIndex constructor); |
| FunctionPtr LookupConstructorByKernelConstructor(const Class& owner, |
| NameIndex constructor); |
| FunctionPtr LookupConstructorByKernelConstructor( |
| const Class& owner, |
| StringIndex constructor_name); |
| FunctionPtr LookupMethodByMember(NameIndex target, const String& method_name); |
| FunctionPtr LookupDynamicFunction(const Class& klass, const String& name); |
| |
| Type& GetDeclarationType(const Class& klass); |
| |
| void SetupFieldAccessorFunction(const Class& klass, |
| const Function& function, |
| const AbstractType& field_type); |
| |
| void ReportError(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); |
| void ReportError(const Script& script, |
| const TokenPosition position, |
| const char* format, |
| ...) PRINTF_ATTRIBUTE(4, 5); |
| void ReportError(const Error& prev_error, const char* format, ...) |
| PRINTF_ATTRIBUTE(3, 4); |
| void ReportError(const Error& prev_error, |
| const Script& script, |
| const TokenPosition position, |
| const char* format, |
| ...) PRINTF_ATTRIBUTE(5, 6); |
| |
| void SetExpressionEvaluationFunction(const Function& function) { |
| ASSERT(expression_evaluation_function_ == nullptr); |
| expression_evaluation_function_ = &Function::Handle(zone_, function.ptr()); |
| } |
| const Function& GetExpressionEvaluationFunction() { |
| if (expression_evaluation_function_ == nullptr) { |
| return Function::null_function(); |
| } |
| return *expression_evaluation_function_; |
| } |
| void SetExpressionEvaluationClass(const Class& cls) { |
| ASSERT(expression_evaluation_class_ == nullptr); |
| ASSERT(!cls.IsNull()); |
| expression_evaluation_class_ = &Class::Handle(zone_, cls.ptr()); |
| } |
| const Class& GetExpressionEvaluationClass() { |
| if (expression_evaluation_class_ == nullptr) { |
| return Class::null_class(); |
| } |
| return *expression_evaluation_class_; |
| } |
| void SetExpressionEvaluationRealClass(const Class& real_class) { |
| ASSERT(expression_evaluation_real_class_ == nullptr); |
| ASSERT(!real_class.IsNull()); |
| expression_evaluation_real_class_ = &Class::Handle(zone_, real_class.ptr()); |
| } |
| const Class& GetExpressionEvaluationRealClass() { |
| if (expression_evaluation_real_class_ == nullptr) { |
| return Class::null_class(); |
| } |
| return *expression_evaluation_real_class_; |
| } |
| |
| private: |
| // This will mangle [name_to_modify] if necessary and make the result a symbol |
| // if asked. The result will be available in [name_to_modify] and it is also |
| // returned. If the name is private, the canonical name [parent] will be used |
| // to get the import URI of the library where the name is visible. |
| String& ManglePrivateName(NameIndex parent, |
| String* name_to_modify, |
| bool symbolize = true, |
| bool obfuscate = true); |
| String& ManglePrivateName(const Library& library, |
| String* name_to_modify, |
| bool symbolize = true, |
| bool obfuscate = true); |
| |
| Thread* thread_; |
| Zone* zone_; |
| Isolate* isolate_; |
| IsolateGroup* isolate_group_; |
| Heap::Space allocation_space_; |
| |
| TypedData& string_offsets_; |
| ExternalTypedData& string_data_; |
| TypedData& canonical_names_; |
| ExternalTypedData& metadata_payloads_; |
| ExternalTypedData& metadata_mappings_; |
| Array& constants_; |
| ExternalTypedData& constants_table_; |
| KernelProgramInfo& info_; |
| Smi& name_index_handle_; |
| GrowableObjectArray* potential_extension_libraries_ = nullptr; |
| Function* expression_evaluation_function_ = nullptr; |
| |
| // A temporary class needed to contain the function to which an eval |
| // expression is compiled. This is a fresh class so loading the kernel |
| // isn't a no-op. It should be unreachable after the eval function is loaded. |
| Class* expression_evaluation_class_ = nullptr; |
| |
| // The original class that is the scope in which the eval expression is |
| // evaluated. |
| Class* expression_evaluation_real_class_ = nullptr; |
| |
| DISALLOW_COPY_AND_ASSIGN(TranslationHelper); |
| }; |
| |
| // Helper class that reads a kernel FunctionNode from binary. |
| // |
| // Use ReadUntilExcluding to read up to but not including a field. |
| // One can then for instance read the field from the call-site (and remember to |
| // call SetAt to inform this helper class), and then use this to read more. |
| // Simple fields are stored (e.g. integers) and can be fetched from this class. |
| // If asked to read a compound field (e.g. an expression) it will be skipped. |
| class FunctionNodeHelper { |
| public: |
| enum Field { |
| kStart, // tag. |
| kPosition, |
| kEndPosition, |
| kAsyncMarker, |
| kDartAsyncMarker, |
| kTypeParameters, |
| kTotalParameterCount, |
| kRequiredParameterCount, |
| kPositionalParameters, |
| kNamedParameters, |
| kReturnType, |
| kFutureValueType, |
| kBody, |
| kEnd, |
| }; |
| |
| enum AsyncMarker : intptr_t { |
| kSync = 0, |
| kSyncStar = 1, |
| kAsync = 2, |
| kAsyncStar = 3, |
| kSyncYielding = 4, |
| }; |
| |
| explicit FunctionNodeHelper(KernelReaderHelper* helper) { |
| helper_ = helper; |
| next_read_ = kStart; |
| } |
| |
| void ReadUntilIncluding(Field field) { |
| ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1)); |
| } |
| |
| void ReadUntilExcluding(Field field); |
| |
| void SetNext(Field field) { next_read_ = field; } |
| void SetJustRead(Field field) { next_read_ = field + 1; } |
| |
| TokenPosition position_ = TokenPosition::kNoSource; |
| TokenPosition end_position_ = TokenPosition::kNoSource; |
| AsyncMarker async_marker_; |
| AsyncMarker dart_async_marker_; |
| intptr_t total_parameter_count_ = 0; |
| intptr_t required_parameter_count_ = 0; |
| |
| private: |
| KernelReaderHelper* helper_; |
| intptr_t next_read_; |
| |
| DISALLOW_COPY_AND_ASSIGN(FunctionNodeHelper); |
| }; |
| |
| class TypeParameterHelper { |
| public: |
| enum Field { |
| kStart, // tag. |
| kFlags, |
| kAnnotations, |
| kVariance, |
| kName, |
| kBound, |
| kDefaultType, |
| kEnd, |
| }; |
| |
| enum Flag { |
| kIsGenericCovariantImpl = 1 << 0, |
| }; |
| |
| explicit TypeParameterHelper(KernelReaderHelper* helper) { |
| helper_ = helper; |
| next_read_ = kStart; |
| } |
| |
| void ReadUntilIncluding(Field field) { |
| ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1)); |
| } |
| |
| void ReadUntilExcluding(Field field); |
| |
| void SetNext(Field field) { next_read_ = field; } |
| void SetJustRead(Field field) { next_read_ = field + 1; } |
| |
| void ReadUntilExcludingAndSetJustRead(Field field) { |
| ReadUntilExcluding(field); |
| SetJustRead(field); |
| } |
| |
| void Finish() { ReadUntilExcluding(kEnd); } |
| |
| bool IsGenericCovariantImpl() { |
| return (flags_ & kIsGenericCovariantImpl) != 0; |
| } |
| |
| TokenPosition position_ = TokenPosition::kNoSource; |
| uint8_t flags_ = 0; |
| StringIndex name_index_; |
| |
| private: |
| KernelReaderHelper* helper_; |
| intptr_t next_read_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TypeParameterHelper); |
| }; |
| |
| // Helper class that reads a kernel VariableDeclaration from binary. |
| // |
| // Use ReadUntilExcluding to read up to but not including a field. |
| // One can then for instance read the field from the call-site (and remember to |
| // call SetAt to inform this helper class), and then use this to read more. |
| // Simple fields are stored (e.g. integers) and can be fetched from this class. |
| // If asked to read a compound field (e.g. an expression) it will be skipped. |
| class VariableDeclarationHelper { |
| public: |
| enum Field { |
| kPosition, |
| kEqualPosition, |
| kAnnotations, |
| kFlags, |
| kNameIndex, |
| kType, |
| kInitializer, |
| kEnd, |
| }; |
| |
| enum Flag { |
| kFinal = 1 << 0, |
| kConst = 1 << 1, |
| kCovariant = 1 << 3, |
| kIsGenericCovariantImpl = 1 << 4, |
| kLate = 1 << 5, |
| kRequired = 1 << 6, |
| kLowered = 1 << 7, |
| }; |
| |
| explicit VariableDeclarationHelper(KernelReaderHelper* helper) |
| : annotation_count_(0), helper_(helper), next_read_(kPosition) {} |
| |
| void ReadUntilIncluding(Field field) { |
| ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1)); |
| } |
| |
| void ReadUntilExcluding(Field field); |
| |
| void SetNext(Field field) { next_read_ = field; } |
| void SetJustRead(Field field) { next_read_ = field + 1; } |
| |
| bool IsConst() const { return (flags_ & kConst) != 0; } |
| bool IsFinal() const { return (flags_ & kFinal) != 0; } |
| bool IsCovariant() const { return (flags_ & kCovariant) != 0; } |
| bool IsLate() const { return (flags_ & kLate) != 0; } |
| bool IsRequired() const { return (flags_ & kRequired) != 0; } |
| |
| bool IsGenericCovariantImpl() const { |
| return (flags_ & kIsGenericCovariantImpl) != 0; |
| } |
| |
| TokenPosition position_ = TokenPosition::kNoSource; |
| TokenPosition equals_position_ = TokenPosition::kNoSource; |
| uint8_t flags_ = 0; |
| StringIndex name_index_; |
| intptr_t annotation_count_ = 0; |
| |
| private: |
| KernelReaderHelper* helper_; |
| intptr_t next_read_; |
| |
| DISALLOW_COPY_AND_ASSIGN(VariableDeclarationHelper); |
| }; |
| |
| // Helper class that reads a kernel Field from binary. |
| // |
| // Use ReadUntilExcluding to read up to but not including a field. |
| // One can then for instance read the field from the call-site (and remember to |
| // call SetAt to inform this helper class), and then use this to read more. |
| // Simple fields are stored (e.g. integers) and can be fetched from this class. |
| // If asked to read a compound field (e.g. an expression) it will be skipped. |
| class FieldHelper { |
| public: |
| enum Field { |
| kStart, // tag. |
| kCanonicalNameField, |
| kCanonicalNameGetter, |
| kCanonicalNameSetter, |
| kSourceUriIndex, |
| kPosition, |
| kEndPosition, |
| kFlags, |
| kName, |
| kAnnotations, |
| kType, |
| kInitializer, |
| kEnd, |
| }; |
| |
| enum Flag { |
| kFinal = 1 << 0, |
| kConst = 1 << 1, |
| kStatic = 1 << 2, |
| kIsCovariant = 1 << 3, |
| kIsGenericCovariantImpl = 1 << 4, |
| kIsLate = 1 << 5, |
| kExtensionMember = 1 << 6, |
| }; |
| |
| explicit FieldHelper(KernelReaderHelper* helper) |
| : helper_(helper), next_read_(kStart) {} |
| |
| FieldHelper(KernelReaderHelper* helper, intptr_t offset); |
| |
| void ReadUntilIncluding(Field field) { |
| ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1)); |
| } |
| |
| void ReadUntilExcluding(Field field); |
| |
| void SetNext(Field field) { next_read_ = field; } |
| void SetJustRead(Field field) { next_read_ = field + 1; } |
| |
| bool IsConst() { return (flags_ & kConst) != 0; } |
| bool IsFinal() { return (flags_ & kFinal) != 0; } |
| bool IsStatic() { return (flags_ & kStatic) != 0; } |
| bool IsCovariant() const { return (flags_ & kIsCovariant) != 0; } |
| bool IsGenericCovariantImpl() { |
| return (flags_ & kIsGenericCovariantImpl) != 0; |
| } |
| bool IsLate() const { return (flags_ & kIsLate) != 0; } |
| bool IsExtensionMember() const { return (flags_ & kExtensionMember) != 0; } |
| |
| NameIndex canonical_name_field_; |
| NameIndex canonical_name_getter_; |
| NameIndex canonical_name_setter_; |
| TokenPosition position_ = TokenPosition::kNoSource; |
| TokenPosition end_position_ = TokenPosition::kNoSource; |
| uint32_t flags_ = 0; |
| intptr_t source_uri_index_ = 0; |
| intptr_t annotation_count_ = 0; |
| |
| private: |
| KernelReaderHelper* helper_; |
| intptr_t next_read_; |
| |
| DISALLOW_COPY_AND_ASSIGN(FieldHelper); |
| }; |
| |
| // Helper class that reads a kernel Procedure from binary. |
| // |
| // Use ReadUntilExcluding to read up to but not including a field. |
| // One can then for instance read the field from the call-site (and remember to |
| // call SetAt to inform this helper class), and then use this to read more. |
| // Simple fields are stored (e.g. integers) and can be fetched from this class. |
| // If asked to read a compound field (e.g. an expression) it will be skipped. |
| class ProcedureHelper { |
| public: |
| enum Field { |
| kStart, // tag. |
| kCanonicalName, |
| kSourceUriIndex, |
| kStartPosition, |
| kPosition, |
| kEndPosition, |
| kKind, |
| kStubKind, |
| kFlags, |
| kName, |
| kAnnotations, |
| kStubTarget, |
| kSignatureType, |
| kFunction, |
| kEnd, |
| }; |
| |
| enum Kind { |
| kMethod, |
| kGetter, |
| kSetter, |
| kOperator, |
| kFactory, |
| }; |
| |
| enum StubKind { |
| kRegularStubKind, |
| kAbstractForwardingStubKind, |
| kConcreteForwardingStubKind, |
| kNoSuchMethodForwarderStubKind, |
| kMemberSignatureStubKind, |
| kAbstractMixinStubKind, |
| kConcreteMixinStubKind, |
| }; |
| |
| enum Flag { |
| kStatic = 1 << 0, |
| kAbstract = 1 << 1, |
| kExternal = 1 << 2, |
| kConst = 1 << 3, // Only for external const factories. |
| |
| // TODO(29841): Remove this line after the issue is resolved. |
| kRedirectingFactory = 1 << 4, |
| kExtensionMember = 1 << 5, |
| kSyntheticProcedure = 1 << 7, |
| }; |
| |
| explicit ProcedureHelper(KernelReaderHelper* helper) |
| : helper_(helper), next_read_(kStart) {} |
| |
| void ReadUntilIncluding(Field field) { |
| ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1)); |
| } |
| |
| void ReadUntilExcluding(Field field); |
| |
| void SetNext(Field field) { next_read_ = field; } |
| void SetJustRead(Field field) { next_read_ = field + 1; } |
| |
| bool IsStatic() const { return (flags_ & kStatic) != 0; } |
| bool IsAbstract() const { return (flags_ & kAbstract) != 0; } |
| bool IsExternal() const { return (flags_ & kExternal) != 0; } |
| bool IsConst() const { return (flags_ & kConst) != 0; } |
| bool IsForwardingStub() const { |
| return stub_kind_ == kAbstractForwardingStubKind || |
| stub_kind_ == kConcreteForwardingStubKind; |
| } |
| bool IsRedirectingFactory() const { |
| return (flags_ & kRedirectingFactory) != 0; |
| } |
| bool IsNoSuchMethodForwarder() const { |
| return stub_kind_ == kNoSuchMethodForwarderStubKind; |
| } |
| bool IsExtensionMember() const { return (flags_ & kExtensionMember) != 0; } |
| bool IsMemberSignature() const { |
| return stub_kind_ == kMemberSignatureStubKind; |
| } |
| |
| NameIndex canonical_name_; |
| TokenPosition start_position_ = TokenPosition::kNoSource; |
| TokenPosition position_ = TokenPosition::kNoSource; |
| TokenPosition end_position_ = TokenPosition::kNoSource; |
| Kind kind_; |
| uint32_t flags_ = 0; |
| intptr_t source_uri_index_ = 0; |
| intptr_t annotation_count_ = 0; |
| StubKind stub_kind_; |
| |
| // Only valid if the 'isForwardingStub' flag is set. |
| NameIndex concrete_forwarding_stub_target_; |
| |
| private: |
| KernelReaderHelper* helper_; |
| intptr_t next_read_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ProcedureHelper); |
| }; |
| |
| // Helper class that reads a kernel Constructor from binary. |
| // |
| // Use ReadUntilExcluding to read up to but not including a field. |
| // One can then for instance read the field from the call-site (and remember to |
| // call SetAt to inform this helper class), and then use this to read more. |
| // Simple fields are stored (e.g. integers) and can be fetched from this class. |
| // If asked to read a compound field (e.g. an expression) it will be skipped. |
| class ConstructorHelper { |
| public: |
| enum Field { |
| kStart, // tag. |
| kCanonicalName, |
| kSourceUriIndex, |
| kStartPosition, |
| kPosition, |
| kEndPosition, |
| kFlags, |
| kName, |
| kAnnotations, |
| kFunction, |
| kInitializers, |
| kEnd, |
| }; |
| |
| enum Flag { |
| kConst = 1 << 0, |
| kExternal = 1 << 1, |
| kSynthetic = 1 << 2, |
| }; |
| |
| explicit ConstructorHelper(KernelReaderHelper* helper) |
| : helper_(helper), next_read_(kStart) {} |
| |
| void ReadUntilIncluding(Field field) { |
| ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1)); |
| } |
| |
| void ReadUntilExcluding(Field field); |
| |
| void SetNext(Field field) { next_read_ = field; } |
| void SetJustRead(Field field) { next_read_ = field + 1; } |
| |
| bool IsExternal() { return (flags_ & kExternal) != 0; } |
| bool IsConst() { return (flags_ & kConst) != 0; } |
| bool IsSynthetic() { return (flags_ & kSynthetic) != 0; } |
| |
| NameIndex canonical_name_; |
| TokenPosition start_position_ = TokenPosition::kNoSource; |
| TokenPosition position_ = TokenPosition::kNoSource; |
| TokenPosition end_position_ = TokenPosition::kNoSource; |
| uint8_t flags_ = 0; |
| intptr_t source_uri_index_ = 0; |
| intptr_t annotation_count_ = 0; |
| |
| private: |
| KernelReaderHelper* helper_; |
| intptr_t next_read_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ConstructorHelper); |
| }; |
| |
| // Helper class that reads a kernel Class from binary. |
| // |
| // Use ReadUntilExcluding to read up to but not including a field. |
| // One can then for instance read the field from the call-site (and remember to |
| // call SetAt to inform this helper class), and then use this to read more. |
| // Simple fields are stored (e.g. integers) and can be fetched from this class. |
| // If asked to read a compound field (e.g. an expression) it will be skipped. |
| class ClassHelper { |
| public: |
| enum Field { |
| kStart, // tag. |
| kCanonicalName, |
| kSourceUriIndex, |
| kStartPosition, |
| kPosition, |
| kEndPosition, |
| kFlags, |
| kNameIndex, |
| kAnnotations, |
| kTypeParameters, |
| kSuperClass, |
| kMixinType, |
| kImplementedClasses, |
| kFields, |
| kConstructors, |
| kProcedures, |
| kClassIndex, |
| kEnd, |
| }; |
| |
| enum Flag { |
| kIsAbstract = 1 << 0, |
| kIsEnumClass = 1 << 1, |
| kIsAnonymousMixin = 1 << 2, |
| kIsEliminatedMixin = 1 << 3, |
| kFlagMixinDeclaration = 1 << 4, |
| kHasConstConstructor = 1 << 5, |
| kIsMacro = 1 << 6, |
| }; |
| |
| explicit ClassHelper(KernelReaderHelper* helper) |
| : helper_(helper), next_read_(kStart) {} |
| |
| void ReadUntilIncluding(Field field) { |
| ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1)); |
| } |
| |
| void ReadUntilExcluding(Field field); |
| |
| void SetNext(Field field) { next_read_ = field; } |
| void SetJustRead(Field field) { next_read_ = field + 1; } |
| |
| bool is_abstract() const { return (flags_ & Flag::kIsAbstract) != 0; } |
| |
| bool is_enum_class() const { return (flags_ & Flag::kIsEnumClass) != 0; } |
| |
| bool is_transformed_mixin_application() const { |
| return (flags_ & Flag::kIsEliminatedMixin) != 0; |
| } |
| |
| bool has_const_constructor() const { |
| return (flags_ & Flag::kHasConstConstructor) != 0; |
| } |
| |
| NameIndex canonical_name_; |
| TokenPosition start_position_ = TokenPosition::kNoSource; |
| TokenPosition position_ = TokenPosition::kNoSource; |
| TokenPosition end_position_ = TokenPosition::kNoSource; |
| StringIndex name_index_; |
| intptr_t source_uri_index_ = 0; |
| intptr_t annotation_count_ = 0; |
| intptr_t procedure_count_ = 0; |
| uint8_t flags_ = 0; |
| |
| private: |
| KernelReaderHelper* helper_; |
| intptr_t next_read_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ClassHelper); |
| }; |
| |
| // Helper class that reads a kernel Library from binary. |
| // |
| // Use ReadUntilExcluding to read up to but not including a field. |
| // One can then for instance read the field from the call-site (and remember to |
| // call SetAt to inform this helper class), and then use this to read more. |
| // Simple fields are stored (e.g. integers) and can be fetched from this class. |
| // If asked to read a compound field (e.g. an expression) it will be skipped. |
| class LibraryHelper { |
| public: |
| enum Field { |
| kFlags, |
| kLanguageVersion /* from binary version 27 */, |
| kCanonicalName, |
| kName, |
| kSourceUriIndex, |
| kProblemsAsJson, |
| kAnnotations, |
| kDependencies, |
| // There are other fields in a library: |
| // * kAdditionalExports |
| // * kParts |
| // * kTypedefs |
| // * kClasses |
| // * kToplevelField |
| // * kToplevelProcedures |
| // * kSourceReferences |
| // * kLibraryIndex |
| // but we never read them via this helper and it makes extending the format |
| // harder to keep the code around. |
| }; |
| |
| enum Flag { |
| kSynthetic = 1 << 0, |
| kIsNonNullableByDefault = 1 << 1, |
| kNonNullableByDefaultCompiledModeBit1 = 1 << 2, |
| kNonNullableByDefaultCompiledModeBit2 = 1 << 3, |
| kUnsupported = 1 << 4, |
| }; |
| |
| explicit LibraryHelper(KernelReaderHelper* helper, uint32_t binary_version) |
| : helper_(helper), binary_version_(binary_version), next_read_(kFlags) {} |
| |
| void ReadUntilIncluding(Field field) { |
| ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1)); |
| } |
| |
| void ReadUntilExcluding(Field field); |
| |
| void SetNext(Field field) { next_read_ = field; } |
| void SetJustRead(Field field) { next_read_ = field + 1; } |
| |
| bool IsSynthetic() const { return (flags_ & kSynthetic) != 0; } |
| bool IsNonNullableByDefault() const { |
| return (flags_ & kIsNonNullableByDefault) != 0; |
| } |
| NNBDCompiledMode GetNonNullableByDefaultCompiledMode() const { |
| bool bit1 = (flags_ & kNonNullableByDefaultCompiledModeBit1) != 0; |
| bool bit2 = (flags_ & kNonNullableByDefaultCompiledModeBit2) != 0; |
| if (!bit1 && !bit2) return NNBDCompiledMode::kWeak; |
| if (bit1 && !bit2) return NNBDCompiledMode::kStrong; |
| if (bit1 && bit2) return NNBDCompiledMode::kAgnostic; |
| if (!bit1 && bit2) return NNBDCompiledMode::kInvalid; |
| UNREACHABLE(); |
| } |
| |
| uint8_t flags_ = 0; |
| NameIndex canonical_name_; |
| StringIndex name_index_; |
| intptr_t source_uri_index_ = 0; |
| |
| private: |
| KernelReaderHelper* helper_; |
| uint32_t binary_version_; |
| intptr_t next_read_; |
| |
| DISALLOW_COPY_AND_ASSIGN(LibraryHelper); |
| }; |
| |
| class LibraryDependencyHelper { |
| public: |
| enum Field { |
| kFileOffset, |
| kFlags, |
| kAnnotations, |
| kTargetLibrary, |
| kName, |
| kCombinators, |
| kEnd, |
| }; |
| |
| enum Flag { |
| Export = 1 << 0, |
| Deferred = 1 << 1, |
| }; |
| |
| enum CombinatorFlag { |
| Show = 1 << 0, |
| }; |
| |
| explicit LibraryDependencyHelper(KernelReaderHelper* helper) |
| : helper_(helper), next_read_(kFileOffset) {} |
| |
| void ReadUntilIncluding(Field field) { |
| ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1)); |
| } |
| |
| void ReadUntilExcluding(Field field); |
| |
| uint8_t flags_ = 0; |
| StringIndex name_index_; |
| NameIndex target_library_canonical_name_; |
| intptr_t annotation_count_ = 0; |
| |
| private: |
| KernelReaderHelper* helper_; |
| intptr_t next_read_; |
| |
| DISALLOW_COPY_AND_ASSIGN(LibraryDependencyHelper); |
| }; |
| |
| // Base class for helpers accessing metadata of a certain kind. |
| // Assumes that metadata is accessed in linear order. |
| class MetadataHelper { |
| public: |
| MetadataHelper(KernelReaderHelper* helper, |
| const char* tag, |
| bool precompiler_only); |
| |
| #if defined(DEBUG) |
| static void VerifyMetadataMappings( |
| const ExternalTypedData& metadata_mappings); |
| #endif |
| |
| protected: |
| // Look for metadata mapping with node offset greater or equal than the given. |
| intptr_t FindMetadataMapping(intptr_t node_offset); |
| |
| // Return offset of the metadata payload corresponding to the given node, |
| // or -1 if there is no metadata. |
| // Assumes metadata is accesses for nodes in linear order most of the time. |
| intptr_t GetNextMetadataPayloadOffset(intptr_t node_offset); |
| |
| // Returns metadata associated with component. |
| intptr_t GetComponentMetadataPayloadOffset(); |
| |
| KernelReaderHelper* helper_; |
| TranslationHelper& translation_helper_; |
| |
| private: |
| MetadataHelper(); |
| |
| void SetMetadataMappings(intptr_t mappings_offset, intptr_t mappings_num); |
| void ScanMetadataMappings(); |
| |
| const char* tag_; |
| bool mappings_scanned_; |
| bool precompiler_only_; |
| intptr_t mappings_offset_; |
| intptr_t mappings_num_; |
| intptr_t last_node_offset_; |
| intptr_t last_mapping_index_; |
| |
| DISALLOW_COPY_AND_ASSIGN(MetadataHelper); |
| }; |
| |
| struct DirectCallMetadata { |
| DirectCallMetadata(const Function& target, bool check_receiver_for_null) |
| : target_(target), check_receiver_for_null_(check_receiver_for_null) {} |
| |
| const Function& target_; |
| const bool check_receiver_for_null_; |
| }; |
| |
| // Helper class which provides access to direct call metadata. |
| class DirectCallMetadataHelper : public MetadataHelper { |
| public: |
| static const char* tag() { return "vm.direct-call.metadata"; } |
| |
| explicit DirectCallMetadataHelper(KernelReaderHelper* helper); |
| |
| DirectCallMetadata GetDirectTargetForPropertyGet(intptr_t node_offset); |
| DirectCallMetadata GetDirectTargetForPropertySet(intptr_t node_offset); |
| DirectCallMetadata GetDirectTargetForMethodInvocation(intptr_t node_offset); |
| |
| private: |
| bool ReadMetadata(intptr_t node_offset, |
| NameIndex* target_name, |
| bool* check_receiver_for_null); |
| |
| DISALLOW_COPY_AND_ASSIGN(DirectCallMetadataHelper); |
| }; |
| |
| struct InferredTypeMetadata { |
| enum Flag { |
| kFlagNullable = 1 << 0, |
| kFlagInt = 1 << 1, |
| kFlagSkipCheck = 1 << 2, |
| kFlagConstant = 1 << 3, |
| kFlagReceiverNotInt = 1 << 4, |
| }; |
| |
| InferredTypeMetadata(intptr_t cid_, |
| uint8_t flags_, |
| const Object& constant_value_ = Object::null_object()) |
| : cid(cid_), flags(flags_), constant_value(constant_value_) {} |
| |
| const intptr_t cid; |
| const uint8_t flags; |
| const Object& constant_value; |
| |
| bool IsTrivial() const { |
| return (cid == kDynamicCid) && (flags == kFlagNullable); |
| } |
| bool IsNullable() const { return (flags & kFlagNullable) != 0; } |
| bool IsInt() const { |
| return (flags & kFlagInt) != 0 || cid == kMintCid || cid == kSmiCid; |
| } |
| bool IsSkipCheck() const { return (flags & kFlagSkipCheck) != 0; } |
| bool IsConstant() const { return (flags & kFlagConstant) != 0; } |
| bool ReceiverNotInt() const { return (flags & kFlagReceiverNotInt) != 0; } |
| |
| CompileType ToCompileType(Zone* zone) const { |
| if (IsInt() && cid == kDynamicCid) { |
| return CompileType::FromAbstractType( |
| Type::ZoneHandle( |
| zone, (IsNullable() ? Type::NullableIntType() : Type::IntType())), |
| IsNullable(), CompileType::kCannotBeSentinel); |
| } else { |
| return CompileType(IsNullable(), CompileType::kCannotBeSentinel, cid, |
| nullptr); |
| } |
| } |
| }; |
| |
| // Helper class which provides access to inferred type metadata. |
| class InferredTypeMetadataHelper : public MetadataHelper { |
| public: |
| static const char* tag() { return "vm.inferred-type.metadata"; } |
| |
| explicit InferredTypeMetadataHelper(KernelReaderHelper* helper, |
| ConstantReader* constant_reader); |
| |
| InferredTypeMetadata GetInferredType(intptr_t node_offset, |
| bool read_constant = true); |
| |
| private: |
| ConstantReader* constant_reader_; |
| |
| DISALLOW_COPY_AND_ASSIGN(InferredTypeMetadataHelper); |
| }; |
| |
| struct ProcedureAttributesMetadata { |
| static const int32_t kInvalidSelectorId = 0; |
| |
| bool method_or_setter_called_dynamically = true; |
| bool getter_called_dynamically = true; |
| bool has_this_uses = true; |
| bool has_non_this_uses = true; |
| bool has_tearoff_uses = true; |
| int32_t method_or_setter_selector_id = kInvalidSelectorId; |
| int32_t getter_selector_id = kInvalidSelectorId; |
| |
| void InitializeFromFlags(uint8_t flags); |
| }; |
| |
| // Helper class which provides access to direct call metadata. |
| class ProcedureAttributesMetadataHelper : public MetadataHelper { |
| public: |
| static const char* tag() { return "vm.procedure-attributes.metadata"; } |
| |
| explicit ProcedureAttributesMetadataHelper(KernelReaderHelper* helper); |
| |
| ProcedureAttributesMetadata GetProcedureAttributes(intptr_t node_offset); |
| |
| private: |
| bool ReadMetadata(intptr_t node_offset, |
| ProcedureAttributesMetadata* metadata); |
| |
| DISALLOW_COPY_AND_ASSIGN(ProcedureAttributesMetadataHelper); |
| }; |
| |
| class ObfuscationProhibitionsMetadataHelper : public MetadataHelper { |
| public: |
| static const char* tag() { return "vm.obfuscation-prohibitions.metadata"; } |
| |
| explicit ObfuscationProhibitionsMetadataHelper(KernelReaderHelper* helper); |
| |
| void ReadProhibitions() { ReadMetadata(0); } |
| |
| private: |
| void ReadMetadata(intptr_t node_offset); |
| |
| DISALLOW_COPY_AND_ASSIGN(ObfuscationProhibitionsMetadataHelper); |
| }; |
| |
| class LoadingUnitsMetadataHelper : public MetadataHelper { |
| public: |
| static const char* tag() { return "vm.loading-units.metadata"; } |
| |
| explicit LoadingUnitsMetadataHelper(KernelReaderHelper* helper); |
| |
| void ReadLoadingUnits() { ReadMetadata(0); } |
| |
| private: |
| void ReadMetadata(intptr_t node_offset); |
| |
| DISALLOW_COPY_AND_ASSIGN(LoadingUnitsMetadataHelper); |
| }; |
| |
| struct CallSiteAttributesMetadata { |
| const AbstractType* receiver_type = nullptr; |
| }; |
| |
| // Helper class which provides access to direct call metadata. |
| class CallSiteAttributesMetadataHelper : public MetadataHelper { |
| public: |
| static const char* tag() { return "vm.call-site-attributes.metadata"; } |
| |
| CallSiteAttributesMetadataHelper(KernelReaderHelper* helper, |
| TypeTranslator* type_translator); |
| |
| CallSiteAttributesMetadata GetCallSiteAttributes(intptr_t node_offset); |
| |
| private: |
| bool ReadMetadata(intptr_t node_offset, CallSiteAttributesMetadata* metadata); |
| |
| TypeTranslator& type_translator_; |
| |
| DISALLOW_COPY_AND_ASSIGN(CallSiteAttributesMetadataHelper); |
| }; |
| |
| // Information about a table selector computed by the TFA. |
| struct TableSelectorInfo { |
| int call_count = 0; |
| bool called_on_null = true; |
| bool torn_off = true; |
| }; |
| |
| // Collection of table selector information for all selectors in the program. |
| class TableSelectorMetadata : public ZoneAllocated { |
| public: |
| explicit TableSelectorMetadata(intptr_t num_selectors) |
| : selectors(num_selectors) { |
| selectors.FillWith(TableSelectorInfo(), 0, num_selectors); |
| } |
| |
| GrowableArray<TableSelectorInfo> selectors; |
| |
| DISALLOW_COPY_AND_ASSIGN(TableSelectorMetadata); |
| }; |
| |
| // Helper class which provides access to table selector metadata. |
| class TableSelectorMetadataHelper : public MetadataHelper { |
| public: |
| static const char* tag() { return "vm.table-selector.metadata"; } |
| |
| explicit TableSelectorMetadataHelper(KernelReaderHelper* helper); |
| |
| TableSelectorMetadata* GetTableSelectorMetadata(Zone* zone); |
| |
| private: |
| static const uint8_t kCalledOnNullBit = 1 << 0; |
| static const uint8_t kTornOffBit = 1 << 1; |
| |
| void ReadTableSelectorInfo(TableSelectorInfo* info); |
| |
| DISALLOW_COPY_AND_ASSIGN(TableSelectorMetadataHelper); |
| }; |
| |
| // Information about a function regarding unboxed parameters and return value. |
| class UnboxingInfoMetadata : public ZoneAllocated { |
| public: |
| enum UnboxingInfoTag { |
| kBoxed = 0, |
| kUnboxedIntCandidate = 1 << 0, |
| kUnboxedDoubleCandidate = 1 << 1, |
| kUnboxingCandidate = kUnboxedIntCandidate | kUnboxedDoubleCandidate, |
| }; |
| |
| UnboxingInfoMetadata() : unboxed_args_info(0) { return_info = kBoxed; } |
| |
| void SetArgsCount(intptr_t num_args) { |
| ASSERT(unboxed_args_info.is_empty()); |
| unboxed_args_info.SetLength(num_args); |
| unboxed_args_info.FillWith(kBoxed, 0, num_args); |
| } |
| |
| GrowableArray<UnboxingInfoTag> unboxed_args_info; |
| UnboxingInfoTag return_info; |
| |
| DISALLOW_COPY_AND_ASSIGN(UnboxingInfoMetadata); |
| }; |
| |
| // Helper class which provides access to unboxing information metadata. |
| class UnboxingInfoMetadataHelper : public MetadataHelper { |
| public: |
| static const char* tag() { return "vm.unboxing-info.metadata"; } |
| |
| explicit UnboxingInfoMetadataHelper(KernelReaderHelper* helper); |
| |
| UnboxingInfoMetadata* GetUnboxingInfoMetadata(intptr_t node_offset); |
| |
| DISALLOW_COPY_AND_ASSIGN(UnboxingInfoMetadataHelper); |
| }; |
| |
| class KernelReaderHelper { |
| public: |
| KernelReaderHelper(Zone* zone, |
| TranslationHelper* translation_helper, |
| const Script& script, |
| const ExternalTypedData& data, |
| intptr_t data_program_offset) |
| : zone_(zone), |
| translation_helper_(*translation_helper), |
| reader_(data), |
| script_(script), |
| data_program_offset_(data_program_offset) {} |
| |
| KernelReaderHelper(Zone* zone, |
| TranslationHelper* translation_helper, |
| const ProgramBinary& binary, |
| intptr_t data_program_offset) |
| : zone_(zone), |
| translation_helper_(*translation_helper), |
| reader_(binary), |
| script_(Script::Handle(zone_)), |
| data_program_offset_(data_program_offset) {} |
| |
| virtual ~KernelReaderHelper() = default; |
| |
| void SetOffset(intptr_t offset); |
| |
| intptr_t ReadListLength(); |
| virtual void ReportUnexpectedTag(const char* variant, Tag tag); |
| |
| void ReadUntilFunctionNode(); |
| |
| Tag PeekTag(uint8_t* payload = NULL); |
| |
| protected: |
| const Script& script() const { return script_; } |
| |
| virtual void set_current_script_id(intptr_t id) { |
| // Do nothing by default. |
| // This is overridden in KernelTokenPositionCollector. |
| USE(id); |
| } |
| |
| virtual void RecordTokenPosition(TokenPosition position) { |
| // Do nothing by default. |
| // This is overridden in KernelTokenPositionCollector. |
| USE(position); |
| } |
| |
| intptr_t ReaderOffset() const; |
| intptr_t ReaderSize() const; |
| void SkipBytes(intptr_t skip); |
| bool ReadBool(); |
| uint8_t ReadByte(); |
| uint32_t ReadUInt(); |
| uint32_t ReadUInt32(); |
| uint32_t PeekUInt(); |
| double ReadDouble(); |
| uint32_t PeekListLength(); |
| StringIndex ReadStringReference(); |
| NameIndex ReadCanonicalNameReference(); |
| NameIndex ReadInterfaceMemberNameReference(); |
| StringIndex ReadNameAsStringIndex(); |
| const String& ReadNameAsMethodName(); |
| const String& ReadNameAsGetterName(); |
| const String& ReadNameAsSetterName(); |
| const String& ReadNameAsFieldName(); |
| void SkipFlags(); |
| void SkipStringReference(); |
| void SkipConstantReference(); |
| void SkipCanonicalNameReference(); |
| void SkipInterfaceMemberNameReference(); |
| void SkipDartType(); |
| void SkipOptionalDartType(); |
| void SkipInterfaceType(bool simple); |
| void SkipFunctionType(bool simple); |
| void SkipStatementList(); |
| void SkipListOfExpressions(); |
| void SkipListOfDartTypes(); |
| void SkipListOfStrings(); |
| void SkipListOfVariableDeclarations(); |
| void SkipListOfCanonicalNameReferences(); |
| void SkipTypeParametersList(); |
| void SkipInitializer(); |
| void SkipExpression(); |
| void SkipStatement(); |
| void SkipFunctionNode(); |
| void SkipName(); |
| void SkipArguments(); |
| void SkipVariableDeclaration(); |
| void SkipLibraryCombinator(); |
| void SkipLibraryDependency(); |
| void SkipLibraryPart(); |
| void SkipLibraryTypedef(); |
| TokenPosition ReadPosition(); |
| Tag ReadTag(uint8_t* payload = NULL); |
| uint8_t ReadFlags() { return reader_.ReadFlags(); } |
| Nullability ReadNullability(); |
| Variance ReadVariance(); |
| |
| intptr_t SourceTableSize(); |
| intptr_t GetOffsetForSourceInfo(intptr_t index); |
| String& SourceTableUriFor(intptr_t index); |
| const String& GetSourceFor(intptr_t index); |
| TypedDataPtr GetLineStartsFor(intptr_t index); |
| String& SourceTableImportUriFor(intptr_t index, uint32_t binaryVersion); |
| ExternalTypedDataPtr GetConstantCoverageFor(intptr_t index); |
| |
| Zone* zone_; |
| TranslationHelper& translation_helper_; |
| Reader reader_; |
| const Script& script_; |
| // Some items like variables are specified in the kernel binary as |
| // absolute offsets (as in, offsets within the whole kernel program) |
| // of their declaration nodes. Hence, to cache and/or access them |
| // uniquely from within a function's kernel data, we need to |
| // add/subtract the offset of the kernel data in the over all |
| // kernel program. |
| intptr_t data_program_offset_; |
| |
| friend class ClassHelper; |
| friend class CallSiteAttributesMetadataHelper; |
| friend class ConstantReader; |
| friend class ConstantHelper; |
| friend class ConstructorHelper; |
| friend class DirectCallMetadataHelper; |
| friend class FieldHelper; |
| friend class FunctionNodeHelper; |
| friend class InferredTypeMetadataHelper; |
| friend class KernelLoader; |
| friend class LibraryDependencyHelper; |
| friend class LibraryHelper; |
| friend class MetadataHelper; |
| friend class ProcedureAttributesMetadataHelper; |
| friend class ProcedureHelper; |
| friend class SimpleExpressionConverter; |
| friend class ScopeBuilder; |
| friend class TableSelectorMetadataHelper; |
| friend class TypeParameterHelper; |
| friend class TypeTranslator; |
| friend class UnboxingInfoMetadataHelper; |
| friend class VariableDeclarationHelper; |
| friend class ObfuscationProhibitionsMetadataHelper; |
| friend class LoadingUnitsMetadataHelper; |
| friend bool NeedsDynamicInvocationForwarder(const Function& function); |
| friend ArrayPtr CollectConstConstructorCoverageFrom( |
| const Script& interesting_script); |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(KernelReaderHelper); |
| }; |
| |
| class ActiveClass { |
| public: |
| ActiveClass() |
| : klass(NULL), |
| member(NULL), |
| enclosing(NULL), |
| local_type_parameters(NULL) {} |
| |
| bool HasMember() { return member != NULL; } |
| |
| bool MemberIsProcedure() { |
| ASSERT(member != NULL); |
| UntaggedFunction::Kind function_kind = member->kind(); |
| return function_kind == UntaggedFunction::kRegularFunction || |
| function_kind == UntaggedFunction::kGetterFunction || |
| function_kind == UntaggedFunction::kSetterFunction || |
| function_kind == UntaggedFunction::kMethodExtractor || |
| function_kind == UntaggedFunction::kDynamicInvocationForwarder || |
| member->IsFactory(); |
| } |
| |
| bool MemberIsFactoryProcedure() { |
| ASSERT(member != NULL); |
| return member->IsFactory(); |
| } |
| |
| bool RequireConstCanonicalTypeErasure(bool null_safety) const { |
| return klass != nullptr && !null_safety && |
| Library::Handle(klass->library()).nnbd_compiled_mode() == |
| NNBDCompiledMode::kAgnostic; |
| } |
| |
| intptr_t MemberTypeParameterCount(Zone* zone); |
| |
| intptr_t ClassNumTypeArguments() { |
| ASSERT(klass != NULL); |
| return klass->NumTypeArguments(); |
| } |
| |
| void RecordDerivedTypeParameter(Zone* zone, const TypeParameter& derived) { |
| if (derived.bound() == AbstractType::null()) { |
| if (derived_type_parameters == nullptr) { |
| derived_type_parameters = &GrowableObjectArray::Handle( |
| zone, GrowableObjectArray::New(Heap::kOld)); |
| } |
| derived_type_parameters->Add(derived); |
| } |
| } |
| |
| const char* ToCString() { |
| return member != NULL ? member->ToCString() : klass->ToCString(); |
| } |
| |
| // The current enclosing class (or the library top-level class). |
| const Class* klass; |
| |
| const Function* member; |
| |
| // The innermost enclosing signature. This is used for building types, as a |
| // parent for function types. |
| const FunctionType* enclosing; |
| |
| const TypeArguments* local_type_parameters; |
| |
| GrowableObjectArray* derived_type_parameters = nullptr; |
| }; |
| |
| class ActiveClassScope { |
| public: |
| ActiveClassScope(ActiveClass* active_class, const Class* klass) |
| : active_class_(active_class), saved_(*active_class) { |
| active_class_->klass = klass; |
| } |
| |
| ~ActiveClassScope() { *active_class_ = saved_; } |
| |
| private: |
| ActiveClass* active_class_; |
| ActiveClass saved_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ActiveClassScope); |
| }; |
| |
| class ActiveMemberScope { |
| public: |
| ActiveMemberScope(ActiveClass* active_class, const Function* member) |
| : active_class_(active_class), saved_(*active_class) { |
| // The class is inherited. |
| active_class_->member = member; |
| } |
| |
| ~ActiveMemberScope() { *active_class_ = saved_; } |
| |
| private: |
| ActiveClass* active_class_; |
| ActiveClass saved_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ActiveMemberScope); |
| }; |
| |
| class ActiveEnclosingFunctionScope { |
| public: |
| ActiveEnclosingFunctionScope(ActiveClass* active_class, |
| const FunctionType* enclosing_signature) |
| : active_class_(active_class), saved_(*active_class) { |
| active_class_->enclosing = enclosing_signature; |
| } |
| |
| ~ActiveEnclosingFunctionScope() { *active_class_ = saved_; } |
| |
| private: |
| ActiveClass* active_class_; |
| ActiveClass saved_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ActiveEnclosingFunctionScope); |
| }; |
| |
| class ActiveTypeParametersScope { |
| public: |
| // Set the local type parameters of the ActiveClass to be exactly all type |
| // parameters defined by 'innermost' and any enclosing *closures* (but not |
| // enclosing methods/top-level functions/classes). |
| // |
| // Also, the enclosing signature is set to innermost's signature. |
| ActiveTypeParametersScope(ActiveClass* active_class, |
| const Function& innermost, |
| const FunctionType* innermost_signature, |
| Zone* Z); |
| |
| // Append the list of the local type parameters to the list in ActiveClass. |
| // |
| // Also, the enclosing signature is set to 'signature'. |
| ActiveTypeParametersScope(ActiveClass* active_class, |
| const FunctionType* innermost_signature, |
| Zone* Z); |
| |
| ~ActiveTypeParametersScope(); |
| |
| private: |
| ActiveClass* active_class_; |
| ActiveClass saved_; |
| Zone* zone_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ActiveTypeParametersScope); |
| }; |
| |
| class TypeTranslator { |
| public: |
| TypeTranslator(KernelReaderHelper* helper, |
| ConstantReader* constant_reader, |
| ActiveClass* active_class, |
| bool finalize = false, |
| bool apply_canonical_type_erasure = false, |
| bool in_constant_context = false); |
| |
| AbstractType& BuildType(); |
| AbstractType& BuildTypeWithoutFinalization(); |
| |
| const TypeArguments& BuildTypeArguments(intptr_t length); |
| |
| const TypeArguments& BuildInstantiatedTypeArguments( |
| const Class& receiver_class, |
| intptr_t length); |
| |
| void LoadAndSetupTypeParameters(ActiveClass* active_class, |
| const Function& function, |
| const Class& parameterized_class, |
| const FunctionType& parameterized_signature, |
| intptr_t type_parameter_count); |
| |
| void LoadAndSetupBounds(ActiveClass* active_class, |
| const Function& function, |
| const Class& parameterized_class, |
| const FunctionType& parameterized_signature, |
| intptr_t type_parameter_count); |
| |
| const Type& ReceiverType(const Class& klass); |
| |
| void SetupFunctionParameters(const Class& klass, |
| const Function& function, |
| bool is_method, |
| bool is_closure, |
| FunctionNodeHelper* function_node_helper); |
| |
| private: |
| void SetupUnboxingInfoMetadata(const Function& function, |
| intptr_t library_kernel_offset); |
| void SetupUnboxingInfoMetadataForFieldAccessors( |
| const Function& field_accessor, |
| intptr_t library_kernel_offset); |
| |
| void BuildTypeInternal(); |
| void BuildInterfaceType(bool simple); |
| void BuildFunctionType(bool simple); |
| void BuildTypeParameterType(); |
| |
| class TypeParameterScope { |
| public: |
| TypeParameterScope(TypeTranslator* translator, intptr_t parameter_count) |
| : parameter_count_(parameter_count), |
| outer_(translator->type_parameter_scope_), |
| translator_(translator) { |
| outer_parameter_count_ = 0; |
| if (outer_ != NULL) { |
| outer_parameter_count_ = |
| outer_->outer_parameter_count_ + outer_->parameter_count_; |
| } |
| translator_->type_parameter_scope_ = this; |
| } |
| ~TypeParameterScope() { translator_->type_parameter_scope_ = outer_; } |
| |
| TypeParameterScope* outer() const { return outer_; } |
| intptr_t parameter_count() const { return parameter_count_; } |
| intptr_t outer_parameter_count() const { return outer_parameter_count_; } |
| |
| private: |
| intptr_t parameter_count_; |
| intptr_t outer_parameter_count_; |
| TypeParameterScope* outer_; |
| TypeTranslator* translator_; |
| }; |
| |
| KernelReaderHelper* helper_; |
| ConstantReader* constant_reader_; |
| TranslationHelper& translation_helper_; |
| ActiveClass* const active_class_; |
| TypeParameterScope* type_parameter_scope_; |
| InferredTypeMetadataHelper inferred_type_metadata_helper_; |
| UnboxingInfoMetadataHelper unboxing_info_metadata_helper_; |
| Zone* zone_; |
| AbstractType& result_; |
| bool finalize_; |
| bool refers_to_derived_type_param_; |
| const bool apply_canonical_type_erasure_; |
| const bool in_constant_context_; |
| |
| friend class ScopeBuilder; |
| friend class KernelLoader; |
| |
| DISALLOW_COPY_AND_ASSIGN(TypeTranslator); |
| }; |
| |
| } // namespace kernel |
| } // namespace dart |
| |
| #endif // RUNTIME_VM_COMPILER_FRONTEND_KERNEL_TRANSLATION_HELPER_H_ |