| 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 '../common.dart'; |
| 9 import '../compiler.dart'; | 9 import '../compiler.dart'; |
| 10 import '../elements/entities.dart'; | 10 import '../elements/entities.dart'; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> { | 24 class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> { |
| 25 final Compiler compiler; | 25 final Compiler compiler; |
| 26 final MemberEntity analyzedMember; | 26 final MemberEntity analyzedMember; |
| 27 final ir.Node analyzedNode; | 27 final ir.Node analyzedNode; |
| 28 final TypeSystem<ir.Node> types; | 28 final TypeSystem<ir.Node> types; |
| 29 LocalsHandler locals; | 29 LocalsHandler locals; |
| 30 final InferrerEngine<ir.Node> inferrer; | 30 final InferrerEngine<ir.Node> inferrer; |
| 31 SideEffects sideEffects = new SideEffects.empty(); | 31 SideEffects sideEffects = new SideEffects.empty(); |
| 32 int loopLevel = 0; | 32 int loopLevel = 0; |
| 33 bool get inLoop => loopLevel > 0; | 33 bool get inLoop => loopLevel > 0; |
| 34 TypeInformation returnType; |
| 34 | 35 |
| 35 final Set<Local> capturedVariables = new Set<Local>(); | 36 final Set<Local> capturedVariables = new Set<Local>(); |
| 36 | 37 |
| 37 KernelTypeGraphBuilder.internal(this.analyzedMember, this.inferrer, | 38 KernelTypeGraphBuilder.internal(this.analyzedMember, this.inferrer, |
| 38 this.compiler, this.locals, this.analyzedNode) | 39 this.compiler, this.locals, this.analyzedNode) |
| 39 : this.types = inferrer.types { | 40 : this.types = inferrer.types { |
| 40 if (locals != null) return; | 41 if (locals != null) return; |
| 41 | 42 |
| 42 FieldInitializationScope<ir.Node> fieldScope = | 43 FieldInitializationScope<ir.Node> fieldScope = |
| 43 analyzedNode is ir.Constructor | 44 analyzedNode is ir.Constructor |
| 44 ? new FieldInitializationScope(types) | 45 ? new FieldInitializationScope(types) |
| 45 : null; | 46 : null; |
| 46 locals = new LocalsHandler( | 47 locals = new LocalsHandler( |
| 47 inferrer, types, compiler.options, analyzedNode, fieldScope); | 48 inferrer, types, compiler.options, analyzedNode, fieldScope); |
| 48 } | 49 } |
| 49 | 50 |
| 50 factory KernelTypeGraphBuilder( | 51 factory KernelTypeGraphBuilder( |
| 51 MemberEntity element, | 52 MemberEntity element, |
| 52 Compiler compiler, | 53 Compiler compiler, |
| 53 KernelToElementMapForBuilding elementMap, | 54 KernelToElementMapForBuilding elementMap, |
| 54 InferrerEngine<ir.Node> inferrer, | 55 InferrerEngine<ir.Node> inferrer, |
| 56 ir.TreeNode analyzedNode, |
| 55 [LocalsHandler<ir.Node> handler]) { | 57 [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 } | |
| 69 return new KernelTypeGraphBuilder.internal( | 58 return new KernelTypeGraphBuilder.internal( |
| 70 element, inferrer, compiler, handler, analyzedNode); | 59 element, inferrer, compiler, handler, analyzedNode); |
| 71 } | 60 } |
| 72 | 61 |
| 73 TypeInformation run() { | 62 TypeInformation run() { |
| 74 ir.Expression initializer; | 63 if (analyzedMember.isField) { |
| 75 if (analyzedNode is ir.Field) { | 64 if (analyzedNode == null || analyzedNode is ir.NullLiteral) { |
| 76 ir.Field field = analyzedNode; | |
| 77 initializer = field.initializer; | |
| 78 if (initializer == null || initializer is ir.NullLiteral) { | |
| 79 // Eagerly bailout, because computing the closure data only | 65 // Eagerly bailout, because computing the closure data only |
| 80 // works for functions and field assignments. | 66 // works for functions and field assignments. |
| 81 return types.nullType; | 67 return types.nullType; |
| 82 } | 68 } |
| 83 } | 69 } |
| 84 | 70 |
| 85 // Update the locals that are boxed in [locals]. These locals will | 71 // Update the locals that are boxed in [locals]. These locals will |
| 86 // be handled specially, in that we are computing their LUB at | 72 // be handled specially, in that we are computing their LUB at |
| 87 // each update, and reading them yields the type that was found in a | 73 // each update, and reading them yields the type that was found in a |
| 88 // previous analysis of [outermostElement]. | 74 // previous analysis of [outermostElement]. |
| 89 ClosureRepresentationInfo closureData = compiler | 75 ClosureRepresentationInfo closureData = compiler |
| 90 .backendStrategy.closureDataLookup | 76 .backendStrategy.closureDataLookup |
| 91 .getClosureInfoForMember(analyzedMember); | 77 .getClosureInfoForMember(analyzedMember); |
| 92 closureData.forEachCapturedVariable((variable, field) { | 78 closureData.forEachCapturedVariable((variable, field) { |
| 93 locals.setCaptured(variable, field); | 79 locals.setCaptured(variable, field); |
| 94 }); | 80 }); |
| 95 closureData.forEachBoxedVariable((variable, field) { | 81 closureData.forEachBoxedVariable((variable, field) { |
| 96 locals.setCapturedAndBoxed(variable, field); | 82 locals.setCapturedAndBoxed(variable, field); |
| 97 }); | 83 }); |
| 98 | 84 |
| 99 if (analyzedNode is ir.Field) { | 85 return analyzedNode.accept(this); |
| 100 return initializer.accept(this); | |
| 101 } | |
| 102 return _processFunctionNode(analyzedNode); | |
| 103 } | 86 } |
| 104 | 87 |
| 105 TypeInformation _processFunctionNode(ir.FunctionNode funcNode) { | 88 void recordReturnType(TypeInformation type) { |
| 106 // TODO(efortuna): Implement. | 89 FunctionEntity analyzedMethod = analyzedMember; |
| 107 return types.dynamicType; | 90 returnType = |
| 91 inferrer.addReturnTypeForMethod(analyzedMethod, returnType, type); |
| 92 } |
| 93 |
| 94 void initializationIsIndefinite() { |
| 95 MemberEntity member = analyzedMember; |
| 96 if (member is ConstructorEntity && member.isGenerativeConstructor) { |
| 97 locals.fieldScope.isIndefinite = true; |
| 98 } |
| 99 } |
| 100 |
| 101 TypeInformation visit(ir.Node node) { |
| 102 return node == null ? null : node.accept(this); |
| 108 } | 103 } |
| 109 | 104 |
| 110 @override | 105 @override |
| 106 TypeInformation visitFunctionNode(ir.FunctionNode node) { |
| 107 // TODO(redemption): Handle constructors. |
| 108 // TODO(redemption): Handle native methods. |
| 109 // TODO(redemption): Set up parameters. |
| 110 visit(node.body); |
| 111 switch (node.asyncMarker) { |
| 112 case ir.AsyncMarker.Sync: |
| 113 if (returnType == null) { |
| 114 // No return in the body. |
| 115 returnType = locals.seenReturnOrThrow |
| 116 ? types.nonNullEmpty() // Body always throws. |
| 117 : types.nullType; |
| 118 } else if (!locals.seenReturnOrThrow) { |
| 119 // We haven'TypeInformation seen returns on all branches. So the metho
d may |
| 120 // also return null. |
| 121 recordReturnType(types.nullType); |
| 122 } |
| 123 break; |
| 124 |
| 125 case ir.AsyncMarker.SyncStar: |
| 126 // TODO(asgerf): Maybe make a ContainerTypeMask for these? The type |
| 127 // contained is the method body's return type. |
| 128 recordReturnType(types.syncStarIterableType); |
| 129 break; |
| 130 |
| 131 case ir.AsyncMarker.Async: |
| 132 recordReturnType(types.asyncFutureType); |
| 133 break; |
| 134 |
| 135 case ir.AsyncMarker.AsyncStar: |
| 136 recordReturnType(types.asyncStarStreamType); |
| 137 break; |
| 138 case ir.AsyncMarker.SyncYielding: |
| 139 failedAt( |
| 140 analyzedMember, "Unexpected async marker: ${node.asyncMarker}"); |
| 141 break; |
| 142 } |
| 143 return returnType; |
| 144 } |
| 145 |
| 146 @override |
| 111 TypeInformation defaultExpression(ir.Expression expression) { | 147 TypeInformation defaultExpression(ir.Expression expression) { |
| 112 // TODO(efortuna): Remove when more is implemented. | 148 // TODO(efortuna): Remove when more is implemented. |
| 113 return types.dynamicType; | 149 return types.dynamicType; |
| 114 } | 150 } |
| 115 | 151 |
| 116 @override | 152 @override |
| 117 TypeInformation visitNullLiteral(ir.NullLiteral literal) { | 153 TypeInformation visitNullLiteral(ir.NullLiteral literal) { |
| 118 return types.nullType; | 154 return types.nullType; |
| 119 } | 155 } |
| 120 | 156 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 145 ? types.nonNullEmpty() | 181 ? types.nonNullEmpty() |
| 146 : types.simplifyPhi(null, null, elementType); | 182 : types.simplifyPhi(null, null, elementType); |
| 147 TypeInformation containerType = | 183 TypeInformation containerType = |
| 148 listLiteral.isConst ? types.constListType : types.growableListType; | 184 listLiteral.isConst ? types.constListType : types.growableListType; |
| 149 // TODO(efortuna): Change signature of allocateList and the rest of | 185 // TODO(efortuna): Change signature of allocateList and the rest of |
| 150 // type_system to deal with Kernel elements. | 186 // type_system to deal with Kernel elements. |
| 151 return types.allocateList( | 187 return types.allocateList( |
| 152 containerType, listLiteral, analyzedMember, elementType, length); | 188 containerType, listLiteral, analyzedMember, elementType, length); |
| 153 }); | 189 }); |
| 154 } | 190 } |
| 191 |
| 192 @override |
| 193 TypeInformation visitReturnStatement(ir.ReturnStatement node) { |
| 194 ir.Node expression = node.expression; |
| 195 recordReturnType( |
| 196 expression == null ? types.nullType : expression.accept(this)); |
| 197 locals.seenReturnOrThrow = true; |
| 198 initializationIsIndefinite(); |
| 199 return null; |
| 200 } |
| 155 } | 201 } |
| OLD | NEW |