| OLD | NEW |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
| 6 | 6 |
| 7 import '../closure.dart'; | 7 import '../closure.dart'; |
| 8 import '../common.dart'; |
| 8 import '../compiler.dart'; | 9 import '../compiler.dart'; |
| 9 import '../elements/elements.dart'; | |
| 10 import '../elements/entities.dart'; | 10 import '../elements/entities.dart'; |
| 11 import '../kernel/kernel.dart'; | 11 import '../kernel/element_map.dart'; |
| 12 import '../ssa/kernel_ast_adapter.dart'; | |
| 13 import '../tree/tree.dart' as ast; | |
| 14 import '../universe/side_effects.dart' show SideEffects; | 12 import '../universe/side_effects.dart' show SideEffects; |
| 15 import 'inferrer_engine.dart'; | 13 import 'inferrer_engine.dart'; |
| 16 import 'locals_handler.dart'; | 14 import 'locals_handler.dart'; |
| 17 import 'type_graph_nodes.dart'; | 15 import 'type_graph_nodes.dart'; |
| 18 import 'type_system.dart'; | 16 import 'type_system.dart'; |
| 19 | 17 |
| 20 /// [KernelTypeGraphBuilder] constructs a type-inference graph for a particular | 18 /// [KernelTypeGraphBuilder] constructs a type-inference graph for a particular |
| 21 /// element. | 19 /// element. |
| 22 /// | 20 /// |
| 23 /// Calling [run] will start the work of visiting the body of the code to | 21 /// Calling [run] will start the work of visiting the body of the code to |
| 24 /// construct a set of inference-nodes that abstractly represent what the code | 22 /// construct a set of inference-nodes that abstractly represent what the code |
| 25 /// is doing. | 23 /// is doing. |
| 26 class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> { | 24 class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> { |
| 27 final Compiler compiler; | 25 final Compiler compiler; |
| 28 final MemberElement originalElement; | 26 final MemberEntity analyzedMember; |
| 29 // TODO(efortuna): Remove this. | |
| 30 final MemberElement outermostElement; | |
| 31 final ir.Node analyzedNode; | 27 final ir.Node analyzedNode; |
| 32 final ResolvedAst resolvedAst; | 28 final TypeSystem<ir.Node> types; |
| 33 // TODO(johnniwinther): This should be TypeSystem<ir.Node>. | |
| 34 final TypeSystem<ast.Node> types; | |
| 35 LocalsHandler locals; | 29 LocalsHandler locals; |
| 36 final InferrerEngine inferrer; | 30 final InferrerEngine<ir.Node> inferrer; |
| 37 SideEffects sideEffects = new SideEffects.empty(); | 31 SideEffects sideEffects = new SideEffects.empty(); |
| 38 int loopLevel = 0; | 32 int loopLevel = 0; |
| 39 bool get inLoop => loopLevel > 0; | 33 bool get inLoop => loopLevel > 0; |
| 40 | 34 |
| 41 final Set<Entity> capturedVariables = new Set<Entity>(); | 35 final Set<Local> capturedVariables = new Set<Local>(); |
| 42 | 36 |
| 43 final KernelAstAdapter astAdapter; | 37 KernelTypeGraphBuilder.internal(this.analyzedMember, this.inferrer, |
| 44 | 38 this.compiler, this.locals, this.analyzedNode) |
| 45 KernelTypeGraphBuilder.internal( | |
| 46 this.originalElement, | |
| 47 this.resolvedAst, | |
| 48 this.outermostElement, | |
| 49 this.inferrer, | |
| 50 this.compiler, | |
| 51 this.locals, | |
| 52 this.astAdapter, | |
| 53 this.analyzedNode) | |
| 54 : this.types = inferrer.types { | 39 : this.types = inferrer.types { |
| 55 if (locals != null) return; | 40 if (locals != null) return; |
| 56 | 41 |
| 57 ast.Node node; | 42 FieldInitializationScope<ir.Node> fieldScope = |
| 58 if (resolvedAst.kind == ResolvedAstKind.PARSED) { | 43 analyzedNode is ir.Constructor |
| 59 node = resolvedAst.node; | 44 ? new FieldInitializationScope(types) |
| 60 } | 45 : null; |
| 61 FieldInitializationScope fieldScope = (analyzedNode is ir.Constructor) | 46 locals = new LocalsHandler( |
| 62 ? new FieldInitializationScope(types) | 47 inferrer, types, compiler.options, analyzedNode, fieldScope); |
| 63 : null; | |
| 64 locals = | |
| 65 new LocalsHandler(inferrer, types, compiler.options, node, fieldScope); | |
| 66 } | 48 } |
| 67 | 49 |
| 68 factory KernelTypeGraphBuilder( | 50 factory KernelTypeGraphBuilder( |
| 69 MemberElement element, Compiler compiler, InferrerEngine inferrer, | 51 MemberEntity element, |
| 70 [LocalsHandler handler]) { | 52 Compiler compiler, |
| 71 var adapter = _createKernelAdapter(compiler, element.resolvedAst); | 53 KernelToElementMapForBuilding elementMap, |
| 72 var node = adapter.getMemberNode(element); | 54 InferrerEngine<ir.Node> inferrer, |
| 55 [LocalsHandler<ir.Node> handler]) { |
| 56 ir.Node analyzedNode; |
| 57 MemberDefinition definition = elementMap.getMemberDefinition(element); |
| 58 switch (definition.kind) { |
| 59 case MemberKind.regular: |
| 60 case MemberKind.closureCall: |
| 61 case MemberKind.constructor: |
| 62 case MemberKind.constructorBody: |
| 63 analyzedNode = definition.node; |
| 64 break; |
| 65 case MemberKind.closureField: |
| 66 failedAt(element, "Unexpected member: $definition"); |
| 67 break; |
| 68 } |
| 73 return new KernelTypeGraphBuilder.internal( | 69 return new KernelTypeGraphBuilder.internal( |
| 74 element, | 70 element, inferrer, compiler, handler, analyzedNode); |
| 75 element.resolvedAst, | |
| 76 element.outermostEnclosingMemberOrTopLevel.implementation, | |
| 77 inferrer, | |
| 78 compiler, | |
| 79 handler, | |
| 80 adapter, | |
| 81 node); | |
| 82 } | |
| 83 | |
| 84 static KernelAstAdapter _createKernelAdapter( | |
| 85 Compiler compiler, ResolvedAst resolvedAst) { | |
| 86 Kernel kernel = compiler.backend.kernelTask.kernel; | |
| 87 return new KernelAstAdapter(kernel, compiler.backend, resolvedAst, | |
| 88 kernel.nodeToAst, kernel.nodeToElement); | |
| 89 } | 71 } |
| 90 | 72 |
| 91 TypeInformation run() { | 73 TypeInformation run() { |
| 92 ir.Expression initializer; | 74 ir.Expression initializer; |
| 93 if (analyzedNode is ir.Field) { | 75 if (analyzedNode is ir.Field) { |
| 94 ir.Field field = analyzedNode; | 76 ir.Field field = analyzedNode; |
| 95 initializer = field.initializer; | 77 initializer = field.initializer; |
| 96 if (initializer == null || initializer is ir.NullLiteral) { | 78 if (initializer == null || initializer is ir.NullLiteral) { |
| 97 // Eagerly bailout, because computing the closure data only | 79 // Eagerly bailout, because computing the closure data only |
| 98 // works for functions and field assignments. | 80 // works for functions and field assignments. |
| 99 return types.nullType; | 81 return types.nullType; |
| 100 } | 82 } |
| 101 } | 83 } |
| 102 | 84 |
| 103 // Update the locals that are boxed in [locals]. These locals will | 85 // Update the locals that are boxed in [locals]. These locals will |
| 104 // be handled specially, in that we are computing their LUB at | 86 // be handled specially, in that we are computing their LUB at |
| 105 // each update, and reading them yields the type that was found in a | 87 // each update, and reading them yields the type that was found in a |
| 106 // previous analysis of [outermostElement]. | 88 // previous analysis of [outermostElement]. |
| 107 ClosureRepresentationInfo closureData = compiler | 89 ClosureRepresentationInfo closureData = compiler |
| 108 .backendStrategy.closureDataLookup | 90 .backendStrategy.closureDataLookup |
| 109 .getClosureInfoForMember(outermostElement); | 91 .getClosureInfoForMember(analyzedMember); |
| 110 closureData.forEachCapturedVariable((variable, field) { | 92 closureData.forEachCapturedVariable((variable, field) { |
| 111 locals.setCaptured(variable, field); | 93 locals.setCaptured(variable, field); |
| 112 }); | 94 }); |
| 113 closureData.forEachBoxedVariable((variable, field) { | 95 closureData.forEachBoxedVariable((variable, field) { |
| 114 locals.setCapturedAndBoxed(variable, field); | 96 locals.setCapturedAndBoxed(variable, field); |
| 115 }); | 97 }); |
| 116 | 98 |
| 117 if (analyzedNode is ir.Field) { | 99 if (analyzedNode is ir.Field) { |
| 118 return initializer.accept(this); | 100 return initializer.accept(this); |
| 119 } | 101 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 142 statement.accept(this); | 124 statement.accept(this); |
| 143 if (locals.aborts) break; | 125 if (locals.aborts) break; |
| 144 } | 126 } |
| 145 return null; | 127 return null; |
| 146 } | 128 } |
| 147 | 129 |
| 148 @override | 130 @override |
| 149 TypeInformation visitListLiteral(ir.ListLiteral listLiteral) { | 131 TypeInformation visitListLiteral(ir.ListLiteral listLiteral) { |
| 150 // We only set the type once. We don't need to re-visit the children | 132 // We only set the type once. We don't need to re-visit the children |
| 151 // when re-analyzing the node. | 133 // when re-analyzing the node. |
| 152 return inferrer.concreteKernelTypes.putIfAbsent(listLiteral, () { | 134 return inferrer.concreteTypes.putIfAbsent(listLiteral, () { |
| 153 TypeInformation elementType; | 135 TypeInformation elementType; |
| 154 int length = 0; | 136 int length = 0; |
| 155 for (ir.Expression element in listLiteral.expressions) { | 137 for (ir.Expression element in listLiteral.expressions) { |
| 156 TypeInformation type = element.accept(this); | 138 TypeInformation type = element.accept(this); |
| 157 elementType = elementType == null | 139 elementType = elementType == null |
| 158 ? types.allocatePhi(null, null, type, isTry: false) | 140 ? types.allocatePhi(null, null, type, isTry: false) |
| 159 : types.addPhiInput(null, elementType, type); | 141 : types.addPhiInput(null, elementType, type); |
| 160 length++; | 142 length++; |
| 161 } | 143 } |
| 162 elementType = elementType == null | 144 elementType = elementType == null |
| 163 ? types.nonNullEmpty() | 145 ? types.nonNullEmpty() |
| 164 : types.simplifyPhi(null, null, elementType); | 146 : types.simplifyPhi(null, null, elementType); |
| 165 TypeInformation containerType = | 147 TypeInformation containerType = |
| 166 listLiteral.isConst ? types.constListType : types.growableListType; | 148 listLiteral.isConst ? types.constListType : types.growableListType; |
| 167 // TODO(efortuna): Change signature of allocateList and the rest of | 149 // TODO(efortuna): Change signature of allocateList and the rest of |
| 168 // type_system to deal with Kernel elements. | 150 // type_system to deal with Kernel elements. |
| 169 return types.allocateList(containerType, astAdapter.getNode(listLiteral), | 151 return types.allocateList( |
| 170 outermostElement, elementType, length); | 152 containerType, listLiteral, analyzedMember, elementType, length); |
| 171 }); | 153 }); |
| 172 } | 154 } |
| 173 } | 155 } |
| OLD | NEW |