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 |