| 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 /** | 348 /// All known intercepted members. Collected during resolution. |
| 349 * The members of instantiated interceptor classes: maps a member name to the | 349 final Map<String, Set<Element>> _interceptedElements = |
| 350 * list of members that have that name. This map is used by the codegen to | 350 <String, Set<Element>>{}; |
| 351 * know whether a send must be intercepted or not. | 351 |
| 352 */ | 352 /// Cache for all instantiated intercepted members for [interceptedElements]. |
| 353 final Map<String, Set<Element>> interceptedElements; | 353 Map<String, Set<Element>> _instantiatedInterceptedElements; |
| 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>>(), | |
| 516 rti = new _RuntimeTypes(compiler), | 515 rti = new _RuntimeTypes(compiler), |
| 517 rtiEncoder = new _RuntimeTypesEncoder(compiler), | 516 rtiEncoder = new _RuntimeTypesEncoder(compiler), |
| 518 specializedGetInterceptors = new Map<jsAst.Name, Set<ClassElement>>(), | 517 specializedGetInterceptors = new Map<jsAst.Name, Set<ClassElement>>(), |
| 519 annotations = new Annotations(compiler), | 518 annotations = new Annotations(compiler), |
| 520 this.sourceInformationStrategy = | 519 this.sourceInformationStrategy = |
| 521 generateSourceMap | 520 generateSourceMap |
| 522 ? (useNewSourceInfo | 521 ? (useNewSourceInfo |
| 523 ? const PositionSourceInformationStrategy() | 522 ? const PositionSourceInformationStrategy() |
| 524 : const StartEndSourceInformationStrategy()) | 523 : const StartEndSourceInformationStrategy()) |
| 525 : const JavaScriptSourceInformationStrategy(), | 524 : const JavaScriptSourceInformationStrategy(), |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 839 } | 838 } |
| 840 | 839 |
| 841 bool isInterceptedName(String name) { | 840 bool isInterceptedName(String name) { |
| 842 return interceptedElements[name] != null; | 841 return interceptedElements[name] != null; |
| 843 } | 842 } |
| 844 | 843 |
| 845 bool isInterceptedSelector(Selector selector) { | 844 bool isInterceptedSelector(Selector selector) { |
| 846 return interceptedElements[selector.name] != null; | 845 return interceptedElements[selector.name] != null; |
| 847 } | 846 } |
| 848 | 847 |
| 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 |
| 849 /** | 870 /** |
| 850 * Returns `true` iff [selector] matches an element defined in a class mixed | 871 * Returns `true` iff [selector] matches an element defined in a class mixed |
| 851 * into an intercepted class. These selectors are not eligible for the 'dummy | 872 * into an intercepted class. These selectors are not eligible for the 'dummy |
| 852 * explicit receiver' optimization. | 873 * explicit receiver' optimization. |
| 853 */ | 874 */ |
| 854 bool isInterceptedMixinSelector(Selector selector, TypeMask mask) { | 875 bool isInterceptedMixinSelector(Selector selector, TypeMask mask) { |
| 855 Set<Element> elements = interceptedMixinElements.putIfAbsent( | 876 Set<Element> elements = _interceptedMixinElements.putIfAbsent( |
| 856 selector.name, | 877 selector.name, |
| 857 () { | 878 () { |
| 858 Set<Element> elements = interceptedElements[selector.name]; | 879 Set<Element> elements = interceptedElements[selector.name]; |
| 859 if (elements == null) return null; | 880 if (elements == null) return null; |
| 860 return elements | 881 return elements |
| 861 .where((element) => | 882 .where((element) => |
| 862 classesMixedIntoInterceptedClasses.contains( | 883 classesMixedIntoInterceptedClasses.contains( |
| 863 element.enclosingClass)) | 884 element.enclosingClass)) |
| 864 .toSet(); | 885 .toSet(); |
| 865 }); | 886 }); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 964 cls.forEachMember((ClassElement classElement, Element member) { | 985 cls.forEachMember((ClassElement classElement, Element member) { |
| 965 if (member.name == Identifiers.call) { | 986 if (member.name == Identifiers.call) { |
| 966 reporter.reportErrorMessage( | 987 reporter.reportErrorMessage( |
| 967 member, | 988 member, |
| 968 MessageKind.CALL_NOT_SUPPORTED_ON_NATIVE_CLASS); | 989 MessageKind.CALL_NOT_SUPPORTED_ON_NATIVE_CLASS); |
| 969 return; | 990 return; |
| 970 } | 991 } |
| 971 if (member.isSynthesized) return; | 992 if (member.isSynthesized) return; |
| 972 // All methods on [Object] are shadowed by [Interceptor]. | 993 // All methods on [Object] are shadowed by [Interceptor]. |
| 973 if (classElement == coreClasses.objectClass) return; | 994 if (classElement == coreClasses.objectClass) return; |
| 974 Set<Element> set = interceptedElements.putIfAbsent( | 995 Set<Element> set = _interceptedElements.putIfAbsent( |
| 975 member.name, () => new Set<Element>()); | 996 member.name, () => new Setlet<Element>()); |
| 976 set.add(member); | 997 set.add(member); |
| 977 }, | 998 }, |
| 978 includeSuperAndInjectedMembers: true); | 999 includeSuperAndInjectedMembers: true); |
| 979 | 1000 |
| 980 // Walk superclass chain to find mixins. | 1001 // Walk superclass chain to find mixins. |
| 981 for (; cls != null; cls = cls.superclass) { | 1002 for (; cls != null; cls = cls.superclass) { |
| 982 if (cls.isMixinApplication) { | 1003 if (cls.isMixinApplication) { |
| 983 MixinApplicationElement mixinApplication = cls; | 1004 MixinApplicationElement mixinApplication = cls; |
| 984 classesMixedIntoInterceptedClasses.add(mixinApplication.mixin); | 1005 classesMixedIntoInterceptedClasses.add(mixinApplication.mixin); |
| 985 } | 1006 } |
| 986 } | 1007 } |
| 987 } | 1008 } |
| 988 } | 1009 } |
| 989 | 1010 |
| 990 void addInterceptors(ClassElement cls, | 1011 void addInterceptors(ClassElement cls, |
| 991 Enqueuer enqueuer, | 1012 Enqueuer enqueuer, |
| 992 Registry registry) { | 1013 Registry registry) { |
| 993 if (enqueuer.isResolutionQueue) { | 1014 if (enqueuer.isResolutionQueue) { |
| 994 _interceptedClasses.add(helpers.jsInterceptorClass); | 1015 _interceptedClasses.add(helpers.jsInterceptorClass); |
| 995 _interceptedClasses.add(cls); | 1016 _interceptedClasses.add(cls); |
| 996 cls.ensureResolved(resolution); | 1017 cls.ensureResolved(resolution); |
| 997 cls.forEachMember((ClassElement classElement, Element member) { | 1018 cls.forEachMember((ClassElement classElement, Element member) { |
| 998 // All methods on [Object] are shadowed by [Interceptor]. | 1019 // All methods on [Object] are shadowed by [Interceptor]. |
| 999 if (classElement == coreClasses.objectClass) return; | 1020 if (classElement == coreClasses.objectClass) return; |
| 1000 Set<Element> set = interceptedElements.putIfAbsent( | 1021 Set<Element> set = _interceptedElements.putIfAbsent( |
| 1001 member.name, () => new Set<Element>()); | 1022 member.name, () => new Setlet<Element>()); |
| 1002 set.add(member); | 1023 set.add(member); |
| 1003 }, | 1024 }, |
| 1004 includeSuperAndInjectedMembers: true); | 1025 includeSuperAndInjectedMembers: true); |
| 1005 } | 1026 } |
| 1006 enqueueClass(enqueuer, cls, registry); | 1027 enqueueClass(enqueuer, cls, registry); |
| 1007 } | 1028 } |
| 1008 | 1029 |
| 1009 Set<ClassElement> get interceptedClasses { | 1030 Set<ClassElement> get interceptedClasses { |
| 1010 assert(compiler.enqueuer.resolution.queueIsClosed); | 1031 assert(compiler.enqueuer.resolution.queueIsClosed); |
| 1011 return _interceptedClasses; | 1032 return _interceptedClasses; |
| (...skipping 2029 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3041 } | 3062 } |
| 3042 } | 3063 } |
| 3043 | 3064 |
| 3044 /// Records that [constant] is used by the element behind [registry]. | 3065 /// Records that [constant] is used by the element behind [registry]. |
| 3045 class Dependency { | 3066 class Dependency { |
| 3046 final ConstantValue constant; | 3067 final ConstantValue constant; |
| 3047 final Element annotatedElement; | 3068 final Element annotatedElement; |
| 3048 | 3069 |
| 3049 const Dependency(this.constant, this.annotatedElement); | 3070 const Dependency(this.constant, this.annotatedElement); |
| 3050 } | 3071 } |
| OLD | NEW |