// 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_KERNEL_BINARY_FLOWGRAPH_H_ #define RUNTIME_VM_KERNEL_BINARY_FLOWGRAPH_H_ #if !defined(DART_PRECOMPILED_RUNTIME) #include #include "vm/kernel.h" #include "vm/kernel_binary.h" #include "vm/kernel_to_il.h" #include "vm/object.h" namespace dart { namespace kernel { class StreamingDartTypeTranslator { public: StreamingDartTypeTranslator(StreamingFlowGraphBuilder* builder, bool finalize = false); // Can return a malformed type. AbstractType& BuildType(); // 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 dart::Class& receiver_class, intptr_t length); const Type& ReceiverType(const dart::Class& klass); private: // Can build a malformed type. void BuildTypeInternal(); void BuildInterfaceType(bool simple); void BuildFunctionType(bool simple); void BuildTypeParameterType(); class TypeParameterScope { public: TypeParameterScope(StreamingDartTypeTranslator* translator, intptr_t* parameters, intptr_t parameters_count) : parameters_(parameters), parameters_count_(parameters_count), outer_(translator->type_parameter_scope_), translator_(translator) { translator_->type_parameter_scope_ = this; } ~TypeParameterScope() { delete[] parameters_; translator_->type_parameter_scope_ = outer_; } TypeParameterScope* outer() const { return outer_; } intptr_t* parameters() const { return parameters_; } intptr_t parameters_count() const { return parameters_count_; } private: intptr_t* parameters_; intptr_t parameters_count_; TypeParameterScope* outer_; StreamingDartTypeTranslator* translator_; }; StreamingFlowGraphBuilder* builder_; TranslationHelper& translation_helper_; ActiveClass* active_class_; TypeParameterScope* type_parameter_scope_; Zone* zone_; AbstractType& result_; bool finalize_; }; class StreamingConstantEvaluator { public: explicit StreamingConstantEvaluator(StreamingFlowGraphBuilder* builder); virtual ~StreamingConstantEvaluator() {} Instance& 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); Object& EvaluateExpressionSafe(intptr_t offset); private: void EvaluateVariableGet(); void EvaluateVariableGet(uint8_t payload); void EvaluatePropertyGet(); void EvaluateStaticGet(); void EvaluateMethodInvocation(); void EvaluateStaticInvocation(); void EvaluateConstructorInvocationInternal(); void EvaluateNot(); void EvaluateLogicalExpression(); void EvaluateConditionalExpression(); void EvaluateStringConcatenation(); void EvaluateSymbolLiteral(); void EvaluateTypeLiteral(); void EvaluateListLiteralInternal(); void EvaluateMapLiteralInternal(); void EvaluateLet(); void EvaluateBigIntLiteral(); void EvaluateStringLiteral(); void EvaluateIntLiteral(uint8_t payload); void EvaluateIntLiteral(bool is_negative); void EvaluateDoubleLiteral(); void EvaluateBoolLiteral(bool value); void EvaluateNullLiteral(); 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); RawObject* EvaluateConstConstructorCall(const dart::Class& type_class, const TypeArguments& type_arguments, const Function& constructor, const Object& argument); const TypeArguments* TranslateTypeArguments(const Function& target, dart::Class* target_klass); void AssertBoolInCheckedMode() { if (isolate_->type_checks() && !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_; Script& script_; Instance& result_; }; class StreamingFlowGraphBuilder { public: StreamingFlowGraphBuilder(FlowGraphBuilder* flow_graph_builder, const uint8_t* buffer, intptr_t buffer_length) : flow_graph_builder_(flow_graph_builder), translation_helper_(flow_graph_builder->translation_helper_), zone_(flow_graph_builder->zone_), reader_(new Reader(buffer, buffer_length)), constant_evaluator_(this), type_translator_(this, /* finalize= */ true) {} Fragment BuildExpressionAt(intptr_t kernel_offset); Fragment BuildStatementAt(intptr_t kernel_offset); private: Fragment BuildExpression(TokenPosition* position = NULL); Fragment BuildStatement(); intptr_t ReaderOffset(); void SetOffset(intptr_t offset); void SkipBytes(intptr_t skip); bool ReadBool(); uint8_t ReadByte(); uint32_t ReadUInt(); uint32_t PeekUInt(); intptr_t ReadListLength(); StringIndex ReadStringReference(); NameIndex ReadCanonicalNameReference(); StringIndex ReadNameAsStringIndex(); const dart::String& ReadNameAsMethodName(); const dart::String& ReadNameAsGetterName(); const dart::String& ReadNameAsSetterName(); void SkipStringReference(); void SkipCanonicalNameReference(); void SkipDartType(); void SkipOptionalDartType(); void SkipInterfaceType(bool simple); void SkipFunctionType(bool simple); void SkipExpression(); void SkipStatement(); void SkipName(); void SkipArguments(); void SkipVariableDeclaration(); TokenPosition ReadPosition(bool record = true); Tag ReadTag(uint8_t* payload = NULL); Tag PeekTag(uint8_t* payload = NULL); word ReadFlags(); 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(); ParsedFunction* parsed_function(); TryFinallyBlock* try_finally_block(); SwitchBlock* switch_block(); BreakableBlock* breakable_block(); GrowableArray& yield_continuations(); Value* stack(); Value* Pop(); Tag PeekArgumentsFirstPositionalTag(); const TypeArguments& PeekArgumentsInstantiatedType(const dart::Class& klass); intptr_t PeekArgumentsCount(); intptr_t PeekArgumentsTypeCount(); void SkipArgumentsBeforeActualArguments(); LocalVariable* LookupVariable(intptr_t kernel_offset); LocalVariable* MakeTemporary(); Token::Kind MethodKind(const dart::String& name); dart::RawFunction* LookupMethodByMember(NameIndex target, const dart::String& method_name); 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 StaticCall(TokenPosition position, const Function& target, intptr_t argument_count); Fragment StaticCall(TokenPosition position, const Function& target, intptr_t argument_count, const Array& argument_names); Fragment InstanceCall(TokenPosition position, const dart::String& name, Token::Kind kind, intptr_t argument_count, intptr_t num_args_checked = 1); Fragment InstanceCall(TokenPosition position, const dart::String& name, Token::Kind kind, intptr_t argument_count, const Array& argument_names, intptr_t num_args_checked); Fragment ThrowException(TokenPosition position); Fragment BooleanNegate(); Fragment TranslateInstantiatedTypeArguments( const TypeArguments& type_arguments); Fragment StrictCompare(Token::Kind kind, bool number_check = false); Fragment AllocateObject(const dart::Class& klass, intptr_t argument_count); Fragment StoreLocal(TokenPosition position, LocalVariable* variable); Fragment StoreStaticField(TokenPosition position, const dart::Field& field); 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(); Fragment CloneContext(); 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); Fragment TryCatch(int try_handler_index); Fragment Drop(); Fragment NullConstant(); JoinEntryInstr* BuildJoinEntry(); JoinEntryInstr* BuildJoinEntry(intptr_t try_index); Fragment Goto(JoinEntryInstr* destination); Fragment BuildImplicitClosureCreation(const Function& target); Fragment CheckBooleanInCheckedMode(); Fragment CheckAssignableInCheckedMode(const dart::AbstractType& dst_type, const dart::String& dst_name); Fragment CheckVariableTypeInCheckedMode(intptr_t variable_kernel_position); Fragment CheckVariableTypeInCheckedMode(const AbstractType& dst_type, const dart::String& name_symbol); Fragment EnterScope(intptr_t kernel_offset, bool* new_context = NULL); Fragment ExitScope(intptr_t kernel_offset); Fragment TranslateCondition(bool* negate); const TypeArguments& BuildTypeArguments(); Fragment BuildArguments(Array* argument_names, intptr_t* 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 BuildDirectPropertyGet(TokenPosition* position); Fragment BuildDirectPropertySet(TokenPosition* position); Fragment BuildStaticGet(TokenPosition* position); Fragment BuildStaticSet(TokenPosition* position); Fragment BuildMethodInvocation(TokenPosition* position); Fragment BuildDirectMethodInvocation(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 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 BuildInvalidStatement(); Fragment BuildExpressionStatement(); Fragment BuildBlock(); Fragment BuildEmptyStatement(); 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(bool has_tag); FlowGraphBuilder* flow_graph_builder_; TranslationHelper& translation_helper_; Zone* zone_; Reader* reader_; StreamingConstantEvaluator constant_evaluator_; StreamingDartTypeTranslator type_translator_; friend class StreamingConstantEvaluator; friend class StreamingDartTypeTranslator; }; } // namespace kernel } // namespace dart #endif // !defined(DART_PRECOMPILED_RUNTIME) #endif // RUNTIME_VM_KERNEL_BINARY_FLOWGRAPH_H_