// Copyright (c) 2017, 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_BINARY_FLOWGRAPH_H_ #define RUNTIME_VM_COMPILER_FRONTEND_KERNEL_BINARY_FLOWGRAPH_H_ #if !defined(DART_PRECOMPILED_RUNTIME) #include #include "vm/compiler/frontend/kernel_to_il.h" #include "vm/kernel.h" #include "vm/kernel_binary.h" #include "vm/object.h" namespace dart { namespace kernel { class KernelReaderHelper; // 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, kBody, kEnd, }; enum AsyncMarker { 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(static_cast(field) + 1)); } void ReadUntilExcluding(Field field); void SetNext(Field field) { next_read_ = field; } void SetJustRead(Field field) { next_read_ = field + 1; } TokenPosition position_; TokenPosition end_position_; AsyncMarker async_marker_; AsyncMarker dart_async_marker_; intptr_t total_parameter_count_; intptr_t required_parameter_count_; private: KernelReaderHelper* helper_; intptr_t next_read_; }; class TypeParameterHelper { public: enum Field { kStart, // tag. kFlags, kAnnotations, 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(static_cast(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); } TokenPosition position_; uint8_t flags_; StringIndex name_index_; private: KernelReaderHelper* helper_; intptr_t next_read_; }; // 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 << 5, }; explicit VariableDeclarationHelper(KernelReaderHelper* helper) : helper_(helper), next_read_(kPosition) {} void ReadUntilIncluding(Field field) { ReadUntilExcluding(static_cast(static_cast(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 IsCovariant() { return (flags_ & kCovariant) != 0; } bool IsGenericCovariantImpl() { return (flags_ & kIsGenericCovariantImpl) != 0; } TokenPosition position_; TokenPosition equals_position_; uint8_t flags_; StringIndex name_index_; private: KernelReaderHelper* helper_; intptr_t next_read_; }; // 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. kCanonicalName, kSourceUriIndex, kPosition, kEndPosition, kFlags, kName, kAnnotations, kType, kInitializer, kEnd, }; enum Flag { kFinal = 1 << 0, kConst = 1 << 1, kStatic = 1 << 2, kIsCovariant = 1 << 5, kIsGenericCovariantImpl = 1 << 6, }; explicit FieldHelper(KernelReaderHelper* helper) : helper_(helper), next_read_(kStart), has_function_literal_initializer_(false) {} FieldHelper(KernelReaderHelper* helper, intptr_t offset); void ReadUntilIncluding(Field field) { ReadUntilExcluding(static_cast(static_cast(field) + 1)); } void ReadUntilExcluding(Field field, bool detect_function_literal_initializer = false); 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 FieldHasFunctionLiteralInitializer(TokenPosition* start, TokenPosition* end) { if (has_function_literal_initializer_) { *start = function_literal_start_; *end = function_literal_end_; } return has_function_literal_initializer_; } NameIndex canonical_name_; TokenPosition position_; TokenPosition end_position_; uint8_t flags_; intptr_t source_uri_index_; intptr_t annotation_count_; private: KernelReaderHelper* helper_; intptr_t next_read_; bool has_function_literal_initializer_; TokenPosition function_literal_start_; TokenPosition function_literal_end_; }; // 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, kPosition, kEndPosition, kKind, kFlags, kName, kAnnotations, kForwardingStubSuperTarget, kForwardingStubInterfaceTarget, kFunction, kEnd, }; enum Kind { kMethod, kGetter, kSetter, kOperator, kFactory, }; enum Flag { kStatic = 1 << 0, kAbstract = 1 << 1, kExternal = 1 << 2, kConst = 1 << 3, // Only for external const factories. kForwardingStub = 1 << 4, // TODO(29841): Remove this line after the issue is resolved. kRedirectingFactoryConstructor = 1 << 6, kNoSuchMethodForwarder = 1 << 7, }; explicit ProcedureHelper(KernelReaderHelper* helper) : helper_(helper), next_read_(kStart) {} void ReadUntilIncluding(Field field) { ReadUntilExcluding(static_cast(static_cast(field) + 1)); } void ReadUntilExcluding(Field field); void SetNext(Field field) { next_read_ = field; } void SetJustRead(Field field) { next_read_ = field + 1; } bool IsStatic() { return (flags_ & kStatic) != 0; } bool IsAbstract() { return (flags_ & kAbstract) != 0; } bool IsExternal() { return (flags_ & kExternal) != 0; } bool IsConst() { return (flags_ & kConst) != 0; } bool IsForwardingStub() { return (flags_ & kForwardingStub) != 0; } bool IsRedirectingFactoryConstructor() { return (flags_ & kRedirectingFactoryConstructor) != 0; } NameIndex canonical_name_; TokenPosition position_; TokenPosition end_position_; Kind kind_; uint8_t flags_; intptr_t source_uri_index_; intptr_t annotation_count_; // Only valid if the 'isForwardingStub' flag is set. NameIndex forwarding_stub_super_target_; private: KernelReaderHelper* helper_; intptr_t next_read_; }; // 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, 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(static_cast(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 position_; TokenPosition end_position_; uint8_t flags_; intptr_t source_uri_index_; intptr_t annotation_count_; private: KernelReaderHelper* helper_; intptr_t next_read_; }; // 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, kPosition, kEndPosition, kFlags, kNameIndex, kAnnotations, kTypeParameters, kSuperClass, kMixinType, kImplementedClasses, kFields, kConstructors, kProcedures, kClassIndex, kEnd, }; enum Flag { kIsAbstract = 1 << 2, kIsEnumClass = 1 << 3, kIsAnonymousMixin = 1 << 4, kIsEliminatedMixin = 1 << 5, }; explicit ClassHelper(KernelReaderHelper* helper) : helper_(helper), next_read_(kStart) {} void ReadUntilIncluding(Field field) { ReadUntilExcluding(static_cast(static_cast(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; } bool is_enum_class() const { return flags_ & Flag::kIsEnumClass; } bool is_transformed_mixin_application() const { return flags_ & Flag::kIsEliminatedMixin; } NameIndex canonical_name_; TokenPosition position_; TokenPosition end_position_; StringIndex name_index_; intptr_t source_uri_index_; intptr_t annotation_count_; intptr_t procedure_count_; uint8_t flags_; private: KernelReaderHelper* helper_; intptr_t next_read_; }; // 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, kCanonicalName, kName, kSourceUriIndex, kAnnotations, kDependencies, kAdditionalExports, kParts, kTypedefs, kClasses, kToplevelField, kToplevelProcedures, kLibraryIndex, kEnd, }; enum Flag { kExternal = 1, }; explicit LibraryHelper(KernelReaderHelper* helper) : helper_(helper), next_read_(kFlags) {} void ReadUntilIncluding(Field field) { ReadUntilExcluding(static_cast(static_cast(field) + 1)); } void ReadUntilExcluding(Field field); void SetNext(Field field) { next_read_ = field; } void SetJustRead(Field field) { next_read_ = field + 1; } bool IsExternal() const { return (flags_ & kExternal) != 0; } uint8_t flags_; NameIndex canonical_name_; StringIndex name_index_; intptr_t source_uri_index_; intptr_t class_count_; intptr_t procedure_count_; private: KernelReaderHelper* helper_; intptr_t next_read_; }; 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(static_cast(field) + 1)); } void ReadUntilExcluding(Field field); uint8_t flags_; StringIndex name_index_; NameIndex target_library_canonical_name_; private: KernelReaderHelper* helper_; intptr_t next_read_; }; // Base class for helpers accessing metadata of a certain kind. // Assumes that metadata is accessed in linear order. class MetadataHelper { public: explicit MetadataHelper(StreamingFlowGraphBuilder* builder); void SetMetadataMappings(intptr_t mappings_offset, intptr_t mappings_num); 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); StreamingFlowGraphBuilder* builder_; TranslationHelper& translation_helper_; private: intptr_t mappings_offset_; intptr_t mappings_num_; intptr_t last_node_offset_; intptr_t last_mapping_index_; }; 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(StreamingFlowGraphBuilder* builder) : MetadataHelper(builder) {} 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); }; struct InferredTypeMetadata { InferredTypeMetadata(intptr_t cid_, bool nullable_) : cid(cid_), nullable(nullable_) {} const intptr_t cid; const bool nullable; bool IsTrivial() const { return (cid == kDynamicCid) && nullable; } }; // 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(StreamingFlowGraphBuilder* builder) : MetadataHelper(builder) {} InferredTypeMetadata GetInferredType(intptr_t node_offset); }; struct ProcedureAttributesMetadata { ProcedureAttributesMetadata(bool has_dynamic_invocations = true, bool has_non_this_uses = true, bool has_tearoff_uses = true) : has_dynamic_invocations(has_dynamic_invocations), has_non_this_uses(has_non_this_uses), has_tearoff_uses(has_tearoff_uses) {} bool has_dynamic_invocations; bool has_non_this_uses; bool has_tearoff_uses; }; // 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(StreamingFlowGraphBuilder* builder) : MetadataHelper(builder) {} ProcedureAttributesMetadata GetProcedureAttributes(intptr_t node_offset); private: bool ReadMetadata(intptr_t node_offset, ProcedureAttributesMetadata* metadata); }; // Helper class which provides access to bytecode metadata. class BytecodeMetadataHelper : public MetadataHelper { public: static const char* tag() { return "vm.bytecode"; } explicit BytecodeMetadataHelper(StreamingFlowGraphBuilder* builder) : MetadataHelper(builder) {} #if defined(DART_USE_INTERPRETER) void ReadMetadata(const Function& function); private: // Returns the index of the last read pool entry. intptr_t ReadPoolEntries(const Function& function, const Function& inner_function, const ObjectPool& pool, intptr_t from_index); RawCode* ReadBytecode(const ObjectPool& pool); void ReadExceptionsTable(const Code& bytecode); #endif }; class StreamingDartTypeTranslator { public: StreamingDartTypeTranslator(StreamingFlowGraphBuilder* builder, bool finalize = false); // Can return a malformed type. AbstractType& BuildType(); // Can return a malformed type. AbstractType& BuildTypeWithoutFinalization(); // Is guaranteed to be not malformed. AbstractType& BuildVariableType(); // Will return `TypeArguments::null()` in case any of the arguments are // malformed. const TypeArguments& BuildTypeArguments(intptr_t length); // Will return `TypeArguments::null()` in case any of the arguments are // malformed. const TypeArguments& BuildInstantiatedTypeArguments( const Class& receiver_class, intptr_t length); const Type& ReceiverType(const Class& klass); private: // Can build a malformed type. void BuildTypeInternal(bool invalid_as_dynamic = false); void BuildInterfaceType(bool simple); void BuildFunctionType(bool simple); void BuildTypeParameterType(); class TypeParameterScope { public: TypeParameterScope(StreamingDartTypeTranslator* 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_; StreamingDartTypeTranslator* translator_; }; StreamingFlowGraphBuilder* builder_; TranslationHelper& translation_helper_; ActiveClass* const active_class_; TypeParameterScope* type_parameter_scope_; Zone* zone_; AbstractType& result_; bool finalize_; friend class StreamingScopeBuilder; friend class KernelLoader; }; class StreamingScopeBuilder { public: explicit StreamingScopeBuilder(ParsedFunction* parsed_function); virtual ~StreamingScopeBuilder(); ScopeBuildingResult* BuildScopes(); private: void VisitField(); void VisitProcedure(); void VisitConstructor(); void VisitFunctionNode(); void VisitNode(); void VisitInitializer(); void VisitExpression(); void VisitStatement(); void VisitArguments(); void VisitVariableDeclaration(); void VisitDartType(); void VisitInterfaceType(bool simple); void VisitFunctionType(bool simple); void VisitTypeParameterType(); void HandleLocalFunction(intptr_t parent_kernel_offset); AbstractType& BuildAndVisitVariableType(); void EnterScope(intptr_t kernel_offset); void ExitScope(TokenPosition start_position, TokenPosition end_position); virtual void ReportUnexpectedTag(const char* variant, Tag tag); // This enum controls which parameters would be marked as requring type // check on the callee side. enum ParameterTypeCheckMode { // All parameters will be checked. kTypeCheckAllParameters, // Only parameters marked as covariant or generic-covariant-impl will be // checked. kTypeCheckForNonDynamicallyInvokedMethod, // Only parameters *not* marked as covariant or generic-covariant-impl will // be checked. The rest would be checked in the method itself. // Inverse of kTypeCheckOnlyGenericCovariantImplParameters. kTypeCheckForTearOffOfNonDynamicallyInvokedMethod, // No parameters will be checked. kTypeCheckForStaticFunction, }; // This assumes that the reader is at a FunctionNode, // about to read the positional parameters. void AddPositionalAndNamedParameters( intptr_t pos, ParameterTypeCheckMode type_check_mode, const ProcedureAttributesMetadata& attrs); // This assumes that the reader is at a FunctionNode, // about to read a parameter (i.e. VariableDeclaration). void AddVariableDeclarationParameter( intptr_t pos, ParameterTypeCheckMode type_check_mode, const ProcedureAttributesMetadata& attrs); LocalVariable* MakeVariable(TokenPosition declaration_pos, TokenPosition token_pos, const String& name, const AbstractType& type, const InferredTypeMetadata* param_type_md = NULL); void AddExceptionVariable(GrowableArray* variables, const char* prefix, intptr_t nesting_depth); void FinalizeExceptionVariable(GrowableArray* variables, GrowableArray* raw_variables, const String& symbol, intptr_t nesting_depth); void AddTryVariables(); void AddCatchVariables(); void FinalizeCatchVariables(); void AddIteratorVariable(); void AddSwitchVariable(); // Record an assignment or reference to a variable. If the occurrence is // in a nested function, ensure that the variable is handled properly as a // captured variable. void LookupVariable(intptr_t declaration_binary_offset); const String& GenerateName(const char* prefix, intptr_t suffix); void HandleSpecialLoad(LocalVariable** variable, const String& symbol); void LookupCapturedVariableByName(LocalVariable** variable, const String& name); struct DepthState { explicit DepthState(intptr_t function) : loop_(0), function_(function), try_(0), catch_(0), finally_(0), for_in_(0) {} intptr_t loop_; intptr_t function_; intptr_t try_; intptr_t catch_; intptr_t finally_; intptr_t for_in_; }; ScopeBuildingResult* result_; ParsedFunction* parsed_function_; ActiveClass active_class_; TranslationHelper translation_helper_; Zone* zone_; FunctionNodeHelper::AsyncMarker current_function_async_marker_; LocalScope* current_function_scope_; LocalScope* scope_; DepthState depth_; intptr_t name_index_; bool needs_expr_temp_; TokenPosition first_body_token_position_; StreamingFlowGraphBuilder* builder_; StreamingDartTypeTranslator type_translator_; }; // There are several cases when we are compiling constant expressions: // // * constant field initializers: // const FieldName = ; // // * constant expressions: // const [, ...] // const { : , ...} // const Constructor(, ...) // // * constant default parameters: // f(a, [b = ]) // f(a, {b: }) // // * constant values to compare in a [SwitchCase] // case : // // In all cases `` must be recursively evaluated and canonicalized at // compile-time. class StreamingConstantEvaluator { public: explicit StreamingConstantEvaluator(StreamingFlowGraphBuilder* builder); virtual ~StreamingConstantEvaluator() {} bool IsCached(intptr_t offset); RawInstance* EvaluateExpression(intptr_t offset, bool reset_position = true); Instance& EvaluateListLiteral(intptr_t offset, bool reset_position = true); Instance& EvaluateMapLiteral(intptr_t offset, bool reset_position = true); Instance& EvaluateConstructorInvocation(intptr_t offset, bool reset_position = true); RawObject* EvaluateExpressionSafe(intptr_t offset); private: bool IsAllowedToEvaluate(); void EvaluateAsExpression(); void EvaluateVariableGet(); void EvaluateVariableGet(uint8_t payload); void EvaluatePropertyGet(); void EvaluateDirectPropertyGet(); void EvaluateStaticGet(); void EvaluateMethodInvocation(); void EvaluateDirectMethodInvocation(); void EvaluateSuperMethodInvocation(); void EvaluateStaticInvocation(); void EvaluateConstructorInvocationInternal(); void EvaluateNot(); void EvaluateLogicalExpression(); void EvaluateConditionalExpression(); void EvaluateStringConcatenation(); void EvaluateSymbolLiteral(); void EvaluateTypeLiteral(); void EvaluateListLiteralInternal(); void EvaluateMapLiteralInternal(); void EvaluateLet(); void EvaluatePartialTearoffInstantiation(); void EvaluateBigIntLiteral(); void EvaluateStringLiteral(); void EvaluateIntLiteral(uint8_t payload); void EvaluateIntLiteral(bool is_negative); void EvaluateDoubleLiteral(); void EvaluateBoolLiteral(bool value); void EvaluateNullLiteral(); void EvaluateConstantExpression(); void EvaluateGetStringLength(intptr_t expression_offset, TokenPosition position); const Object& RunFunction(const Function& function, intptr_t argument_count, const Instance* receiver, const TypeArguments* type_args); const Object& RunFunction(const Function& function, const Array& arguments, const Array& names); const Object& RunMethodCall(const Function& function, const Instance* receiver); RawObject* EvaluateConstConstructorCall(const Class& type_class, const TypeArguments& type_arguments, const Function& constructor, const Object& argument); const TypeArguments* TranslateTypeArguments(const Function& target, Class* target_klass); void AssertBool() { if (!result_.IsBool()) { translation_helper_.ReportError("Expected boolean expression."); } } bool EvaluateBooleanExpressionHere(); bool GetCachedConstant(intptr_t kernel_offset, Instance* value); void CacheConstantValue(intptr_t kernel_offset, const Instance& value); StreamingFlowGraphBuilder* builder_; Isolate* isolate_; Zone* zone_; TranslationHelper& translation_helper_; StreamingDartTypeTranslator& type_translator_; const Script& script_; Instance& result_; }; class KernelReaderHelper { public: KernelReaderHelper(Zone* zone, TranslationHelper* translation_helper, const Script& script, const TypedData& 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 uint8_t* data_buffer, intptr_t buffer_length, intptr_t data_program_offset) : zone_(zone), translation_helper_(*translation_helper), reader_(data_buffer, buffer_length), script_(Script::Handle(zone_)), data_program_offset_(data_program_offset) {} virtual ~KernelReaderHelper() {} void SetOffset(intptr_t offset); intptr_t ReadListLength(); virtual void ReportUnexpectedTag(const char* variant, Tag tag); protected: const Script& script() const { return script_; } virtual void set_current_script_id(intptr_t id) { // Do nothing by default. This is overridden in StreamingFlowGraphBuilder. USE(id); } virtual void RecordYieldPosition(TokenPosition position) { // Do nothing by default. This is overridden in StreamingFlowGraphBuilder. USE(position); } virtual void RecordTokenPosition(TokenPosition position) { // Do nothing by default. This is overridden in StreamingFlowGraphBuilder. USE(position); } intptr_t ReaderOffset() 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(); StringIndex ReadNameAsStringIndex(); const String& ReadNameAsMethodName(); const String& ReadNameAsGetterName(); const String& ReadNameAsSetterName(); const String& ReadNameAsFieldName(); void SkipFlags(); void SkipStringReference(); void SkipConstantReference(); void SkipCanonicalNameReference(); void SkipDartType(); void SkipOptionalDartType(); void SkipInterfaceType(bool simple); void SkipFunctionType(bool simple); void SkipStatementList(); void SkipListOfExpressions(); void SkipListOfDartTypes(); void SkipListOfStrings(); void SkipListOfVariableDeclarations(); 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(bool record = true); Tag ReadTag(uint8_t* payload = NULL); Tag PeekTag(uint8_t* payload = NULL); uint8_t ReadFlags() { return reader_.ReadFlags(); } 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 ConstantHelper; friend class ConstructorHelper; friend class DirectCallMetadataHelper; friend class ProcedureAttributesMetadataHelper; friend class FieldHelper; friend class FunctionNodeHelper; friend class InferredTypeMetadataHelper; friend class KernelLoader; friend class LibraryDependencyHelper; friend class LibraryHelper; friend class MetadataHelper; friend class ProcedureHelper; friend class SimpleExpressionConverter; friend class StreamingConstantEvaluator; friend class StreamingDartTypeTranslator; friend class StreamingScopeBuilder; friend class VariableDeclarationHelper; friend class TypeParameterHelper; }; class KernelFingerprintHelper : public KernelReaderHelper { public: KernelFingerprintHelper(Zone* zone, TranslationHelper* translation_helper, const Script& script, const TypedData& 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 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_; }; class StreamingFlowGraphBuilder : public KernelReaderHelper { public: StreamingFlowGraphBuilder(FlowGraphBuilder* flow_graph_builder, const TypedData& data, intptr_t data_program_offset) : KernelReaderHelper( flow_graph_builder->zone_, &flow_graph_builder->translation_helper_, Script::Handle( flow_graph_builder->zone_, flow_graph_builder->parsed_function_->function().script()), data, data_program_offset), flow_graph_builder_(flow_graph_builder), active_class_(&flow_graph_builder->active_class_), constant_evaluator_(this), type_translator_(this, /* finalize= */ true), current_script_id_(-1), record_for_script_id_(-1), record_token_positions_into_(NULL), record_yield_positions_into_(NULL), direct_call_metadata_helper_(this), inferred_type_metadata_helper_(this), procedure_attributes_metadata_helper_(this), bytecode_metadata_helper_(this), metadata_scanned_(false) {} StreamingFlowGraphBuilder(TranslationHelper* translation_helper, Zone* zone, const uint8_t* data_buffer, intptr_t buffer_length, intptr_t data_program_offset, ActiveClass* active_class) : KernelReaderHelper(zone, translation_helper, data_buffer, buffer_length, data_program_offset), flow_graph_builder_(NULL), active_class_(active_class), constant_evaluator_(this), type_translator_(this, /* finalize= */ true), current_script_id_(-1), record_for_script_id_(-1), record_token_positions_into_(NULL), record_yield_positions_into_(NULL), direct_call_metadata_helper_(this), inferred_type_metadata_helper_(this), procedure_attributes_metadata_helper_(this), bytecode_metadata_helper_(this), metadata_scanned_(false) {} StreamingFlowGraphBuilder(TranslationHelper* translation_helper, const Script& script, Zone* zone, const TypedData& data, intptr_t data_program_offset, ActiveClass* active_class) : KernelReaderHelper(zone, translation_helper, script, data, data_program_offset), flow_graph_builder_(NULL), active_class_(active_class), constant_evaluator_(this), type_translator_(this, /* finalize= */ true), current_script_id_(-1), record_for_script_id_(-1), record_token_positions_into_(NULL), record_yield_positions_into_(NULL), direct_call_metadata_helper_(this), inferred_type_metadata_helper_(this), procedure_attributes_metadata_helper_(this), bytecode_metadata_helper_(this), metadata_scanned_(false) {} virtual ~StreamingFlowGraphBuilder() {} FlowGraph* BuildGraph(intptr_t kernel_offset); void ReportUnexpectedTag(const char* variant, Tag tag) override; Fragment BuildStatementAt(intptr_t kernel_offset); RawObject* BuildParameterDescriptor(intptr_t kernel_offset); RawObject* EvaluateMetadata(intptr_t kernel_offset); void CollectTokenPositionsFor( intptr_t script_index, intptr_t initial_script_index, intptr_t kernel_offset, GrowableArray* record_token_positions_in, GrowableArray* record_yield_positions_in); intptr_t SourceTableSize(); String& SourceTableUriFor(intptr_t index); String& GetSourceFor(intptr_t index); RawTypedData* GetLineStartsFor(intptr_t index); // If a 'ParsedFunction' is provided for 'set_forwarding_stub', this method // will attach the forwarding stub target reference to the parsed function if // it crosses a procedure node for a concrete forwarding stub. void ReadUntilFunctionNode(ParsedFunction* set_forwarding_stub = NULL); enum DispatchCategory { Interface, ViaThis, Closure, DynamicDispatch }; private: void LoadAndSetupTypeParameters(ActiveClass* active_class, const Object& set_on, intptr_t type_parameter_count, const Function& parameterized_function); void DiscoverEnclosingElements(Zone* zone, const Function& function, Function* outermost_function); StringIndex GetNameFromVariableDeclaration(intptr_t kernel_offset, const Function& function); bool optimizing(); FlowGraph* BuildGraphOfFieldInitializer(); FlowGraph* BuildGraphOfFieldAccessor(LocalVariable* setter_value); void SetupDefaultParameterValues(); Fragment BuildFieldInitializer(NameIndex canonical_name); Fragment BuildInitializers(const Class& parent_class); FlowGraph* BuildGraphOfImplicitClosureFunction(const Function& function); FlowGraph* BuildGraphOfFunction(bool constructor); FlowGraph* BuildGraphOfNoSuchMethodForwarder( const Function& function, bool is_implicit_closure_function, bool throw_no_such_method_error = false); intptr_t GetOffsetForSourceInfo(intptr_t index); Fragment BuildExpression(TokenPosition* position = NULL); Fragment BuildStatement(); void loop_depth_inc(); void loop_depth_dec(); intptr_t for_in_depth(); void for_in_depth_inc(); void for_in_depth_dec(); void catch_depth_inc(); void catch_depth_dec(); void try_depth_inc(); void try_depth_dec(); intptr_t CurrentTryIndex(); intptr_t AllocateTryIndex(); LocalVariable* CurrentException(); LocalVariable* CurrentStackTrace(); CatchBlock* catch_block(); ActiveClass* active_class(); ScopeBuildingResult* scopes(); void set_scopes(ScopeBuildingResult* scope); ParsedFunction* parsed_function(); TryFinallyBlock* try_finally_block(); SwitchBlock* switch_block(); BreakableBlock* breakable_block(); GrowableArray& yield_continuations(); Value* stack(); void Push(Definition* definition); Value* Pop(); Class& GetSuperOrDie(); Tag PeekArgumentsFirstPositionalTag(); const TypeArguments& PeekArgumentsInstantiatedType(const Class& klass); intptr_t PeekArgumentsCount(); // See BaseFlowGraphBuilder::MakeTemporary. LocalVariable* MakeTemporary(); LocalVariable* LookupVariable(intptr_t kernel_offset); RawFunction* LookupMethodByMember(NameIndex target, const String& method_name); Function& FindMatchingFunctionAnyArgs(const Class& klass, const String& name); Function& FindMatchingFunction(const Class& klass, const String& name, int type_args_len, int argument_count, const Array& argument_names); bool NeedsDebugStepCheck(const Function& function, TokenPosition position); bool NeedsDebugStepCheck(Value* value, TokenPosition position); void InlineBailout(const char* reason); Fragment DebugStepCheck(TokenPosition position); Fragment LoadLocal(LocalVariable* variable); Fragment Return(TokenPosition position); Fragment PushArgument(); Fragment EvaluateAssertion(); Fragment RethrowException(TokenPosition position, int catch_try_index); Fragment ThrowNoSuchMethodError(); Fragment Constant(const Object& value); Fragment IntConstant(int64_t value); Fragment LoadStaticField(); Fragment CheckNull(TokenPosition position, LocalVariable* receiver, const String& function_name); Fragment StaticCall(TokenPosition position, const Function& target, intptr_t argument_count, ICData::RebindRule rebind_rule); Fragment StaticCall(TokenPosition position, const Function& target, intptr_t argument_count, const Array& argument_names, ICData::RebindRule rebind_rule, const InferredTypeMetadata* result_type = NULL, intptr_t type_args_len = 0); Fragment InstanceCall(TokenPosition position, const String& name, Token::Kind kind, intptr_t argument_count, intptr_t checked_argument_count = 1); Fragment InstanceCall(TokenPosition position, const String& name, Token::Kind kind, intptr_t type_args_len, intptr_t argument_count, const Array& argument_names, intptr_t checked_argument_count, const Function& interface_target, const InferredTypeMetadata* result_type = NULL); enum TypeChecksToBuild { kDefaultTypeChecks, kTypeChecksForNoDynamicInvocationsTearOff }; // Does not move the cursor. Fragment BuildDefaultTypeHandling(const Function& function, intptr_t type_parameters_offset); Fragment BuildArgumentTypeChecks(TypeChecksToBuild mode = kDefaultTypeChecks); Fragment ThrowException(TokenPosition position); Fragment BooleanNegate(); Fragment TranslateInstantiatedTypeArguments( const TypeArguments& type_arguments); Fragment StrictCompare(Token::Kind kind, bool number_check = false); Fragment AllocateObject(TokenPosition position, const Class& klass, intptr_t argument_count); Fragment AllocateObject(const Class& klass, const Function& closure_function); Fragment AllocateContext(intptr_t size); Fragment LoadField(intptr_t offset); Fragment StoreLocal(TokenPosition position, LocalVariable* variable); Fragment StoreStaticField(TokenPosition position, const Field& field); Fragment StoreInstanceField(TokenPosition position, intptr_t offset); Fragment StringInterpolate(TokenPosition position); Fragment StringInterpolateSingle(TokenPosition position); Fragment ThrowTypeError(); Fragment LoadInstantiatorTypeArguments(); Fragment LoadFunctionTypeArguments(); Fragment InstantiateType(const AbstractType& type); Fragment CreateArray(); Fragment StoreIndexed(intptr_t class_id); Fragment CheckStackOverflow(TokenPosition position); Fragment CloneContext(intptr_t num_context_variables); Fragment TranslateFinallyFinalizers(TryFinallyBlock* outer_finally, intptr_t target_context_depth); Fragment BranchIfTrue(TargetEntryInstr** then_entry, TargetEntryInstr** otherwise_entry, bool negate); Fragment BranchIfEqual(TargetEntryInstr** then_entry, TargetEntryInstr** otherwise_entry, bool negate); Fragment BranchIfNull(TargetEntryInstr** then_entry, TargetEntryInstr** otherwise_entry, bool negate = false); Fragment CatchBlockEntry(const Array& handler_types, intptr_t handler_index, bool needs_stacktrace, bool is_synthesized); Fragment TryCatch(int try_handler_index); Fragment Drop(); // Drop given number of temps from the stack but preserve top of the stack. Fragment DropTempsPreserveTop(intptr_t num_temps_to_drop); Fragment MakeTemp(); Fragment NullConstant(); JoinEntryInstr* BuildJoinEntry(); JoinEntryInstr* BuildJoinEntry(intptr_t try_index); Fragment Goto(JoinEntryInstr* destination); Fragment BuildImplicitClosureCreation(const Function& target); Fragment CheckBoolean(); Fragment CheckAssignableInCheckedMode(const AbstractType& dst_type, const String& dst_name); Fragment CheckArgumentType(LocalVariable* variable, const AbstractType& type); Fragment CheckTypeArgumentBound(const AbstractType& parameter, const AbstractType& bound, const String& dst_name); Fragment CheckVariableTypeInCheckedMode(intptr_t variable_kernel_position); Fragment CheckVariableTypeInCheckedMode(const AbstractType& dst_type, const String& name_symbol); Fragment EnterScope(intptr_t kernel_offset, intptr_t* num_context_variables = NULL); Fragment ExitScope(intptr_t kernel_offset); Fragment TranslateCondition(bool* negate); const TypeArguments& BuildTypeArguments(); Fragment BuildArguments(Array* argument_names, intptr_t* argument_count, intptr_t* positional_argument_count, bool skip_push_arguments = false, bool do_drop = false); Fragment BuildArgumentsFromActualArguments(Array* argument_names, bool skip_push_arguments = false, bool do_drop = false); Fragment BuildInvalidExpression(TokenPosition* position); Fragment BuildVariableGet(TokenPosition* position); Fragment BuildVariableGet(uint8_t payload, TokenPosition* position); Fragment BuildVariableSet(TokenPosition* position); Fragment BuildVariableSet(uint8_t payload, TokenPosition* position); Fragment BuildPropertyGet(TokenPosition* position); Fragment BuildPropertySet(TokenPosition* position); Fragment BuildAllocateInvocationMirrorCall(TokenPosition position, const String& name, intptr_t num_type_arguments, intptr_t num_arguments, const Array& argument_names, LocalVariable* actuals_array, Fragment build_rest_of_actuals); Fragment BuildSuperPropertyGet(TokenPosition* position); Fragment BuildSuperPropertySet(TokenPosition* position); Fragment BuildDirectPropertyGet(TokenPosition* position); Fragment BuildDirectPropertySet(TokenPosition* position); Fragment BuildStaticGet(TokenPosition* position); Fragment BuildStaticSet(TokenPosition* position); Fragment BuildMethodInvocation(TokenPosition* position); Fragment BuildDirectMethodInvocation(TokenPosition* position); Fragment BuildSuperMethodInvocation(TokenPosition* position); Fragment BuildStaticInvocation(bool is_const, TokenPosition* position); Fragment BuildConstructorInvocation(bool is_const, TokenPosition* position); Fragment BuildNot(TokenPosition* position); Fragment BuildLogicalExpression(TokenPosition* position); Fragment BuildConditionalExpression(TokenPosition* position); Fragment BuildStringConcatenation(TokenPosition* position); Fragment BuildIsExpression(TokenPosition* position); Fragment BuildAsExpression(TokenPosition* position); Fragment BuildSymbolLiteral(TokenPosition* position); Fragment BuildTypeLiteral(TokenPosition* position); Fragment BuildThisExpression(TokenPosition* position); Fragment BuildRethrow(TokenPosition* position); Fragment BuildThrow(TokenPosition* position); Fragment BuildListLiteral(bool is_const, TokenPosition* position); Fragment BuildMapLiteral(bool is_const, TokenPosition* position); Fragment BuildFunctionExpression(); Fragment BuildLet(TokenPosition* position); Fragment BuildBigIntLiteral(TokenPosition* position); Fragment BuildStringLiteral(TokenPosition* position); Fragment BuildIntLiteral(uint8_t payload, TokenPosition* position); Fragment BuildIntLiteral(bool is_negative, TokenPosition* position); Fragment BuildDoubleLiteral(TokenPosition* position); Fragment BuildBoolLiteral(bool value, TokenPosition* position); Fragment BuildNullLiteral(TokenPosition* position); Fragment BuildFutureNullValue(TokenPosition* position); Fragment BuildConstantExpression(TokenPosition* position); Fragment BuildPartialTearoffInstantiation(TokenPosition* position); Fragment BuildExpressionStatement(); Fragment BuildBlock(); Fragment BuildEmptyStatement(); Fragment BuildAssertBlock(); Fragment BuildAssertStatement(); Fragment BuildLabeledStatement(); Fragment BuildBreakStatement(); Fragment BuildWhileStatement(); Fragment BuildDoStatement(); Fragment BuildForStatement(); Fragment BuildForInStatement(bool async); Fragment BuildSwitchStatement(); Fragment BuildContinueSwitchStatement(); Fragment BuildIfStatement(); Fragment BuildReturnStatement(); Fragment BuildTryCatch(); Fragment BuildTryFinally(); Fragment BuildYieldStatement(); Fragment BuildVariableDeclaration(); Fragment BuildFunctionDeclaration(); Fragment BuildFunctionNode(TokenPosition parent_position, StringIndex name_index); void SetupFunctionParameters(ActiveClass* active_class, const Class& klass, const Function& function, bool is_method, bool is_closure, FunctionNodeHelper* function_node_helper); void set_current_script_id(intptr_t id) override { current_script_id_ = id; } void RecordTokenPosition(TokenPosition position) override; void RecordYieldPosition(TokenPosition position) override; // Scan through metadata mappings section and cache offsets for recognized // metadata kinds. void EnsureMetadataIsScanned(); FlowGraphBuilder* flow_graph_builder_; ActiveClass* const active_class_; StreamingConstantEvaluator constant_evaluator_; StreamingDartTypeTranslator type_translator_; intptr_t current_script_id_; intptr_t record_for_script_id_; GrowableArray* record_token_positions_into_; GrowableArray* record_yield_positions_into_; DirectCallMetadataHelper direct_call_metadata_helper_; InferredTypeMetadataHelper inferred_type_metadata_helper_; ProcedureAttributesMetadataHelper procedure_attributes_metadata_helper_; BytecodeMetadataHelper bytecode_metadata_helper_; bool metadata_scanned_; friend class ClassHelper; friend class ConstantHelper; friend class ConstructorHelper; friend class DirectCallMetadataHelper; friend class ProcedureAttributesMetadataHelper; friend class BytecodeMetadataHelper; friend class FieldHelper; friend class FunctionNodeHelper; friend class InferredTypeMetadataHelper; friend class KernelLoader; friend class KernelReaderHelper; friend class LibraryDependencyHelper; friend class LibraryHelper; friend class MetadataHelper; friend class ProcedureHelper; friend class SimpleExpressionConverter; friend class StreamingConstantEvaluator; friend class StreamingDartTypeTranslator; friend class StreamingScopeBuilder; friend class VariableDeclarationHelper; friend class TypeParameterHelper; }; class AlternativeScriptScope { public: AlternativeScriptScope(TranslationHelper* helper, const Script& new_script, const Script& old_script) : helper_(helper), old_script_(old_script) { helper_->Reset(); helper_->InitFromScript(new_script); } ~AlternativeScriptScope() { helper_->Reset(); helper_->InitFromScript(old_script_); } TranslationHelper* helper_; const Script& old_script_; }; // A helper class that saves the current reader position, goes to another reader // position, and upon destruction, resets to the original reader position. class AlternativeReadingScope { public: AlternativeReadingScope(Reader* reader, intptr_t new_position) : reader_(reader), saved_size_(reader_->size()), saved_raw_buffer_(reader_->raw_buffer()), saved_typed_data_(reader_->typed_data()), saved_offset_(reader_->offset()) { reader_->set_offset(new_position); } AlternativeReadingScope(Reader* reader, const TypedData* new_typed_data, intptr_t new_position) : reader_(reader), saved_size_(reader_->size()), saved_raw_buffer_(reader_->raw_buffer()), saved_typed_data_(reader_->typed_data()), saved_offset_(reader_->offset()) { reader_->set_raw_buffer(NULL); reader_->set_typed_data(new_typed_data); reader_->set_size(new_typed_data->Length()); reader_->set_offset(new_position); } explicit AlternativeReadingScope(Reader* reader) : reader_(reader), saved_size_(reader_->size()), saved_raw_buffer_(reader_->raw_buffer()), saved_typed_data_(reader_->typed_data()), saved_offset_(reader_->offset()) {} ~AlternativeReadingScope() { reader_->set_raw_buffer(saved_raw_buffer_); reader_->set_typed_data(saved_typed_data_); reader_->set_size(saved_size_); reader_->set_offset(saved_offset_); } intptr_t saved_offset() { return saved_offset_; } private: Reader* reader_; intptr_t saved_size_; const uint8_t* saved_raw_buffer_; const TypedData* saved_typed_data_; intptr_t saved_offset_; }; // Helper class that reads a kernel Constant from binary. class ConstantHelper { public: ConstantHelper(ActiveClass* active_class, StreamingFlowGraphBuilder* builder, StreamingDartTypeTranslator* type_translator, TranslationHelper* translation_helper, Zone* zone, NameIndex skip_vmservice_library) : skip_vmservice_library_(skip_vmservice_library), active_class_(active_class), builder_(*builder), type_translator_(*type_translator), const_evaluator_(&builder_), translation_helper_(*translation_helper), zone_(zone), temp_type_(AbstractType::Handle(zone)), temp_type_arguments_(TypeArguments::Handle(zone)), temp_type_arguments2_(TypeArguments::Handle(zone)), temp_type_arguments3_(TypeArguments::Handle(zone)), temp_object_(Object::Handle(zone)), temp_array_(Array::Handle(zone)), temp_instance_(Instance::Handle(zone)), temp_field_(Field::Handle(zone)), temp_class_(Class::Handle(zone)), temp_function_(Function::Handle(zone)), temp_closure_(Closure::Handle(zone)), temp_context_(Context::Handle(zone)), temp_integer_(Integer::Handle(zone)) {} // Reads the constant table from the binary. // // This method assumes the Reader is positioned already at the constant table // and an active class scope is setup. const Array& ReadConstantTable(); private: void InstantiateTypeArguments(const Class& receiver_class, TypeArguments* type_arguments); // If [index] has `dart:vm_service` as a parent and we are skipping the VM // service library, this method returns `true`, otherwise `false`. bool ShouldSkipConstant(NameIndex index); NameIndex skip_vmservice_library_; ActiveClass* const active_class_; StreamingFlowGraphBuilder& builder_; StreamingDartTypeTranslator& type_translator_; StreamingConstantEvaluator const_evaluator_; TranslationHelper translation_helper_; Zone* zone_; AbstractType& temp_type_; TypeArguments& temp_type_arguments_; TypeArguments& temp_type_arguments2_; TypeArguments& temp_type_arguments3_; Object& temp_object_; Array& temp_array_; Instance& temp_instance_; Field& temp_field_; Class& temp_class_; Function& temp_function_; Closure& temp_closure_; Context& temp_context_; Integer& temp_integer_; }; } // namespace kernel } // namespace dart #endif // !defined(DART_PRECOMPILED_RUNTIME) #endif // RUNTIME_VM_COMPILER_FRONTEND_KERNEL_BINARY_FLOWGRAPH_H_