| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 '../common.dart'; | 7 import '../common.dart'; |
| 8 import '../common/names.dart'; | 8 import '../common/names.dart'; |
| 9 import '../compiler.dart'; | 9 import '../compiler.dart'; |
| 10 import '../constants/expressions.dart'; | 10 import '../constants/expressions.dart'; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 | 65 |
| 66 /// Add a checked-mode type use of [type] if it is not `dynamic`. | 66 /// Add a checked-mode type use of [type] if it is not `dynamic`. |
| 67 DartType checkType(ir.DartType irType) { | 67 DartType checkType(ir.DartType irType) { |
| 68 DartType type = astAdapter.getDartType(irType); | 68 DartType type = astAdapter.getDartType(irType); |
| 69 if (!type.isDynamic) { | 69 if (!type.isDynamic) { |
| 70 impactBuilder.registerTypeUse(new TypeUse.checkedModeCheck(type)); | 70 impactBuilder.registerTypeUse(new TypeUse.checkedModeCheck(type)); |
| 71 } | 71 } |
| 72 return type; | 72 return type; |
| 73 } | 73 } |
| 74 | 74 |
| 75 /// Add a checked-mode type use of return type and parameters of [node]. |
| 76 void checkFunctionTypes(ir.FunctionNode node) { |
| 77 checkType(node.returnType); |
| 78 node.positionalParameters.forEach((v) => checkType(v.type)); |
| 79 node.namedParameters.forEach((v) => checkType(v.type)); |
| 80 } |
| 81 |
| 75 ResolutionImpact buildField(ir.Field field) { | 82 ResolutionImpact buildField(ir.Field field) { |
| 76 checkType(field.type); | 83 checkType(field.type); |
| 77 if (field.initializer != null) { | 84 if (field.initializer != null) { |
| 78 field.initializer.accept(this); | 85 visitNode(field.initializer); |
| 79 } else { | 86 } else { |
| 80 impactBuilder.registerFeature(Feature.FIELD_WITHOUT_INITIALIZER); | 87 impactBuilder.registerFeature(Feature.FIELD_WITHOUT_INITIALIZER); |
| 81 } | 88 } |
| 82 return impactBuilder; | 89 return impactBuilder; |
| 83 } | 90 } |
| 84 | 91 |
| 85 ResolutionImpact buildProcedure(ir.Procedure procedure) { | 92 ResolutionImpact buildProcedure(ir.Procedure procedure) { |
| 86 if (procedure.kind == ir.ProcedureKind.Method || | 93 if (procedure.kind == ir.ProcedureKind.Method || |
| 87 procedure.kind == ir.ProcedureKind.Operator) { | 94 procedure.kind == ir.ProcedureKind.Operator) { |
| 88 checkType(procedure.function.returnType); | 95 checkFunctionTypes(procedure.function); |
| 89 procedure.function.positionalParameters.forEach((v) => checkType(v.type)); | 96 visitNode(procedure.function.body); |
| 90 procedure.function.namedParameters.forEach((v) => checkType(v.type)); | |
| 91 procedure.function.body.accept(this); | |
| 92 } else { | 97 } else { |
| 93 compiler.reporter.internalError( | 98 compiler.reporter.internalError( |
| 94 resolvedAst.element, | 99 resolvedAst.element, |
| 95 "Unable to compute resolution impact for this kind of Kernel " | 100 "Unable to compute resolution impact for this kind of Kernel " |
| 96 "procedure: ${procedure.kind}"); | 101 "procedure: ${procedure.kind}"); |
| 97 } | 102 } |
| 98 return impactBuilder; | 103 return impactBuilder; |
| 99 } | 104 } |
| 100 | 105 |
| 106 void visitNode(ir.Node node) => node?.accept(this); |
| 107 |
| 101 void visitNodes(Iterable<ir.Node> nodes) { | 108 void visitNodes(Iterable<ir.Node> nodes) { |
| 102 nodes.forEach((ir.Node node) => node.accept(this)); | 109 nodes.forEach(visitNode); |
| 103 } | 110 } |
| 104 | 111 |
| 105 @override | 112 @override |
| 106 void visitBlock(ir.Block block) => visitNodes(block.statements); | 113 void visitBlock(ir.Block block) => visitNodes(block.statements); |
| 107 | 114 |
| 108 @override | 115 @override |
| 109 void visitExpressionStatement(ir.ExpressionStatement exprStatement) { | 116 void visitExpressionStatement(ir.ExpressionStatement exprStatement) { |
| 110 exprStatement.expression.accept(this); | 117 visitNode(exprStatement.expression); |
| 111 } | 118 } |
| 112 | 119 |
| 113 @override | 120 @override |
| 114 void visitReturnStatement(ir.ReturnStatement returnStatement) { | 121 void visitReturnStatement(ir.ReturnStatement returnStatement) { |
| 115 returnStatement.expression?.accept(this); | 122 visitNode(returnStatement.expression); |
| 116 } | 123 } |
| 117 | 124 |
| 118 @override | 125 @override |
| 119 void visitIfStatement(ir.IfStatement ifStatement) { | 126 void visitIfStatement(ir.IfStatement ifStatement) { |
| 120 ifStatement.condition.accept(this); | 127 visitNode(ifStatement.condition); |
| 121 ifStatement.then.accept(this); | 128 visitNode(ifStatement.then); |
| 122 ifStatement.otherwise?.accept(this); | 129 visitNode(ifStatement.otherwise); |
| 123 } | 130 } |
| 124 | 131 |
| 125 @override | 132 @override |
| 126 void visitIntLiteral(ir.IntLiteral literal) { | 133 void visitIntLiteral(ir.IntLiteral literal) { |
| 127 impactBuilder | 134 impactBuilder |
| 128 .registerConstantLiteral(new IntConstantExpression(literal.value)); | 135 .registerConstantLiteral(new IntConstantExpression(literal.value)); |
| 129 } | 136 } |
| 130 | 137 |
| 131 @override | 138 @override |
| 132 void visitDoubleLiteral(ir.DoubleLiteral literal) { | 139 void visitDoubleLiteral(ir.DoubleLiteral literal) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 visitNodes(literal.entries); | 179 visitNodes(literal.entries); |
| 173 DartType keyType = checkType(literal.keyType); | 180 DartType keyType = checkType(literal.keyType); |
| 174 DartType valueType = checkType(literal.valueType); | 181 DartType valueType = checkType(literal.valueType); |
| 175 impactBuilder.registerMapLiteral(new MapLiteralUse( | 182 impactBuilder.registerMapLiteral(new MapLiteralUse( |
| 176 compiler.coreTypes.mapType(keyType, valueType), | 183 compiler.coreTypes.mapType(keyType, valueType), |
| 177 isConstant: literal.isConst, | 184 isConstant: literal.isConst, |
| 178 isEmpty: literal.entries.isEmpty)); | 185 isEmpty: literal.entries.isEmpty)); |
| 179 } | 186 } |
| 180 | 187 |
| 181 void visitMapEntry(ir.MapEntry entry) { | 188 void visitMapEntry(ir.MapEntry entry) { |
| 182 entry.key.accept(this); | 189 visitNode(entry.key); |
| 183 entry.value.accept(this); | 190 visitNode(entry.value); |
| 184 } | 191 } |
| 185 | 192 |
| 186 void _visitArguments(ir.Arguments arguments) { | 193 void _visitArguments(ir.Arguments arguments) { |
| 187 for (ir.Expression argument in arguments.positional) { | 194 arguments.positional.forEach(visitNode); |
| 188 argument.accept(this); | 195 arguments.named.forEach(visitNode); |
| 189 } | |
| 190 for (ir.NamedExpression argument in arguments.named) { | |
| 191 argument.value.accept(this); | |
| 192 } | |
| 193 } | 196 } |
| 194 | 197 |
| 195 @override | 198 @override |
| 196 void visitStaticInvocation(ir.StaticInvocation invocation) { | 199 void visitStaticInvocation(ir.StaticInvocation invocation) { |
| 197 _visitArguments(invocation.arguments); | 200 _visitArguments(invocation.arguments); |
| 198 Element target = astAdapter.getElement(invocation.target).declaration; | 201 Element target = astAdapter.getElement(invocation.target).declaration; |
| 199 if (target.isFactoryConstructor) { | 202 if (target.isFactoryConstructor) { |
| 200 impactBuilder.registerStaticUse(new StaticUse.constructorInvoke( | 203 impactBuilder.registerStaticUse(new StaticUse.constructorInvoke( |
| 201 target, astAdapter.getCallStructure(invocation.arguments))); | 204 target, astAdapter.getCallStructure(invocation.arguments))); |
| 202 // TODO(johnniwinther): We should not mark the type as instantiated but | 205 // TODO(johnniwinther): We should not mark the type as instantiated but |
| (...skipping 28 matching lines...) Expand all Loading... |
| 231 impactBuilder.registerFeature(Feature.TYPE_VARIABLE_BOUNDS_CHECK); | 234 impactBuilder.registerFeature(Feature.TYPE_VARIABLE_BOUNDS_CHECK); |
| 232 } | 235 } |
| 233 } else { | 236 } else { |
| 234 impactBuilder.registerStaticUse(new StaticUse.staticInvoke( | 237 impactBuilder.registerStaticUse(new StaticUse.staticInvoke( |
| 235 target, astAdapter.getCallStructure(invocation.arguments))); | 238 target, astAdapter.getCallStructure(invocation.arguments))); |
| 236 } | 239 } |
| 237 } | 240 } |
| 238 | 241 |
| 239 @override | 242 @override |
| 240 void visitStaticGet(ir.StaticGet node) { | 243 void visitStaticGet(ir.StaticGet node) { |
| 241 Element target = astAdapter.getElement(node.target).declaration; | 244 ir.Member target = node.target; |
| 242 impactBuilder.registerStaticUse(new StaticUse.staticGet(target)); | 245 Element element = astAdapter.getElement(target).declaration; |
| 246 if (target is ir.Procedure && target.kind == ir.ProcedureKind.Method) { |
| 247 impactBuilder.registerStaticUse(new StaticUse.staticTearOff(element)); |
| 248 } else { |
| 249 impactBuilder.registerStaticUse(new StaticUse.staticGet(element)); |
| 250 } |
| 243 } | 251 } |
| 244 | 252 |
| 245 @override | 253 @override |
| 246 void visitMethodInvocation(ir.MethodInvocation invocation) { | 254 void visitMethodInvocation(ir.MethodInvocation invocation) { |
| 247 var receiver = invocation.receiver; | 255 var receiver = invocation.receiver; |
| 248 if (receiver is ir.VariableGet && | 256 if (receiver is ir.VariableGet && |
| 249 receiver.variable.isFinal && | 257 receiver.variable.isFinal && |
| 250 receiver.variable.parent is ir.FunctionDeclaration) { | 258 receiver.variable.parent is ir.FunctionDeclaration) { |
| 251 // Invocation of a local function. No need for dynamic use. | 259 // Invocation of a local function. No need for dynamic use. |
| 252 } else { | 260 } else { |
| 253 invocation.receiver.accept(this); | 261 visitNode(invocation.receiver); |
| 254 impactBuilder.registerDynamicUse( | 262 impactBuilder.registerDynamicUse( |
| 255 new DynamicUse(astAdapter.getSelector(invocation), null)); | 263 new DynamicUse(astAdapter.getSelector(invocation), null)); |
| 256 } | 264 } |
| 257 _visitArguments(invocation.arguments); | 265 _visitArguments(invocation.arguments); |
| 258 } | 266 } |
| 259 | 267 |
| 260 @override | 268 @override |
| 261 void visitPropertyGet(ir.PropertyGet node) { | 269 void visitPropertyGet(ir.PropertyGet node) { |
| 262 node.receiver.accept(this); | 270 visitNode(node.receiver); |
| 263 impactBuilder.registerDynamicUse(new DynamicUse( | 271 impactBuilder.registerDynamicUse(new DynamicUse( |
| 264 new Selector.getter(astAdapter.getName(node.name)), null)); | 272 new Selector.getter(astAdapter.getName(node.name)), null)); |
| 265 } | 273 } |
| 266 | 274 |
| 267 @override | 275 @override |
| 268 void visitPropertySet(ir.PropertySet node) { | 276 void visitPropertySet(ir.PropertySet node) { |
| 269 node.receiver.accept(this); | 277 visitNode(node.receiver); |
| 270 node.value.accept(this); | 278 visitNode(node.value); |
| 271 impactBuilder.registerDynamicUse(new DynamicUse( | 279 impactBuilder.registerDynamicUse(new DynamicUse( |
| 272 new Selector.setter(astAdapter.getName(node.name)), null)); | 280 new Selector.setter(astAdapter.getName(node.name)), null)); |
| 273 } | 281 } |
| 274 | 282 |
| 275 @override | 283 @override |
| 276 void visitAssertStatement(ir.AssertStatement node) { | 284 void visitAssertStatement(ir.AssertStatement node) { |
| 277 impactBuilder.registerFeature( | 285 impactBuilder.registerFeature( |
| 278 node.message != null ? Feature.ASSERT_WITH_MESSAGE : Feature.ASSERT); | 286 node.message != null ? Feature.ASSERT_WITH_MESSAGE : Feature.ASSERT); |
| 279 node.visitChildren(this); | 287 visitNode(node.condition); |
| 288 visitNode(node.message); |
| 280 } | 289 } |
| 281 | 290 |
| 282 @override | 291 @override |
| 283 void visitStringConcatenation(ir.StringConcatenation node) { | 292 void visitStringConcatenation(ir.StringConcatenation node) { |
| 284 impactBuilder.registerFeature(Feature.STRING_INTERPOLATION); | 293 impactBuilder.registerFeature(Feature.STRING_INTERPOLATION); |
| 285 impactBuilder.registerFeature(Feature.STRING_JUXTAPOSITION); | 294 impactBuilder.registerFeature(Feature.STRING_JUXTAPOSITION); |
| 286 node.visitChildren(this); | 295 visitNodes(node.expressions); |
| 287 } | 296 } |
| 288 | 297 |
| 289 @override | 298 @override |
| 290 void visitFunctionDeclaration(ir.FunctionDeclaration node) { | 299 void visitFunctionDeclaration(ir.FunctionDeclaration node) { |
| 291 impactBuilder | 300 impactBuilder |
| 292 .registerStaticUse(new StaticUse.closure(astAdapter.getElement(node))); | 301 .registerStaticUse(new StaticUse.closure(astAdapter.getElement(node))); |
| 293 node.visitChildren(this); | 302 checkFunctionTypes(node.function); |
| 303 visitNode(node.function.body); |
| 294 } | 304 } |
| 295 | 305 |
| 296 @override | 306 @override |
| 307 void visitFunctionExpression(ir.FunctionExpression node) { |
| 308 impactBuilder |
| 309 .registerStaticUse(new StaticUse.closure(astAdapter.getElement(node))); |
| 310 checkFunctionTypes(node.function); |
| 311 visitNode(node.function.body); |
| 312 } |
| 313 |
| 314 @override |
| 315 void visitVariableDeclaration(ir.VariableDeclaration node) { |
| 316 checkType(node.type); |
| 317 if (node.initializer != null) { |
| 318 visitNode(node.initializer); |
| 319 } else { |
| 320 impactBuilder.registerFeature(Feature.LOCAL_WITHOUT_INITIALIZER); |
| 321 } |
| 322 } |
| 323 |
| 324 // TODO(johnniwinther): Make this throw and visit child nodes explicitly |
| 325 // instead to ensure that we don't visit unwanted parts of the ir. |
| 326 @override |
| 297 void defaultNode(ir.Node node) => node.visitChildren(this); | 327 void defaultNode(ir.Node node) => node.visitChildren(this); |
| 298 } | 328 } |
| OLD | NEW |