| 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 15 matching lines...) Expand all Loading... |
| 26 import '../common/resolution.dart'; | 26 import '../common/resolution.dart'; |
| 27 | 27 |
| 28 /// Computes the [ResolutionImpact] for [resolvedAst] through kernel. | 28 /// Computes the [ResolutionImpact] for [resolvedAst] through kernel. |
| 29 ResolutionImpact build(Compiler compiler, ResolvedAst resolvedAst) { | 29 ResolutionImpact build(Compiler compiler, ResolvedAst resolvedAst) { |
| 30 AstElement element = resolvedAst.element; | 30 AstElement element = resolvedAst.element; |
| 31 return compiler.reporter.withCurrentElement(element.implementation, () { | 31 return compiler.reporter.withCurrentElement(element.implementation, () { |
| 32 JavaScriptBackend backend = compiler.backend; | 32 JavaScriptBackend backend = compiler.backend; |
| 33 Kernel kernel = backend.kernelTask.kernel; | 33 Kernel kernel = backend.kernelTask.kernel; |
| 34 KernelAstAdapter astAdapter = new KernelAstAdapter(kernel, compiler.backend, | 34 KernelAstAdapter astAdapter = new KernelAstAdapter(kernel, compiler.backend, |
| 35 resolvedAst, kernel.nodeToAst, kernel.nodeToElement); | 35 resolvedAst, kernel.nodeToAst, kernel.nodeToElement); |
| 36 KernelImpactBuilder builder = new KernelImpactBuilder( | 36 ir.Member member = getIrMember(compiler, resolvedAst); |
| 37 '${resolvedAst.element}', astAdapter, compiler.commonElements); | 37 return buildKernelImpact(member, astAdapter); |
| 38 if (element.isFunction || | 38 }); |
| 39 element.isGetter || | 39 } |
| 40 element.isSetter || | 40 |
| 41 element.isFactoryConstructor) { | 41 ir.Member getIrMember(Compiler compiler, ResolvedAst resolvedAst) { |
| 42 ir.Procedure function = kernel.functions[element]; | 42 AstElement element = resolvedAst.element; |
| 43 if (function == null) { | 43 JavaScriptBackend backend = compiler.backend; |
| 44 throw "FOUND NULL FUNCTION: $element"; | 44 Kernel kernel = backend.kernelTask.kernel; |
| 45 } else { | 45 ir.Member member; |
| 46 return builder.buildProcedure(function); | 46 if (element.isFunction || |
| 47 } | 47 element.isGetter || |
| 48 } else if (element.isGenerativeConstructor) { | 48 element.isSetter || |
| 49 ir.Constructor constructor = kernel.functions[element]; | 49 element.isConstructor) { |
| 50 if (constructor == null) { | 50 member = kernel.functions[element]; |
| 51 throw "FOUND NULL CONSTRUCTOR: $element"; | 51 if (member == null) { |
| 52 } else { | 52 throw "FOUND NULL FUNCTION: $element"; |
| 53 return builder.buildConstructor(constructor); | |
| 54 } | |
| 55 } else if (element.isField) { | |
| 56 ir.Field field = kernel.fields[element]; | |
| 57 if (field == null) { | |
| 58 throw "FOUND NULL FIELD: $element"; | |
| 59 } else { | |
| 60 return builder.buildField(field); | |
| 61 } | |
| 62 } else { | |
| 63 throw new UnsupportedError("Unsupported element: $element"); | |
| 64 } | 53 } |
| 65 }); | 54 } else if (element.isField) { |
| 55 member = kernel.fields[element]; |
| 56 if (member == null) { |
| 57 throw "FOUND NULL FIELD: $element"; |
| 58 } |
| 59 } else { |
| 60 throw new UnsupportedError("Unsupported element: $element"); |
| 61 } |
| 62 return member; |
| 63 } |
| 64 |
| 65 ResolutionImpact buildKernelImpact( |
| 66 ir.Member member, KernelElementAdapter elementAdapter) { |
| 67 KernelImpactBuilder builder = |
| 68 new KernelImpactBuilder('${member.name}', elementAdapter); |
| 69 if (member is ir.Procedure) { |
| 70 return builder.buildProcedure(member); |
| 71 } else if (member is ir.Constructor) { |
| 72 return builder.buildConstructor(member); |
| 73 } else if (member is ir.Field) { |
| 74 return builder.buildField(member); |
| 75 } |
| 76 throw new UnsupportedError("Unsupported member: $member"); |
| 66 } | 77 } |
| 67 | 78 |
| 68 class KernelImpactBuilder extends ir.Visitor { | 79 class KernelImpactBuilder extends ir.Visitor { |
| 69 final ResolutionWorldImpactBuilder impactBuilder; | 80 final ResolutionWorldImpactBuilder impactBuilder; |
| 70 final KernelElementAdapter elementAdapter; | 81 final KernelElementAdapter elementAdapter; |
| 71 final CommonElements commonElements; | |
| 72 | 82 |
| 73 KernelImpactBuilder(String name, this.elementAdapter, this.commonElements) | 83 KernelImpactBuilder(String name, this.elementAdapter) |
| 74 : this.impactBuilder = new ResolutionWorldImpactBuilder(name); | 84 : this.impactBuilder = new ResolutionWorldImpactBuilder(name); |
| 75 | 85 |
| 86 CommonElements get commonElements => elementAdapter.commonElements; |
| 87 |
| 76 /// Add a checked-mode type use of [type] if it is not `dynamic`. | 88 /// Add a checked-mode type use of [type] if it is not `dynamic`. |
| 77 DartType checkType(ir.DartType irType) { | 89 DartType checkType(ir.DartType irType) { |
| 78 DartType type = elementAdapter.getDartType(irType); | 90 DartType type = elementAdapter.getDartType(irType); |
| 79 if (!type.isDynamic) { | 91 if (!type.isDynamic) { |
| 80 impactBuilder.registerTypeUse(new TypeUse.checkedModeCheck(type)); | 92 impactBuilder.registerTypeUse(new TypeUse.checkedModeCheck(type)); |
| 81 } | 93 } |
| 82 return type; | 94 return type; |
| 83 } | 95 } |
| 84 | 96 |
| 85 /// Add checked-mode type use for the parameter type and constant for the | 97 /// Add checked-mode type use for the parameter type and constant for the |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 @override | 282 @override |
| 271 void visitSuperInitializer(ir.SuperInitializer node) { | 283 void visitSuperInitializer(ir.SuperInitializer node) { |
| 272 ConstructorEntity target = elementAdapter.getConstructor(node.target); | 284 ConstructorEntity target = elementAdapter.getConstructor(node.target); |
| 273 _visitArguments(node.arguments); | 285 _visitArguments(node.arguments); |
| 274 impactBuilder.registerStaticUse(new StaticUse.superConstructorInvoke( | 286 impactBuilder.registerStaticUse(new StaticUse.superConstructorInvoke( |
| 275 target, elementAdapter.getCallStructure(node.arguments))); | 287 target, elementAdapter.getCallStructure(node.arguments))); |
| 276 } | 288 } |
| 277 | 289 |
| 278 @override | 290 @override |
| 279 void visitStaticInvocation(ir.StaticInvocation node) { | 291 void visitStaticInvocation(ir.StaticInvocation node) { |
| 280 FunctionEntity target = elementAdapter.getMethod(node.target); | |
| 281 if (node.target.kind == ir.ProcedureKind.Factory) { | 292 if (node.target.kind == ir.ProcedureKind.Factory) { |
| 282 // TODO(johnniwinther): We should not mark the type as instantiated but | 293 // TODO(johnniwinther): We should not mark the type as instantiated but |
| 283 // rather follow the type arguments directly. | 294 // rather follow the type arguments directly. |
| 284 // | 295 // |
| 285 // Consider this: | 296 // Consider this: |
| 286 // | 297 // |
| 287 // abstract class A<T> { | 298 // abstract class A<T> { |
| 288 // factory A.regular() => new B<T>(); | 299 // factory A.regular() => new B<T>(); |
| 289 // factory A.redirect() = B<T>; | 300 // factory A.redirect() = B<T>; |
| 290 // } | 301 // } |
| 291 // | 302 // |
| 292 // class B<T> implements A<T> {} | 303 // class B<T> implements A<T> {} |
| 293 // | 304 // |
| 294 // main() { | 305 // main() { |
| 295 // print(new A<int>.regular() is B<int>); | 306 // print(new A<int>.regular() is B<int>); |
| 296 // print(new A<String>.redirect() is B<String>); | 307 // print(new A<String>.redirect() is B<String>); |
| 297 // } | 308 // } |
| 298 // | 309 // |
| 299 // To track that B is actually instantiated as B<int> and B<String> we | 310 // To track that B is actually instantiated as B<int> and B<String> we |
| 300 // need to follow the type arguments passed to A.regular and A.redirect | 311 // need to follow the type arguments passed to A.regular and A.redirect |
| 301 // to B. Currently, we only do this soundly if we register A<int> and | 312 // to B. Currently, we only do this soundly if we register A<int> and |
| 302 // A<String> as instantiated. We should instead register that A.T is | 313 // A<String> as instantiated. We should instead register that A.T is |
| 303 // instantiated as int and String. | 314 // instantiated as int and String. |
| 304 handleNew(node, node.target, isConst: node.isConst); | 315 handleNew(node, node.target, isConst: node.isConst); |
| 305 } else { | 316 } else { |
| 317 FunctionEntity target = elementAdapter.getMethod(node.target); |
| 306 _visitArguments(node.arguments); | 318 _visitArguments(node.arguments); |
| 307 impactBuilder.registerStaticUse(new StaticUse.staticInvoke( | 319 impactBuilder.registerStaticUse(new StaticUse.staticInvoke( |
| 308 target, elementAdapter.getCallStructure(node.arguments))); | 320 target, elementAdapter.getCallStructure(node.arguments))); |
| 309 } | 321 } |
| 310 switch (elementAdapter.getForeignKind(node)) { | 322 switch (elementAdapter.getForeignKind(node)) { |
| 311 case ForeignKind.JS: | 323 case ForeignKind.JS: |
| 312 impactBuilder.registerNativeData( | 324 impactBuilder.registerNativeData( |
| 313 elementAdapter.getNativeBehaviorForJsCall(node)); | 325 elementAdapter.getNativeBehaviorForJsCall(node)); |
| 314 break; | 326 break; |
| 315 case ForeignKind.JS_BUILTIN: | 327 case ForeignKind.JS_BUILTIN: |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 562 ConstructorEntity target = elementAdapter.getConstructor(node.target); | 574 ConstructorEntity target = elementAdapter.getConstructor(node.target); |
| 563 impactBuilder.registerStaticUse(new StaticUse.superConstructorInvoke( | 575 impactBuilder.registerStaticUse(new StaticUse.superConstructorInvoke( |
| 564 target, elementAdapter.getCallStructure(node.arguments))); | 576 target, elementAdapter.getCallStructure(node.arguments))); |
| 565 } | 577 } |
| 566 | 578 |
| 567 // TODO(johnniwinther): Make this throw and visit child nodes explicitly | 579 // TODO(johnniwinther): Make this throw and visit child nodes explicitly |
| 568 // instead to ensure that we don't visit unwanted parts of the ir. | 580 // instead to ensure that we don't visit unwanted parts of the ir. |
| 569 @override | 581 @override |
| 570 void defaultNode(ir.Node node) => node.visitChildren(this); | 582 void defaultNode(ir.Node node) => node.visitChildren(this); |
| 571 } | 583 } |
| OLD | NEW |