| // 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 <map> |
| |
| #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<YieldContinuation>& 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_ |