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'; |
11 import '../dart_types.dart'; | 11 import '../dart_types.dart'; |
12 import '../elements/elements.dart'; | 12 import '../elements/elements.dart'; |
13 import '../js_backend/backend.dart' show JavaScriptBackend; | 13 import '../js_backend/backend.dart' show JavaScriptBackend; |
14 import '../kernel/kernel.dart'; | 14 import '../kernel/kernel.dart'; |
15 import '../kernel/kernel_debug.dart'; | 15 import '../kernel/kernel_debug.dart'; |
16 import '../kernel/kernel_visitor.dart'; | 16 import '../kernel/kernel_visitor.dart'; |
17 import '../resolution/registry.dart' show ResolutionWorldImpactBuilder; | 17 import '../resolution/registry.dart' show ResolutionWorldImpactBuilder; |
18 import '../universe/feature.dart'; | 18 import '../universe/feature.dart'; |
19 import '../universe/selector.dart'; | 19 import '../universe/selector.dart'; |
20 import '../universe/use.dart'; | 20 import '../universe/use.dart'; |
21 | 21 |
22 import 'kernel_ast_adapter.dart'; | 22 import 'kernel_ast_adapter.dart'; |
23 import '../common/resolution.dart'; | 23 import '../common/resolution.dart'; |
24 | 24 |
25 /// Computes the [ResolutionImpact] for [resolvedAst] through kernel. | 25 /// Computes the [ResolutionImpact] for [resolvedAst] through kernel. |
26 ResolutionImpact build(Compiler compiler, ResolvedAst resolvedAst) { | 26 ResolutionImpact build(Compiler compiler, ResolvedAst resolvedAst) { |
27 AstElement element = resolvedAst.element.implementation; | 27 AstElement element = resolvedAst.element; |
28 JavaScriptBackend backend = compiler.backend; | 28 JavaScriptBackend backend = compiler.backend; |
29 Kernel kernel = backend.kernelTask.kernel; | 29 Kernel kernel = backend.kernelTask.kernel; |
30 KernelImpactBuilder builder = | 30 KernelImpactBuilder builder = |
31 new KernelImpactBuilder(resolvedAst, compiler, kernel); | 31 new KernelImpactBuilder(resolvedAst, compiler, kernel); |
32 if (element.isFunction) { | 32 if (element.isFunction) { |
33 ir.Procedure function = kernel.functions[element]; | 33 ir.Procedure function = kernel.functions[element]; |
34 if (function == null) { | 34 if (function == null) { |
35 print("FOUND NULL FUNCTION: $element"); | 35 print("FOUND NULL FUNCTION: $element"); |
36 } else { | 36 } else { |
37 return builder.buildProcedure(function); | 37 return builder.buildProcedure(function); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 impactBuilder.registerFeature(Feature.FIELD_WITHOUT_INITIALIZER); | 90 impactBuilder.registerFeature(Feature.FIELD_WITHOUT_INITIALIZER); |
91 } | 91 } |
92 return impactBuilder; | 92 return impactBuilder; |
93 } | 93 } |
94 | 94 |
95 ResolutionImpact buildProcedure(ir.Procedure procedure) { | 95 ResolutionImpact buildProcedure(ir.Procedure procedure) { |
96 if (procedure.kind == ir.ProcedureKind.Method || | 96 if (procedure.kind == ir.ProcedureKind.Method || |
97 procedure.kind == ir.ProcedureKind.Operator) { | 97 procedure.kind == ir.ProcedureKind.Operator) { |
98 checkFunctionTypes(procedure.function); | 98 checkFunctionTypes(procedure.function); |
99 visitNode(procedure.function.body); | 99 visitNode(procedure.function.body); |
| 100 switch (procedure.function.asyncMarker) { |
| 101 case ir.AsyncMarker.Sync: |
| 102 break; |
| 103 case ir.AsyncMarker.SyncStar: |
| 104 impactBuilder.registerFeature(Feature.SYNC_STAR); |
| 105 break; |
| 106 case ir.AsyncMarker.Async: |
| 107 impactBuilder.registerFeature(Feature.ASYNC); |
| 108 break; |
| 109 case ir.AsyncMarker.AsyncStar: |
| 110 impactBuilder.registerFeature(Feature.ASYNC_STAR); |
| 111 break; |
| 112 case ir.AsyncMarker.SyncYielding: |
| 113 compiler.reporter.internalError(resolvedAst.element, |
| 114 "Unexpected async marker: ${procedure.function.asyncMarker}"); |
| 115 } |
100 } else { | 116 } else { |
101 compiler.reporter.internalError( | 117 compiler.reporter.internalError( |
102 resolvedAst.element, | 118 resolvedAst.element, |
103 "Unable to compute resolution impact for this kind of Kernel " | 119 "Unable to compute resolution impact for this kind of Kernel " |
104 "procedure: ${procedure.kind}"); | 120 "procedure: ${procedure.kind}"); |
105 } | 121 } |
106 return impactBuilder; | 122 return impactBuilder; |
107 } | 123 } |
108 | 124 |
109 void visitNode(ir.Node node) => node?.accept(this); | 125 void visitNode(ir.Node node) => node?.accept(this); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 visitNode(entry.key); | 208 visitNode(entry.key); |
193 visitNode(entry.value); | 209 visitNode(entry.value); |
194 } | 210 } |
195 | 211 |
196 void _visitArguments(ir.Arguments arguments) { | 212 void _visitArguments(ir.Arguments arguments) { |
197 arguments.positional.forEach(visitNode); | 213 arguments.positional.forEach(visitNode); |
198 arguments.named.forEach(visitNode); | 214 arguments.named.forEach(visitNode); |
199 } | 215 } |
200 | 216 |
201 @override | 217 @override |
202 void visitStaticInvocation(ir.StaticInvocation invocation) { | 218 void visitConstructorInvocation(ir.ConstructorInvocation node) { |
203 _visitArguments(invocation.arguments); | 219 handleNew(node, node.target); |
204 Element target = astAdapter.getElement(invocation.target).declaration; | 220 } |
| 221 |
| 222 void handleNew(ir.InvocationExpression node, ir.Member target) { |
| 223 _visitArguments(node.arguments); |
| 224 Element element = astAdapter.getElement(target).declaration; |
| 225 impactBuilder.registerStaticUse(new StaticUse.constructorInvoke( |
| 226 element, astAdapter.getCallStructure(node.arguments))); |
| 227 ClassElement cls = astAdapter.getElement(target.enclosingClass); |
| 228 List<DartType> typeArguments = |
| 229 astAdapter.getDartTypes(node.arguments.types); |
| 230 impactBuilder.registerTypeUse( |
| 231 new TypeUse.instantiation(new InterfaceType(cls, typeArguments))); |
| 232 if (typeArguments.any((DartType type) => !type.isDynamic)) { |
| 233 impactBuilder.registerFeature(Feature.TYPE_VARIABLE_BOUNDS_CHECK); |
| 234 } |
| 235 } |
| 236 |
| 237 @override |
| 238 void visitStaticInvocation(ir.StaticInvocation node) { |
| 239 Element target = astAdapter.getElement(node.target).declaration; |
205 if (target.isFactoryConstructor) { | 240 if (target.isFactoryConstructor) { |
206 impactBuilder.registerStaticUse(new StaticUse.constructorInvoke( | |
207 target, astAdapter.getCallStructure(invocation.arguments))); | |
208 // TODO(johnniwinther): We should not mark the type as instantiated but | 241 // TODO(johnniwinther): We should not mark the type as instantiated but |
209 // rather follow the type arguments directly. | 242 // rather follow the type arguments directly. |
210 // | 243 // |
211 // Consider this: | 244 // Consider this: |
212 // | 245 // |
213 // abstract class A<T> { | 246 // abstract class A<T> { |
214 // factory A.regular() => new B<T>(); | 247 // factory A.regular() => new B<T>(); |
215 // factory A.redirect() = B<T>; | 248 // factory A.redirect() = B<T>; |
216 // } | 249 // } |
217 // | 250 // |
218 // class B<T> implements A<T> {} | 251 // class B<T> implements A<T> {} |
219 // | 252 // |
220 // main() { | 253 // main() { |
221 // print(new A<int>.regular() is B<int>); | 254 // print(new A<int>.regular() is B<int>); |
222 // print(new A<String>.redirect() is B<String>); | 255 // print(new A<String>.redirect() is B<String>); |
223 // } | 256 // } |
224 // | 257 // |
225 // To track that B is actually instantiated as B<int> and B<String> we | 258 // To track that B is actually instantiated as B<int> and B<String> we |
226 // need to follow the type arguments passed to A.regular and A.redirect | 259 // need to follow the type arguments passed to A.regular and A.redirect |
227 // to B. Currently, we only do this soundly if we register A<int> and | 260 // to B. Currently, we only do this soundly if we register A<int> and |
228 // A<String> as instantiated. We should instead register that A.T is | 261 // A<String> as instantiated. We should instead register that A.T is |
229 // instantiated as int and String. | 262 // instantiated as int and String. |
230 ClassElement cls = | 263 handleNew(node, node.target); |
231 astAdapter.getElement(invocation.target.enclosingClass); | |
232 List<DartType> typeArguments = | |
233 astAdapter.getDartTypes(invocation.arguments.types); | |
234 impactBuilder.registerTypeUse( | |
235 new TypeUse.instantiation(new InterfaceType(cls, typeArguments))); | |
236 if (typeArguments.any((DartType type) => !type.isDynamic)) { | |
237 impactBuilder.registerFeature(Feature.TYPE_VARIABLE_BOUNDS_CHECK); | |
238 } | |
239 } else { | 264 } else { |
| 265 _visitArguments(node.arguments); |
240 impactBuilder.registerStaticUse(new StaticUse.staticInvoke( | 266 impactBuilder.registerStaticUse(new StaticUse.staticInvoke( |
241 target, astAdapter.getCallStructure(invocation.arguments))); | 267 target, astAdapter.getCallStructure(node.arguments))); |
242 } | 268 } |
243 } | 269 } |
244 | 270 |
245 @override | 271 @override |
246 void visitStaticGet(ir.StaticGet node) { | 272 void visitStaticGet(ir.StaticGet node) { |
247 ir.Member target = node.target; | 273 ir.Member target = node.target; |
248 Element element = astAdapter.getElement(target).declaration; | 274 Element element = astAdapter.getElement(target).declaration; |
249 if (target is ir.Procedure && target.kind == ir.ProcedureKind.Method) { | 275 if (target is ir.Procedure && target.kind == ir.ProcedureKind.Method) { |
250 impactBuilder.registerStaticUse(new StaticUse.staticTearOff(element)); | 276 impactBuilder.registerStaticUse(new StaticUse.staticTearOff(element)); |
251 } else { | 277 } else { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 @override | 343 @override |
318 void visitVariableDeclaration(ir.VariableDeclaration node) { | 344 void visitVariableDeclaration(ir.VariableDeclaration node) { |
319 checkType(node.type); | 345 checkType(node.type); |
320 if (node.initializer != null) { | 346 if (node.initializer != null) { |
321 visitNode(node.initializer); | 347 visitNode(node.initializer); |
322 } else { | 348 } else { |
323 impactBuilder.registerFeature(Feature.LOCAL_WITHOUT_INITIALIZER); | 349 impactBuilder.registerFeature(Feature.LOCAL_WITHOUT_INITIALIZER); |
324 } | 350 } |
325 } | 351 } |
326 | 352 |
| 353 @override |
| 354 void visitIsExpression(ir.IsExpression node) { |
| 355 impactBuilder.registerTypeUse( |
| 356 new TypeUse.isCheck(astAdapter.getDartType(node.type))); |
| 357 } |
| 358 |
| 359 @override |
| 360 void visitAsExpression(ir.AsExpression node) { |
| 361 impactBuilder |
| 362 .registerTypeUse(new TypeUse.asCast(astAdapter.getDartType(node.type))); |
| 363 } |
| 364 |
| 365 @override |
| 366 void visitThrow(ir.Throw node) { |
| 367 impactBuilder.registerFeature(Feature.THROW_EXPRESSION); |
| 368 visitNode(node.expression); |
| 369 } |
| 370 |
| 371 @override |
| 372 void visitForInStatement(ir.ForInStatement node) { |
| 373 visitNode(node.variable); |
| 374 visitNode(node.iterable); |
| 375 visitNode(node.body); |
| 376 if (node.isAsync) { |
| 377 impactBuilder.registerFeature(Feature.ASYNC_FOR_IN); |
| 378 } else { |
| 379 impactBuilder.registerFeature(Feature.SYNC_FOR_IN); |
| 380 impactBuilder |
| 381 .registerDynamicUse(new DynamicUse(Selectors.iterator, null)); |
| 382 } |
| 383 impactBuilder.registerDynamicUse(new DynamicUse(Selectors.current, null)); |
| 384 impactBuilder.registerDynamicUse(new DynamicUse(Selectors.moveNext, null)); |
| 385 } |
| 386 |
327 // TODO(johnniwinther): Make this throw and visit child nodes explicitly | 387 // TODO(johnniwinther): Make this throw and visit child nodes explicitly |
328 // instead to ensure that we don't visit unwanted parts of the ir. | 388 // instead to ensure that we don't visit unwanted parts of the ir. |
329 @override | 389 @override |
330 void defaultNode(ir.Node node) => node.visitChildren(this); | 390 void defaultNode(ir.Node node) => node.visitChildren(this); |
331 } | 391 } |
OLD | NEW |