| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 part of js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 const VERBOSE_OPTIMIZER_HINTS = false; | 7 const VERBOSE_OPTIMIZER_HINTS = false; |
| 8 | 8 |
| 9 class JavaScriptItemCompilationContext extends ItemCompilationContext { | 9 class JavaScriptItemCompilationContext extends ItemCompilationContext { |
| 10 final Set<HInstruction> boundsChecked = new Set<HInstruction>(); | 10 final Set<HInstruction> boundsChecked = new Set<HInstruction>(); |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 bool needToInitializeDispatchProperty = false; | 338 bool needToInitializeDispatchProperty = false; |
| 339 | 339 |
| 340 final Namer namer; | 340 final Namer namer; |
| 341 | 341 |
| 342 /** | 342 /** |
| 343 * A collection of selectors that must have a one shot interceptor | 343 * A collection of selectors that must have a one shot interceptor |
| 344 * generated. | 344 * generated. |
| 345 */ | 345 */ |
| 346 final Map<jsAst.Name, Selector> oneShotInterceptors; | 346 final Map<jsAst.Name, Selector> oneShotInterceptors; |
| 347 | 347 |
| 348 /// All known intercepted members. Collected during resolution. | 348 /** |
| 349 final Map<String, Set<Element>> _interceptedElements = | 349 * The members of instantiated interceptor classes: maps a member name to the |
| 350 <String, Set<Element>>{}; | 350 * list of members that have that name. This map is used by the codegen to |
| 351 | 351 * know whether a send must be intercepted or not. |
| 352 /// Cache for all instantiated intercepted members for [interceptedElements]. | 352 */ |
| 353 Map<String, Set<Element>> _instantiatedInterceptedElements; | 353 final Map<String, Set<Element>> interceptedElements; |
| 354 | 354 |
| 355 /** | 355 /** |
| 356 * The members of mixin classes that are mixed into an instantiated | 356 * The members of mixin classes that are mixed into an instantiated |
| 357 * interceptor class. This is a cached subset of [interceptedElements]. | 357 * interceptor class. This is a cached subset of [interceptedElements]. |
| 358 * | 358 * |
| 359 * Mixin methods are not specialized for the class they are mixed into. | 359 * Mixin methods are not specialized for the class they are mixed into. |
| 360 * Methods mixed into intercepted classes thus always make use of the explicit | 360 * Methods mixed into intercepted classes thus always make use of the explicit |
| 361 * receiver argument, even when mixed into non-interceptor classes. | 361 * receiver argument, even when mixed into non-interceptor classes. |
| 362 * | 362 * |
| 363 * These members must be invoked with a correct explicit receiver even when | 363 * These members must be invoked with a correct explicit receiver even when |
| 364 * the receiver is not an intercepted class. | 364 * the receiver is not an intercepted class. |
| 365 */ | 365 */ |
| 366 final Map<String, Set<Element>> _interceptedMixinElements = | 366 final Map<String, Set<Element>> interceptedMixinElements = |
| 367 new Map<String, Set<Element>>(); | 367 new Map<String, Set<Element>>(); |
| 368 | 368 |
| 369 /** | 369 /** |
| 370 * A map of specialized versions of the [getInterceptorMethod]. | 370 * A map of specialized versions of the [getInterceptorMethod]. |
| 371 * Since [getInterceptorMethod] is a hot method at runtime, we're | 371 * Since [getInterceptorMethod] is a hot method at runtime, we're |
| 372 * always specializing it based on the incoming type. The keys in | 372 * always specializing it based on the incoming type. The keys in |
| 373 * the map are the names of these specialized versions. Note that | 373 * the map are the names of these specialized versions. Note that |
| 374 * the generic version that contains all possible type checks is | 374 * the generic version that contains all possible type checks is |
| 375 * also stored in this map. | 375 * also stored in this map. |
| 376 */ | 376 */ |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 505 final SourceInformationStrategy sourceInformationStrategy; | 505 final SourceInformationStrategy sourceInformationStrategy; |
| 506 | 506 |
| 507 final BackendHelpers helpers; | 507 final BackendHelpers helpers; |
| 508 final BackendImpacts impacts; | 508 final BackendImpacts impacts; |
| 509 | 509 |
| 510 JavaScriptBackend(Compiler compiler, | 510 JavaScriptBackend(Compiler compiler, |
| 511 {bool generateSourceMap: true, | 511 {bool generateSourceMap: true, |
| 512 bool useStartupEmitter: false}) | 512 bool useStartupEmitter: false}) |
| 513 : namer = determineNamer(compiler), | 513 : namer = determineNamer(compiler), |
| 514 oneShotInterceptors = new Map<jsAst.Name, Selector>(), | 514 oneShotInterceptors = new Map<jsAst.Name, Selector>(), |
| 515 interceptedElements = new Map<String, Set<Element>>(), |
| 515 rti = new _RuntimeTypes(compiler), | 516 rti = new _RuntimeTypes(compiler), |
| 516 rtiEncoder = new _RuntimeTypesEncoder(compiler), | 517 rtiEncoder = new _RuntimeTypesEncoder(compiler), |
| 517 specializedGetInterceptors = new Map<jsAst.Name, Set<ClassElement>>(), | 518 specializedGetInterceptors = new Map<jsAst.Name, Set<ClassElement>>(), |
| 518 annotations = new Annotations(compiler), | 519 annotations = new Annotations(compiler), |
| 519 this.sourceInformationStrategy = | 520 this.sourceInformationStrategy = |
| 520 generateSourceMap | 521 generateSourceMap |
| 521 ? (useNewSourceInfo | 522 ? (useNewSourceInfo |
| 522 ? const PositionSourceInformationStrategy() | 523 ? const PositionSourceInformationStrategy() |
| 523 : const StartEndSourceInformationStrategy()) | 524 : const StartEndSourceInformationStrategy()) |
| 524 : const JavaScriptSourceInformationStrategy(), | 525 : const JavaScriptSourceInformationStrategy(), |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 838 } | 839 } |
| 839 | 840 |
| 840 bool isInterceptedName(String name) { | 841 bool isInterceptedName(String name) { |
| 841 return interceptedElements[name] != null; | 842 return interceptedElements[name] != null; |
| 842 } | 843 } |
| 843 | 844 |
| 844 bool isInterceptedSelector(Selector selector) { | 845 bool isInterceptedSelector(Selector selector) { |
| 845 return interceptedElements[selector.name] != null; | 846 return interceptedElements[selector.name] != null; |
| 846 } | 847 } |
| 847 | 848 |
| 848 /// The members of instantiated interceptor classes: maps a member name to the | |
| 849 /// list of members that have that name. This map is used by the codegen to | |
| 850 /// know whether a send must be intercepted or not. | |
| 851 Map<String, Set<Element>> get interceptedElements { | |
| 852 assert(compiler.enqueuer.resolution.queueIsClosed); | |
| 853 if (_instantiatedInterceptedElements == null) { | |
| 854 _instantiatedInterceptedElements = <String, Set<Element>>{}; | |
| 855 _interceptedElements.forEach((String name, Set<Element> members) { | |
| 856 Set<Element> instantiatedMembers = new Set<Element>(); | |
| 857 for (Element member in members) { | |
| 858 if (compiler.world.isInstantiated(member.enclosingClass)) { | |
| 859 instantiatedMembers.add(member); | |
| 860 } | |
| 861 } | |
| 862 if (instantiatedMembers.isNotEmpty) { | |
| 863 _instantiatedInterceptedElements[name] = instantiatedMembers; | |
| 864 } | |
| 865 }); | |
| 866 } | |
| 867 return _instantiatedInterceptedElements; | |
| 868 } | |
| 869 | |
| 870 /** | 849 /** |
| 871 * Returns `true` iff [selector] matches an element defined in a class mixed | 850 * Returns `true` iff [selector] matches an element defined in a class mixed |
| 872 * into an intercepted class. These selectors are not eligible for the 'dummy | 851 * into an intercepted class. These selectors are not eligible for the 'dummy |
| 873 * explicit receiver' optimization. | 852 * explicit receiver' optimization. |
| 874 */ | 853 */ |
| 875 bool isInterceptedMixinSelector(Selector selector, TypeMask mask) { | 854 bool isInterceptedMixinSelector(Selector selector, TypeMask mask) { |
| 876 Set<Element> elements = _interceptedMixinElements.putIfAbsent( | 855 Set<Element> elements = interceptedMixinElements.putIfAbsent( |
| 877 selector.name, | 856 selector.name, |
| 878 () { | 857 () { |
| 879 Set<Element> elements = interceptedElements[selector.name]; | 858 Set<Element> elements = interceptedElements[selector.name]; |
| 880 if (elements == null) return null; | 859 if (elements == null) return null; |
| 881 return elements | 860 return elements |
| 882 .where((element) => | 861 .where((element) => |
| 883 classesMixedIntoInterceptedClasses.contains( | 862 classesMixedIntoInterceptedClasses.contains( |
| 884 element.enclosingClass)) | 863 element.enclosingClass)) |
| 885 .toSet(); | 864 .toSet(); |
| 886 }); | 865 }); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 985 cls.forEachMember((ClassElement classElement, Element member) { | 964 cls.forEachMember((ClassElement classElement, Element member) { |
| 986 if (member.name == Identifiers.call) { | 965 if (member.name == Identifiers.call) { |
| 987 reporter.reportErrorMessage( | 966 reporter.reportErrorMessage( |
| 988 member, | 967 member, |
| 989 MessageKind.CALL_NOT_SUPPORTED_ON_NATIVE_CLASS); | 968 MessageKind.CALL_NOT_SUPPORTED_ON_NATIVE_CLASS); |
| 990 return; | 969 return; |
| 991 } | 970 } |
| 992 if (member.isSynthesized) return; | 971 if (member.isSynthesized) return; |
| 993 // All methods on [Object] are shadowed by [Interceptor]. | 972 // All methods on [Object] are shadowed by [Interceptor]. |
| 994 if (classElement == coreClasses.objectClass) return; | 973 if (classElement == coreClasses.objectClass) return; |
| 995 Set<Element> set = _interceptedElements.putIfAbsent( | 974 Set<Element> set = interceptedElements.putIfAbsent( |
| 996 member.name, () => new Setlet<Element>()); | 975 member.name, () => new Set<Element>()); |
| 997 set.add(member); | 976 set.add(member); |
| 998 }, | 977 }, |
| 999 includeSuperAndInjectedMembers: true); | 978 includeSuperAndInjectedMembers: true); |
| 1000 | 979 |
| 1001 // Walk superclass chain to find mixins. | 980 // Walk superclass chain to find mixins. |
| 1002 for (; cls != null; cls = cls.superclass) { | 981 for (; cls != null; cls = cls.superclass) { |
| 1003 if (cls.isMixinApplication) { | 982 if (cls.isMixinApplication) { |
| 1004 MixinApplicationElement mixinApplication = cls; | 983 MixinApplicationElement mixinApplication = cls; |
| 1005 classesMixedIntoInterceptedClasses.add(mixinApplication.mixin); | 984 classesMixedIntoInterceptedClasses.add(mixinApplication.mixin); |
| 1006 } | 985 } |
| 1007 } | 986 } |
| 1008 } | 987 } |
| 1009 } | 988 } |
| 1010 | 989 |
| 1011 void addInterceptors(ClassElement cls, | 990 void addInterceptors(ClassElement cls, |
| 1012 Enqueuer enqueuer, | 991 Enqueuer enqueuer, |
| 1013 Registry registry) { | 992 Registry registry) { |
| 1014 if (enqueuer.isResolutionQueue) { | 993 if (enqueuer.isResolutionQueue) { |
| 1015 _interceptedClasses.add(helpers.jsInterceptorClass); | 994 _interceptedClasses.add(helpers.jsInterceptorClass); |
| 1016 _interceptedClasses.add(cls); | 995 _interceptedClasses.add(cls); |
| 1017 cls.ensureResolved(resolution); | 996 cls.ensureResolved(resolution); |
| 1018 cls.forEachMember((ClassElement classElement, Element member) { | 997 cls.forEachMember((ClassElement classElement, Element member) { |
| 1019 // All methods on [Object] are shadowed by [Interceptor]. | 998 // All methods on [Object] are shadowed by [Interceptor]. |
| 1020 if (classElement == coreClasses.objectClass) return; | 999 if (classElement == coreClasses.objectClass) return; |
| 1021 Set<Element> set = _interceptedElements.putIfAbsent( | 1000 Set<Element> set = interceptedElements.putIfAbsent( |
| 1022 member.name, () => new Setlet<Element>()); | 1001 member.name, () => new Set<Element>()); |
| 1023 set.add(member); | 1002 set.add(member); |
| 1024 }, | 1003 }, |
| 1025 includeSuperAndInjectedMembers: true); | 1004 includeSuperAndInjectedMembers: true); |
| 1026 } | 1005 } |
| 1027 enqueueClass(enqueuer, cls, registry); | 1006 enqueueClass(enqueuer, cls, registry); |
| 1028 } | 1007 } |
| 1029 | 1008 |
| 1030 Set<ClassElement> get interceptedClasses { | 1009 Set<ClassElement> get interceptedClasses { |
| 1031 assert(compiler.enqueuer.resolution.queueIsClosed); | 1010 assert(compiler.enqueuer.resolution.queueIsClosed); |
| 1032 return _interceptedClasses; | 1011 return _interceptedClasses; |
| (...skipping 2060 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3093 } | 3072 } |
| 3094 } | 3073 } |
| 3095 | 3074 |
| 3096 /// Records that [constant] is used by the element behind [registry]. | 3075 /// Records that [constant] is used by the element behind [registry]. |
| 3097 class Dependency { | 3076 class Dependency { |
| 3098 final ConstantValue constant; | 3077 final ConstantValue constant; |
| 3099 final Element annotatedElement; | 3078 final Element annotatedElement; |
| 3100 | 3079 |
| 3101 const Dependency(this.constant, this.annotatedElement); | 3080 const Dependency(this.constant, this.annotatedElement); |
| 3102 } | 3081 } |
| OLD | NEW |