Index: runtime/vm/kernel_to_il.h |
diff --git a/runtime/vm/kernel_to_il.h b/runtime/vm/kernel_to_il.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ccf4801a81e0055ec34d0ec86104be8098d94c57 |
--- /dev/null |
+++ b/runtime/vm/kernel_to_il.h |
@@ -0,0 +1,830 @@ |
+// Copyright (c) 2016, 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 VM_KERNEL_TO_IL_H_ |
+#define VM_KERNEL_TO_IL_H_ |
+ |
+#include "vm/growable_array.h" |
+#include "vm/hash_map.h" |
+ |
+#include "vm/flow_graph.h" |
+#include "vm/flow_graph_builder.h" |
+#include "vm/intermediate_language.h" |
+#include "vm/kernel.h" |
+ |
+namespace dart { |
+namespace kernel { |
+ |
+template <typename K, typename V> |
+class Map : public DirectChainedHashMap<RawPointerKeyValueTrait<K, V> > { |
+ public: |
+ typedef typename RawPointerKeyValueTrait<K, V>::Key Key; |
+ typedef typename RawPointerKeyValueTrait<K, V>::Value Value; |
+ typedef typename RawPointerKeyValueTrait<K, V>::Pair Pair; |
+ |
+ inline void Insert(const Key& key, const Value& value) { |
+ Pair pair(key, value); |
+ DirectChainedHashMap<RawPointerKeyValueTrait<K, V> >::Insert(pair); |
+ } |
+ |
+ inline V Lookup(const Key& key) { |
+ Pair* pair = |
+ DirectChainedHashMap<RawPointerKeyValueTrait<K, V> >::Lookup(key); |
+ if (pair == NULL) { |
+ return V(); |
+ } else { |
+ return pair->value; |
+ } |
+ } |
+}; |
+ |
+class BreakableBlock; |
+class CatchBlock; |
+class FlowGraphBuilder; |
+class SwitchBlock; |
+class TryCatchBlock; |
+class TryFinallyBlock; |
+ |
+class Fragment { |
+ public: |
+ Instruction* entry; |
+ Instruction* current; |
+ |
+ Fragment() : entry(NULL), current(NULL) {} |
+ |
+ explicit Fragment(Instruction* instruction) |
+ : entry(instruction), current(instruction) {} |
+ |
+ Fragment(Instruction* entry, Instruction* current) |
+ : entry(entry), current(current) {} |
+ |
+ bool is_open() { return entry == NULL || current != NULL; } |
+ bool is_closed() { return !is_open(); } |
+ |
+ Fragment& operator+=(const Fragment& other); |
+ Fragment& operator<<=(Instruction* next); |
+ |
+ Fragment closed(); |
+}; |
+ |
+Fragment operator+(const Fragment& first, const Fragment& second); |
+Fragment operator<<(const Fragment& fragment, Instruction* next); |
+ |
+typedef ZoneGrowableArray<PushArgumentInstr*>* ArgumentArray; |
+ |
+ |
+class ActiveClass { |
+ public: |
+ ActiveClass() |
+ : kernel_class(NULL), klass(NULL), member(NULL), kernel_function(NULL) {} |
+ |
+ // The current enclosing kernel class (if available, otherwise NULL). |
+ Class* kernel_class; |
+ |
+ // The current enclosing class (or the library top-level class). When this is |
+ // a library's top-level class, the kernel_class will be NULL. |
+ const dart::Class* klass; |
+ |
+ // The enclosing member (e.g., Constructor, Procedure, or Field) if there |
+ // is one. |
+ Member* member; |
+ |
+ // The current function. |
+ FunctionNode* kernel_function; |
+}; |
+ |
+ |
+class ActiveClassScope { |
+ public: |
+ ActiveClassScope(ActiveClass* active_class, Class* kernel_class, |
+ const dart::Class* klass) |
+ : active_class_(active_class), saved_(*active_class) { |
+ active_class_->kernel_class = kernel_class; |
+ active_class_->klass = klass; |
+ active_class_->member = NULL; |
+ active_class_->kernel_function = NULL; |
+ } |
+ |
+ ~ActiveClassScope() { *active_class_ = saved_; } |
+ |
+ private: |
+ ActiveClass* active_class_; |
+ ActiveClass saved_; |
+}; |
+ |
+ |
+class ActiveMemberScope { |
+ public: |
+ ActiveMemberScope(ActiveClass* active_class, Member* member) |
+ : active_class_(active_class), saved_(*active_class) { |
+ // The class and kernel_class is inherited. |
+ active_class_->member = member; |
+ active_class_->kernel_function = NULL; |
+ } |
+ |
+ ~ActiveMemberScope() { *active_class_ = saved_; } |
+ |
+ private: |
+ ActiveClass* active_class_; |
+ ActiveClass saved_; |
+}; |
+ |
+ |
+class ActiveFunctionScope { |
+ public: |
+ ActiveFunctionScope(ActiveClass* active_class, FunctionNode* kernel_function) |
+ : active_class_(active_class), saved_(*active_class) { |
+ // The class, kernel_class, and member are inherited. |
+ active_class_->kernel_function = kernel_function; |
+ } |
+ |
+ ~ActiveFunctionScope() { *active_class_ = saved_; } |
+ |
+ private: |
+ ActiveClass* active_class_; |
+ ActiveClass saved_; |
+}; |
+ |
+ |
+class TranslationHelper { |
+ public: |
+ TranslationHelper(dart::Thread* thread, dart::Zone* zone, Isolate* isolate) |
+ : thread_(thread), zone_(zone), isolate_(isolate) {} |
+ virtual ~TranslationHelper() {} |
+ |
+ Thread* thread() { return thread_; } |
+ |
+ Zone* zone() { return zone_; } |
+ |
+ Isolate* isolate() { return isolate_; } |
+ |
+ // Set whether unfinalized classes should be finalized. The base class |
+ // implementation used at flow graph construction time looks up classes in the |
+ // VM's heap, all of which should already be finalized. |
+ virtual void SetFinalize(bool finalize) {} |
+ |
+ RawInstance* Canonicalize(const Instance& instance); |
+ |
+ const dart::String& DartString(const char* content, |
+ Heap::Space space = Heap::kNew); |
+ dart::String& DartString(String* content, Heap::Space space = Heap::kNew); |
+ const dart::String& DartSymbol(const char* content) const; |
+ dart::String& DartSymbol(String* content) const; |
+ |
+ const dart::String& DartClassName(Class* kernel_klass); |
+ const dart::String& DartConstructorName(Constructor* node); |
+ const dart::String& DartProcedureName(Procedure* procedure); |
+ |
+ const dart::String& DartSetterName(Name* kernel_name); |
+ const dart::String& DartGetterName(Name* kernel_name); |
+ const dart::String& DartFieldName(Name* kernel_name); |
+ const dart::String& DartInitializerName(Name* kernel_name); |
+ const dart::String& DartMethodName(Name* kernel_name); |
+ const dart::String& DartFactoryName(Class* klass, Name* kernel_name); |
+ |
+ const Array& ArgumentNames(List<NamedExpression>* named); |
+ |
+ // A subclass overrides these when reading in the Kernel program in order to |
+ // support recursive type expressions (e.g. for "implements X" ... |
+ // annotations). |
+ virtual RawLibrary* LookupLibraryByKernelLibrary(Library* library); |
+ virtual RawClass* LookupClassByKernelClass(Class* klass); |
+ |
+ RawField* LookupFieldByKernelField(Field* field); |
+ RawFunction* LookupStaticMethodByKernelProcedure(Procedure* procedure); |
+ RawFunction* LookupConstructorByKernelConstructor(Constructor* constructor); |
+ dart::RawFunction* LookupConstructorByKernelConstructor( |
+ const dart::Class& owner, Constructor* constructor); |
+ |
+ dart::Type& GetCanonicalType(const dart::Class& klass); |
+ |
+ void ReportError(const char* format, ...); |
+ void ReportError(const Error& prev_error, const char* format, ...); |
+ |
+ private: |
+ // This will mangle [kernel_name] (if necessary) and make the result a symbol. |
+ // The result will be avilable in [name_to_modify] and it is also returned. |
+ dart::String& ManglePrivateName(Library* kernel_library, |
+ dart::String* name_to_modify, |
+ bool symbolize = true); |
+ |
+ dart::Thread* thread_; |
+ dart::Zone* zone_; |
+ dart::Isolate* isolate_; |
+}; |
+ |
+// Regarding malformed types: |
+// The spec says in section "19.1 Static Types" roughly: |
+// |
+// A type T is malformed iff: |
+// * T does not denote a type in scope |
+// * T refers to a type parameter in a static member |
+// * T is a parametrized Type G<T1, ...> and G is malformed |
+// * T denotes declarations from multiple imports |
+// |
+// Any use of a malformed type gives rise to a static warning. A malformed |
+// type is then interpreted as dynamic by the static type checker and the |
+// runtime unless explicitly specified otherwise. |
+class DartTypeTranslator : public DartTypeVisitor { |
+ public: |
+ DartTypeTranslator(TranslationHelper* helper, ActiveClass* active_class, |
+ bool finalize = true) |
+ : translation_helper_(*helper), |
+ active_class_(active_class), |
+ zone_(helper->zone()), |
+ result_(AbstractType::Handle(helper->zone())), |
+ finalize_(finalize) {} |
+ |
+ // Can return a malformed type. |
+ AbstractType& TranslateType(DartType* node); |
+ |
+ // Can return a malformed type. |
+ AbstractType& TranslateTypeWithoutFinalization(DartType* node); |
+ |
+ |
+ virtual void VisitDefaultDartType(DartType* node) { UNREACHABLE(); } |
+ |
+ virtual void VisitInvalidType(InvalidType* node); |
+ |
+ virtual void VisitFunctionType(FunctionType* node); |
+ |
+ virtual void VisitTypeParameterType(TypeParameterType* node); |
+ |
+ virtual void VisitInterfaceType(InterfaceType* node); |
+ |
+ virtual void VisitDynamicType(DynamicType* node); |
+ |
+ virtual void VisitVoidType(VoidType* node); |
+ |
+ // Will return `TypeArguments::null()` in case any of the arguments are |
+ // malformed. |
+ const TypeArguments& TranslateInstantiatedTypeArguments( |
+ const dart::Class& receiver_class, DartType** receiver_type_arguments, |
+ intptr_t length); |
+ |
+ // Will return `TypeArguments::null()` in case any of the arguments are |
+ // malformed. |
+ const TypeArguments& TranslateTypeArguments(DartType** dart_types, |
+ intptr_t length); |
+ |
+ const Type& ReceiverType(const dart::Class& klass); |
+ |
+ private: |
+ TranslationHelper& translation_helper_; |
+ ActiveClass* active_class_; |
+ Zone* zone_; |
+ AbstractType& result_; |
+ |
+ bool finalize_; |
+}; |
+ |
+ |
+// There are several cases when we are compiling constant expressions: |
+// |
+// * constant field initializers: |
+// const FieldName = <expr>; |
+// |
+// * constant expressions: |
+// const [<expr>, ...] |
+// const {<expr> : <expr>, ...} |
+// const Constructor(<expr>, ...) |
+// |
+// * constant default parameters: |
+// f(a, [b = <expr>]) |
+// f(a, {b: <expr>}) |
+// |
+// * constant values to compare in a [SwitchCase] |
+// case <expr>: |
+// |
+// In all cases `<expr>` must be recursively evaluated and canonicalized at |
+// compile-time. |
+class ConstantEvaluator : public ExpressionVisitor { |
+ public: |
+ ConstantEvaluator(FlowGraphBuilder* builder, Zone* zone, TranslationHelper* h, |
+ DartTypeTranslator* type_translator) |
+ : builder_(builder), |
+ isolate_(Isolate::Current()), |
+ zone_(zone), |
+ translation_helper_(*h), |
+ type_translator_(*type_translator), |
+ result_(dart::Instance::Handle(zone)) {} |
+ virtual ~ConstantEvaluator() {} |
+ |
+ Instance& EvaluateExpression(Expression* node); |
+ Object& EvaluateExpressionSafe(Expression* node); |
+ Instance& EvaluateConstructorInvocation(ConstructorInvocation* node); |
+ Instance& EvaluateListLiteral(ListLiteral* node); |
+ Instance& EvaluateMapLiteral(MapLiteral* node); |
+ |
+ virtual void VisitDefaultExpression(Expression* node) { UNREACHABLE(); } |
+ |
+ virtual void VisitBigintLiteral(BigintLiteral* node); |
+ virtual void VisitBoolLiteral(BoolLiteral* node); |
+ virtual void VisitDoubleLiteral(DoubleLiteral* node); |
+ virtual void VisitIntLiteral(IntLiteral* node); |
+ virtual void VisitNullLiteral(NullLiteral* node); |
+ virtual void VisitStringLiteral(StringLiteral* node); |
+ virtual void VisitSymbolLiteral(SymbolLiteral* node); |
+ virtual void VisitTypeLiteral(TypeLiteral* node); |
+ |
+ virtual void VisitListLiteral(ListLiteral* node); |
+ virtual void VisitMapLiteral(MapLiteral* node); |
+ |
+ virtual void VisitConstructorInvocation(ConstructorInvocation* node); |
+ virtual void VisitMethodInvocation(MethodInvocation* node); |
+ virtual void VisitStaticGet(StaticGet* node); |
+ virtual void VisitVariableGet(VariableGet* node); |
+ virtual void VisitLet(Let* node); |
+ virtual void VisitStaticInvocation(StaticInvocation* node); |
+ virtual void VisitStringConcatenation(StringConcatenation* node); |
+ virtual void VisitConditionalExpression(ConditionalExpression* node); |
+ virtual void VisitLogicalExpression(LogicalExpression* node); |
+ virtual void VisitNot(Not* node); |
+ |
+ private: |
+ // This will translate type arguments form [kernel_arguments]. If no type |
+ // arguments are passed and the [target] is a factory then the null type |
+ // argument array will be returned. |
+ // |
+ // If none of these cases apply, NULL will be returned. |
+ const TypeArguments* TranslateTypeArguments(const Function& target, |
+ dart::Class* target_klass, |
+ Arguments* kernel_arguments); |
+ |
+ const Object& RunFunction(const Function& function, Arguments* arguments, |
+ const Instance* receiver = NULL, |
+ const TypeArguments* type_args = NULL); |
+ |
+ 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); |
+ |
+ FlowGraphBuilder* builder_; |
+ Isolate* isolate_; |
+ Zone* zone_; |
+ TranslationHelper& translation_helper_; |
+ DartTypeTranslator& type_translator_; |
+ |
+ Instance& result_; |
+}; |
+ |
+ |
+struct FunctionScope { |
+ FunctionNode* function; |
+ LocalScope* scope; |
+}; |
+ |
+ |
+class ScopeBuildingResult : public ZoneAllocated { |
+ public: |
+ Map<VariableDeclaration, LocalVariable*> locals; |
+ Map<TreeNode, LocalScope*> scopes; |
+ GrowableArray<FunctionScope> function_scopes; |
+ |
+ // Only non-NULL for instance functions. |
+ LocalVariable* this_variable = NULL; |
+ |
+ // Only non-NULL for factory constructor functions. |
+ LocalVariable* type_arguments_variable = NULL; |
+ |
+ // Non-NULL when the function contains a switch statement. |
+ LocalVariable* switch_variable = NULL; |
+ |
+ // Non-NULL when the function contains a return inside a finally block. |
+ LocalVariable* finally_return_variable = NULL; |
+ |
+ // Non-NULL when the function is a setter. |
+ LocalVariable* setter_value = NULL; |
+ |
+ // Non-NULL if the function contains yield statement. |
+ // TODO(27590) actual variable is called :await_jump_var, we should rename |
+ // it to reflect the fact that it is used for both await and yield. |
+ LocalVariable* yield_jump_variable = NULL; |
+ |
+ // Non-NULL if the function contains yield statement. |
+ // TODO(27590) actual variable is called :await_ctx_var, we should rename |
+ // it to reflect the fact that it is used for both await and yield. |
+ LocalVariable* yield_context_variable = NULL; |
+ |
+ // Variables used in exception handlers, one per exception handler nesting |
+ // level. |
+ GrowableArray<LocalVariable*> exception_variables; |
+ GrowableArray<LocalVariable*> stack_trace_variables; |
+ GrowableArray<LocalVariable*> catch_context_variables; |
+ |
+ // For-in iterators, one per for-in nesting level. |
+ GrowableArray<LocalVariable*> iterator_variables; |
+}; |
+ |
+ |
+class ScopeBuilder : public RecursiveVisitor { |
+ public: |
+ ScopeBuilder(ParsedFunction* parsed_function, TreeNode* node) |
+ : result_(NULL), |
+ parsed_function_(parsed_function), |
+ node_(node), |
+ zone_(Thread::Current()->zone()), |
+ translation_helper_(Thread::Current(), zone_, Isolate::Current()), |
+ current_function_scope_(NULL), |
+ scope_(NULL), |
+ depth_(0), |
+ name_index_(0) {} |
+ |
+ virtual ~ScopeBuilder() {} |
+ |
+ ScopeBuildingResult* BuildScopes(); |
+ |
+ virtual void VisitName(Name* node) { /* NOP */ |
+ } |
+ |
+ virtual void VisitThisExpression(ThisExpression* node); |
+ virtual void VisitTypeParameterType(TypeParameterType* node); |
+ virtual void VisitVariableGet(VariableGet* node); |
+ virtual void VisitVariableSet(VariableSet* node); |
+ virtual void VisitFunctionExpression(FunctionExpression* node); |
+ virtual void VisitLet(Let* node); |
+ virtual void VisitBlock(Block* node); |
+ virtual void VisitVariableDeclaration(VariableDeclaration* node); |
+ virtual void VisitFunctionDeclaration(FunctionDeclaration* node); |
+ virtual void VisitWhileStatement(WhileStatement* node); |
+ virtual void VisitDoStatement(DoStatement* node); |
+ virtual void VisitForStatement(ForStatement* node); |
+ virtual void VisitForInStatement(ForInStatement* node); |
+ virtual void VisitSwitchStatement(SwitchStatement* node); |
+ virtual void VisitReturnStatement(ReturnStatement* node); |
+ virtual void VisitTryCatch(TryCatch* node); |
+ virtual void VisitTryFinally(TryFinally* node); |
+ virtual void VisitYieldStatement(YieldStatement* node); |
+ virtual void VisitAssertStatement(AssertStatement* node); |
+ |
+ virtual void VisitFunctionNode(FunctionNode* node); |
+ |
+ virtual void VisitConstructor(Constructor* node); |
+ |
+ private: |
+ void EnterScope(TreeNode* node); |
+ void ExitScope(); |
+ |
+ LocalVariable* MakeVariable(const dart::String& name); |
+ LocalVariable* MakeVariable(const dart::String& name, const Type& type); |
+ |
+ void AddParameters(FunctionNode* function, intptr_t pos = 0); |
+ void AddParameter(VariableDeclaration* declaration, intptr_t pos); |
+ void AddVariable(VariableDeclaration* declaration); |
+ void AddExceptionVariable(GrowableArray<LocalVariable*>* variables, |
+ const char* prefix, intptr_t nesting_depth); |
+ void AddTryVariables(); |
+ void AddCatchVariables(); |
+ 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(VariableDeclaration* declaration); |
+ |
+ const dart::String& GenerateName(const char* prefix, intptr_t suffix); |
+ |
+ void HandleLocalFunction(TreeNode* parent, FunctionNode* function); |
+ void HandleSpecialLoad(LocalVariable** variable, const dart::String& symbol); |
+ void LookupCapturedVariableByName(LocalVariable** variable, |
+ const dart::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_; |
+ TreeNode* node_; |
+ |
+ Zone* zone_; |
+ TranslationHelper translation_helper_; |
+ |
+ |
+ FunctionNode* current_function_node_; |
+ LocalScope* current_function_scope_; |
+ LocalScope* scope_; |
+ DepthState depth_; |
+ |
+ intptr_t name_index_; |
+}; |
+ |
+ |
+class FlowGraphBuilder : public TreeVisitor { |
+ public: |
+ FlowGraphBuilder(TreeNode* node, ParsedFunction* parsed_function, |
+ const ZoneGrowableArray<const ICData*>& ic_data_array, |
+ InlineExitCollector* exit_collector, intptr_t osr_id, |
+ intptr_t first_block_id = 1); |
+ virtual ~FlowGraphBuilder(); |
+ |
+ FlowGraph* BuildGraph(); |
+ |
+ virtual void VisitDefaultTreeNode(TreeNode* node) { UNREACHABLE(); } |
+ |
+ virtual void VisitInvalidExpression(InvalidExpression* node); |
+ virtual void VisitNullLiteral(NullLiteral* node); |
+ virtual void VisitBoolLiteral(BoolLiteral* node); |
+ virtual void VisitIntLiteral(IntLiteral* node); |
+ virtual void VisitBigintLiteral(BigintLiteral* node); |
+ virtual void VisitDoubleLiteral(DoubleLiteral* node); |
+ virtual void VisitStringLiteral(StringLiteral* node); |
+ virtual void VisitSymbolLiteral(SymbolLiteral* node); |
+ virtual void VisitTypeLiteral(TypeLiteral* node); |
+ virtual void VisitVariableGet(VariableGet* node); |
+ virtual void VisitVariableSet(VariableSet* node); |
+ virtual void VisitStaticGet(StaticGet* node); |
+ virtual void VisitStaticSet(StaticSet* node); |
+ virtual void VisitPropertyGet(PropertyGet* node); |
+ virtual void VisitPropertySet(PropertySet* node); |
+ virtual void VisitDirectPropertyGet(DirectPropertyGet* node); |
+ virtual void VisitDirectPropertySet(DirectPropertySet* node); |
+ virtual void VisitStaticInvocation(StaticInvocation* node); |
+ virtual void VisitMethodInvocation(MethodInvocation* node); |
+ virtual void VisitDirectMethodInvocation(DirectMethodInvocation* node); |
+ virtual void VisitConstructorInvocation(ConstructorInvocation* node); |
+ virtual void VisitIsExpression(IsExpression* node); |
+ virtual void VisitAsExpression(AsExpression* node); |
+ virtual void VisitConditionalExpression(ConditionalExpression* node); |
+ virtual void VisitLogicalExpression(LogicalExpression* node); |
+ virtual void VisitNot(Not* node); |
+ virtual void VisitThisExpression(ThisExpression* node); |
+ virtual void VisitStringConcatenation(StringConcatenation* node); |
+ virtual void VisitListLiteral(ListLiteral* node); |
+ virtual void VisitMapLiteral(MapLiteral* node); |
+ virtual void VisitFunctionExpression(FunctionExpression* node); |
+ virtual void VisitLet(Let* node); |
+ virtual void VisitThrow(Throw* node); |
+ virtual void VisitRethrow(Rethrow* node); |
+ virtual void VisitBlockExpression(BlockExpression* node); |
+ |
+ virtual void VisitInvalidStatement(InvalidStatement* node); |
+ virtual void VisitEmptyStatement(EmptyStatement* node); |
+ virtual void VisitBlock(Block* node); |
+ virtual void VisitReturnStatement(ReturnStatement* node); |
+ virtual void VisitExpressionStatement(ExpressionStatement* node); |
+ virtual void VisitVariableDeclaration(VariableDeclaration* node); |
+ virtual void VisitFunctionDeclaration(FunctionDeclaration* node); |
+ virtual void VisitIfStatement(IfStatement* node); |
+ virtual void VisitWhileStatement(WhileStatement* node); |
+ virtual void VisitDoStatement(DoStatement* node); |
+ virtual void VisitForStatement(ForStatement* node); |
+ virtual void VisitForInStatement(ForInStatement* node); |
+ virtual void VisitLabeledStatement(LabeledStatement* node); |
+ virtual void VisitBreakStatement(BreakStatement* node); |
+ virtual void VisitSwitchStatement(SwitchStatement* node); |
+ virtual void VisitContinueSwitchStatement(ContinueSwitchStatement* node); |
+ virtual void VisitAssertStatement(AssertStatement* node); |
+ virtual void VisitTryFinally(TryFinally* node); |
+ virtual void VisitTryCatch(TryCatch* node); |
+ virtual void VisitYieldStatement(YieldStatement* node); |
+ |
+ private: |
+ FlowGraph* BuildGraphOfFunction(FunctionNode* node, |
+ Constructor* constructor = NULL); |
+ FlowGraph* BuildGraphOfFieldAccessor(Field* node, |
+ LocalVariable* setter_value); |
+ FlowGraph* BuildGraphOfStaticFieldInitializer(Field* node); |
+ FlowGraph* BuildGraphOfMethodExtractor(const Function& method); |
+ FlowGraph* BuildGraphOfImplicitClosureFunction(FunctionNode* kernel_function, |
+ const Function& function); |
+ FlowGraph* BuildGraphOfNoSuchMethodDispatcher(const Function& function); |
+ FlowGraph* BuildGraphOfInvokeFieldDispatcher(const Function& function); |
+ |
+ Fragment NativeFunctionBody(FunctionNode* kernel_function, |
+ const Function& function); |
+ |
+ void SetupDefaultParameterValues(FunctionNode* function); |
+ |
+ TargetEntryInstr* BuildTargetEntry(); |
+ JoinEntryInstr* BuildJoinEntry(); |
+ |
+ Fragment TranslateArguments(Arguments* node, Array* argument_names); |
+ ArgumentArray GetArguments(int count); |
+ |
+ Fragment TranslateInitializers(Class* kernel_klass, |
+ List<Initializer>* initialiers); |
+ |
+ Fragment TranslateStatement(Statement* statement); |
+ Fragment TranslateCondition(Expression* expression, bool* negate); |
+ Fragment TranslateExpression(Expression* expression); |
+ |
+ Fragment TranslateFinallyFinalizers(TryFinallyBlock* outer_finally, |
+ intptr_t target_context_depth); |
+ |
+ Fragment TranslateFunctionNode(FunctionNode* node, TreeNode* parent); |
+ |
+ Fragment EnterScope(TreeNode* node, bool* new_context = NULL); |
+ Fragment ExitScope(TreeNode* node); |
+ |
+ Fragment LoadContextAt(int depth); |
+ Fragment AdjustContextTo(int depth); |
+ |
+ Fragment PushContext(int size); |
+ Fragment PopContext(); |
+ |
+ Fragment LoadInstantiatorTypeArguments(); |
+ Fragment InstantiateTypeArguments(const TypeArguments& type_arguments); |
+ Fragment TranslateInstantiatedTypeArguments( |
+ const TypeArguments& type_arguments); |
+ |
+ Fragment AllocateContext(int size); |
+ Fragment AllocateObject(const dart::Class& klass, intptr_t argument_count); |
+ Fragment AllocateObject(const dart::Class& klass, |
+ const Function& closure_function); |
+ Fragment BooleanNegate(); |
+ Fragment StrictCompare(Token::Kind kind, bool number_check = false); |
+ Fragment BranchIfTrue(TargetEntryInstr** then_entry, |
+ TargetEntryInstr** otherwise_entry, |
+ bool negate = false); |
+ Fragment BranchIfNull(TargetEntryInstr** then_entry, |
+ TargetEntryInstr** otherwise_entry, |
+ bool negate = false); |
+ Fragment BranchIfEqual(TargetEntryInstr** then_entry, |
+ TargetEntryInstr** otherwise_entry, |
+ bool negate = false); |
+ Fragment BranchIfStrictEqual(TargetEntryInstr** then_entry, |
+ TargetEntryInstr** otherwise_entry); |
+ Fragment CatchBlockEntry(const Array& handler_types, intptr_t handler_index); |
+ Fragment TryCatch(int try_handler_index); |
+ Fragment CheckStackOverflowInPrologue(); |
+ Fragment CheckStackOverflow(); |
+ Fragment CloneContext(); |
+ Fragment Constant(const Object& value); |
+ Fragment CreateArray(); |
+ Fragment Goto(JoinEntryInstr* destination); |
+ Fragment IntConstant(int64_t value); |
+ Fragment InstanceCall(const dart::String& name, Token::Kind kind, |
+ intptr_t argument_count, intptr_t num_args_checked = 1); |
+ Fragment InstanceCall(const dart::String& name, Token::Kind kind, |
+ intptr_t argument_count, const Array& argument_names, |
+ intptr_t num_args_checked = 1); |
+ Fragment ClosureCall(int argument_count, const Array& argument_names); |
+ Fragment ThrowException(); |
+ Fragment RethrowException(int catch_try_index); |
+ Fragment LoadClassId(); |
+ Fragment LoadField(const dart::Field& field); |
+ Fragment LoadField(intptr_t offset, intptr_t class_id = kDynamicCid); |
+ Fragment LoadNativeField(MethodRecognizer::Kind kind, intptr_t offset, |
+ const Type& type, intptr_t class_id, |
+ bool is_immutable = false); |
+ Fragment LoadLocal(LocalVariable* variable); |
+ Fragment InitStaticField(const dart::Field& field); |
+ Fragment LoadStaticField(); |
+ Fragment NullConstant(); |
+ Fragment NativeCall(const dart::String* name, const Function* function); |
+ Fragment PushArgument(); |
+ Fragment Return(); |
+ Fragment StaticCall(const Function& target, intptr_t argument_count); |
+ Fragment StaticCall(const Function& target, intptr_t argument_count, |
+ const Array& argument_names); |
+ Fragment StoreIndexed(intptr_t class_id); |
+ Fragment StoreInstanceField(const dart::Field& field); |
+ Fragment StoreInstanceField(intptr_t offset); |
+ Fragment StoreLocal(LocalVariable* variable); |
+ Fragment StoreStaticField(const dart::Field& field); |
+ Fragment StringInterpolate(); |
+ Fragment ThrowTypeError(); |
+ Fragment ThrowNoSuchMethodError(); |
+ Fragment BuildImplicitClosureCreation(const Function& target); |
+ |
+ dart::RawFunction* LookupMethodByMember(Member* target, |
+ const dart::String& method_name); |
+ |
+ LocalVariable* MakeTemporary(); |
+ LocalVariable* MakeNonTemporary(const dart::String& symbol); |
+ |
+ intptr_t CurrentTryIndex(); |
+ intptr_t AllocateTryIndex() { return next_used_try_index_++; } |
+ |
+ void AddVariable(VariableDeclaration* declaration, LocalVariable* variable); |
+ void AddParameter(VariableDeclaration* declaration, LocalVariable* variable, |
+ intptr_t pos); |
+ dart::LocalVariable* LookupVariable(VariableDeclaration* var); |
+ |
+ void SetTempIndex(Definition* definition); |
+ |
+ void Push(Definition* definition); |
+ Value* Pop(); |
+ Fragment Drop(); |
+ |
+ bool IsInlining() { return exit_collector_ != NULL; } |
+ |
+ Token::Kind MethodKind(const dart::String& name); |
+ |
+ void InlineBailout(const char* reason); |
+ |
+ Zone* zone_; |
+ TranslationHelper translation_helper_; |
+ |
+ // The node we are currently compiling (e.g. FunctionNode, Constructor, |
+ // Field) |
+ TreeNode* node_; |
+ |
+ ParsedFunction* parsed_function_; |
+ intptr_t osr_id_; |
+ const ZoneGrowableArray<const ICData*>& ic_data_array_; |
+ InlineExitCollector* exit_collector_; |
+ |
+ intptr_t next_block_id_; |
+ intptr_t AllocateBlockId() { return next_block_id_++; } |
+ |
+ intptr_t next_function_id_; |
+ intptr_t AllocateFunctionId() { return next_function_id_++; } |
+ |
+ intptr_t context_depth_; |
+ intptr_t loop_depth_; |
+ intptr_t try_depth_; |
+ intptr_t catch_depth_; |
+ intptr_t for_in_depth_; |
+ Fragment fragment_; |
+ Value* stack_; |
+ intptr_t pending_argument_count_; |
+ |
+ GraphEntryInstr* graph_entry_; |
+ |
+ ScopeBuildingResult* scopes_; |
+ |
+ struct YieldContinuation { |
+ Instruction* entry; |
+ intptr_t try_index; |
+ |
+ YieldContinuation(Instruction* entry, intptr_t try_index) |
+ : entry(entry), try_index(try_index) {} |
+ |
+ YieldContinuation() |
+ : entry(NULL), try_index(CatchClauseNode::kInvalidTryIndex) {} |
+ }; |
+ |
+ GrowableArray<YieldContinuation> yield_continuations_; |
+ |
+ LocalVariable* CurrentException() { |
+ return scopes_->exception_variables[catch_depth_ - 1]; |
+ } |
+ LocalVariable* CurrentStackTrace() { |
+ return scopes_->stack_trace_variables[catch_depth_ - 1]; |
+ } |
+ LocalVariable* CurrentCatchContext() { |
+ return scopes_->catch_context_variables[try_depth_]; |
+ } |
+ |
+ // A chained list of breakable blocks. Chaining and lookup is done by the |
+ // [BreakableBlock] class. |
+ BreakableBlock* breakable_block_; |
+ |
+ // A chained list of switch blocks. Chaining and lookup is done by the |
+ // [SwitchBlock] class. |
+ SwitchBlock* switch_block_; |
+ |
+ // A chained list of try-finally blocks. Chaining and lookup is done by the |
+ // [TryFinallyBlock] class. |
+ TryFinallyBlock* try_finally_block_; |
+ |
+ // A chained list of try-catch blocks. Chaining and lookup is done by the |
+ // [TryCatchBlock] class. |
+ TryCatchBlock* try_catch_block_; |
+ intptr_t next_used_try_index_; |
+ |
+ // A chained list of catch blocks. Chaining and lookup is done by the |
+ // [CatchBlock] class. |
+ CatchBlock* catch_block_; |
+ |
+ ActiveClass active_class_; |
+ DartTypeTranslator type_translator_; |
+ ConstantEvaluator constant_evaluator_; |
+ |
+ friend class BreakableBlock; |
+ friend class CatchBlock; |
+ friend class ConstantEvaluator; |
+ friend class DartTypeTranslator; |
+ friend class ScopeBuilder; |
+ friend class SwitchBlock; |
+ friend class TryCatchBlock; |
+ friend class TryFinallyBlock; |
+}; |
+ |
+} // namespace kernel |
+} // namespace dart |
+ |
+ |
+#endif // VM_KERNEL_TO_IL_H_ |