| 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 |