| 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 library js_backend.backend; | 5 library js_backend.backend; |
| 6 | 6 |
| 7 import 'dart:async' show Future; | 7 import 'dart:async' show Future; |
| 8 | 8 |
| 9 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames; | 9 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames; |
| 10 | 10 |
| 11 import '../closure.dart'; | 11 import '../closure.dart'; |
| 12 import '../common.dart'; | 12 import '../common.dart'; |
| 13 import '../common/backend_api.dart' | 13 import '../common/backend_api.dart' |
| 14 show BackendClasses, ImpactTransformer, ForeignResolver, NativeRegistry; | 14 show BackendClasses, ImpactTransformer, ForeignResolver, NativeRegistry; |
| 15 import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem; | 15 import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem; |
| 16 import '../common/names.dart' show Identifiers, Uris; | 16 import '../common/names.dart' show Identifiers, Uris; |
| 17 import '../common/resolution.dart' | 17 import '../common/resolution.dart' |
| 18 show Frontend, Resolution, ResolutionImpact, Target; | 18 show Frontend, Resolution, ResolutionImpact, Target; |
| 19 import '../common/tasks.dart' show CompilerTask; | 19 import '../common/tasks.dart' show CompilerTask; |
| 20 import '../compiler.dart' show Compiler; | 20 import '../compiler.dart' show Compiler; |
| 21 import '../constants/constant_system.dart'; | 21 import '../constants/constant_system.dart'; |
| 22 import '../constants/expressions.dart'; | 22 import '../constants/expressions.dart'; |
| 23 import '../constants/values.dart'; | 23 import '../constants/values.dart'; |
| 24 import '../core_types.dart' show CommonElements; | 24 import '../core_types.dart' show CommonElements, ElementEnvironment; |
| 25 import '../deferred_load.dart' show DeferredLoadTask; | 25 import '../deferred_load.dart' show DeferredLoadTask; |
| 26 import '../dump_info.dart' show DumpInfoTask; | 26 import '../dump_info.dart' show DumpInfoTask; |
| 27 import '../elements/elements.dart'; | 27 import '../elements/elements.dart'; |
| 28 import '../elements/entities.dart'; | 28 import '../elements/entities.dart'; |
| 29 import '../elements/resolution_types.dart'; | 29 import '../elements/resolution_types.dart'; |
| 30 import '../elements/types.dart'; | 30 import '../elements/types.dart'; |
| 31 import '../enqueue.dart' | 31 import '../enqueue.dart' |
| 32 show Enqueuer, EnqueueTask, ResolutionEnqueuer, TreeShakingEnqueuerStrategy; | 32 show Enqueuer, EnqueueTask, ResolutionEnqueuer, TreeShakingEnqueuerStrategy; |
| 33 import '../io/position_information.dart' show PositionSourceInformationStrategy; | 33 import '../io/position_information.dart' show PositionSourceInformationStrategy; |
| 34 import '../io/source_information.dart' show SourceInformationStrategy; | 34 import '../io/source_information.dart' show SourceInformationStrategy; |
| 35 import '../io/start_end_information.dart' | 35 import '../io/start_end_information.dart' |
| 36 show StartEndSourceInformationStrategy; | 36 show StartEndSourceInformationStrategy; |
| 37 import '../js/js.dart' as jsAst; | 37 import '../js/js.dart' as jsAst; |
| 38 import '../js/js.dart' show js; | 38 import '../js/js.dart' show js; |
| 39 import '../js/js_source_mapping.dart' show JavaScriptSourceInformationStrategy; | 39 import '../js/js_source_mapping.dart' show JavaScriptSourceInformationStrategy; |
| 40 import '../js/rewrite_async.dart'; | 40 import '../js/rewrite_async.dart'; |
| 41 import '../js_emitter/js_emitter.dart' show CodeEmitterTask; | 41 import '../js_emitter/js_emitter.dart' show CodeEmitterTask; |
| 42 import '../kernel/task.dart'; |
| 42 import '../library_loader.dart' show LibraryLoader, LoadedLibraries; | 43 import '../library_loader.dart' show LibraryLoader, LoadedLibraries; |
| 43 import '../native/native.dart' as native; | 44 import '../native/native.dart' as native; |
| 44 import '../patch_parser.dart' | 45 import '../patch_parser.dart' |
| 45 show checkNativeAnnotation, checkJsInteropAnnotation; | 46 show checkNativeAnnotation, checkJsInteropAnnotation; |
| 46 import '../ssa/ssa.dart' show SsaFunctionCompiler; | 47 import '../ssa/ssa.dart' show SsaFunctionCompiler; |
| 47 import '../tracer.dart'; | 48 import '../tracer.dart'; |
| 48 import '../tree/tree.dart'; | 49 import '../tree/tree.dart'; |
| 49 import '../types/types.dart'; | |
| 50 import '../universe/call_structure.dart' show CallStructure; | 50 import '../universe/call_structure.dart' show CallStructure; |
| 51 import '../universe/feature.dart'; | 51 import '../universe/feature.dart'; |
| 52 import '../universe/selector.dart' show Selector; | 52 import '../universe/selector.dart' show Selector; |
| 53 import '../universe/world_builder.dart'; | 53 import '../universe/world_builder.dart'; |
| 54 import '../universe/use.dart' | 54 import '../universe/use.dart' |
| 55 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; | 55 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; |
| 56 import '../universe/world_impact.dart' | 56 import '../universe/world_impact.dart' |
| 57 show | 57 show |
| 58 ImpactStrategy, | 58 ImpactStrategy, |
| 59 ImpactUseCase, | 59 ImpactUseCase, |
| 60 TransformedWorldImpact, | 60 TransformedWorldImpact, |
| 61 WorldImpact, | 61 WorldImpact, |
| 62 WorldImpactBuilder, | 62 WorldImpactBuilder, |
| 63 WorldImpactBuilderImpl, | 63 WorldImpactBuilderImpl, |
| 64 WorldImpactVisitor, | 64 WorldImpactVisitor, |
| 65 StagedWorldImpactBuilder; | 65 StagedWorldImpactBuilder; |
| 66 import '../util/util.dart'; | 66 import '../util/util.dart'; |
| 67 import '../world.dart' show ClosedWorld, ClosedWorldRefiner; | 67 import '../world.dart' show ClosedWorld, ClosedWorldRefiner; |
| 68 import 'backend_helpers.dart'; | 68 import 'backend_helpers.dart'; |
| 69 import 'backend_impact.dart'; | 69 import 'backend_impact.dart'; |
| 70 import 'backend_serialization.dart' show JavaScriptBackendSerialization; | 70 import 'backend_serialization.dart' show JavaScriptBackendSerialization; |
| 71 import 'checked_mode_helpers.dart'; | 71 import 'checked_mode_helpers.dart'; |
| 72 import 'constant_handler_javascript.dart'; | 72 import 'constant_handler_javascript.dart'; |
| 73 import 'custom_elements_analysis.dart'; | 73 import 'custom_elements_analysis.dart'; |
| 74 import 'enqueuer.dart'; | 74 import 'enqueuer.dart'; |
| 75 import 'interceptor_data.dart' show InterceptorData; |
| 75 import 'js_interop_analysis.dart' show JsInteropAnalysis; | 76 import 'js_interop_analysis.dart' show JsInteropAnalysis; |
| 76 import '../kernel/task.dart'; | |
| 77 import 'lookup_map_analysis.dart' show LookupMapAnalysis; | 77 import 'lookup_map_analysis.dart' show LookupMapAnalysis; |
| 78 import 'mirrors_analysis.dart'; | 78 import 'mirrors_analysis.dart'; |
| 79 import 'namer.dart'; | 79 import 'namer.dart'; |
| 80 import 'native_data.dart' show NativeData; | 80 import 'native_data.dart' show NativeData; |
| 81 import 'no_such_method_registry.dart'; | 81 import 'no_such_method_registry.dart'; |
| 82 import 'patch_resolver.dart'; | 82 import 'patch_resolver.dart'; |
| 83 import 'type_variable_handler.dart'; | 83 import 'type_variable_handler.dart'; |
| 84 | 84 |
| 85 part 'runtime_types.dart'; | 85 part 'runtime_types.dart'; |
| 86 | 86 |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 | 347 |
| 348 Namer _namer; | 348 Namer _namer; |
| 349 | 349 |
| 350 Namer get namer { | 350 Namer get namer { |
| 351 assert(invariant(NO_LOCATION_SPANNABLE, _namer != null, | 351 assert(invariant(NO_LOCATION_SPANNABLE, _namer != null, |
| 352 message: "Namer has not been created yet.")); | 352 message: "Namer has not been created yet.")); |
| 353 return _namer; | 353 return _namer; |
| 354 } | 354 } |
| 355 | 355 |
| 356 /** | 356 /** |
| 357 * A collection of selectors that must have a one shot interceptor | |
| 358 * generated. | |
| 359 */ | |
| 360 final Map<jsAst.Name, Selector> oneShotInterceptors; | |
| 361 | |
| 362 /** | |
| 363 * The members of instantiated interceptor classes: maps a member name to the | |
| 364 * list of members that have that name. This map is used by the codegen to | |
| 365 * know whether a send must be intercepted or not. | |
| 366 */ | |
| 367 final Map<String, Set<Element>> interceptedElements; | |
| 368 | |
| 369 /** | |
| 370 * The members of mixin classes that are mixed into an instantiated | |
| 371 * interceptor class. This is a cached subset of [interceptedElements]. | |
| 372 * | |
| 373 * Mixin methods are not specialized for the class they are mixed into. | |
| 374 * Methods mixed into intercepted classes thus always make use of the explicit | |
| 375 * receiver argument, even when mixed into non-interceptor classes. | |
| 376 * | |
| 377 * These members must be invoked with a correct explicit receiver even when | |
| 378 * the receiver is not an intercepted class. | |
| 379 */ | |
| 380 final Map<String, Set<Element>> interceptedMixinElements = | |
| 381 new Map<String, Set<Element>>(); | |
| 382 | |
| 383 /** | |
| 384 * A map of specialized versions of the [getInterceptorMethod]. | |
| 385 * Since [getInterceptorMethod] is a hot method at runtime, we're | |
| 386 * always specializing it based on the incoming type. The keys in | |
| 387 * the map are the names of these specialized versions. Note that | |
| 388 * the generic version that contains all possible type checks is | |
| 389 * also stored in this map. | |
| 390 */ | |
| 391 final Map<jsAst.Name, Set<ClassElement>> specializedGetInterceptors; | |
| 392 | |
| 393 /** | |
| 394 * Set of classes whose methods are intercepted. | |
| 395 */ | |
| 396 final Set<ClassElement> _interceptedClasses = new Set<ClassElement>(); | |
| 397 | |
| 398 /** | |
| 399 * Set of classes used as mixins on intercepted (native and primitive) | |
| 400 * classes. Methods on these classes might also be mixed in to regular Dart | |
| 401 * (unintercepted) classes. | |
| 402 */ | |
| 403 final Set<ClassElement> classesMixedIntoInterceptedClasses = | |
| 404 new Set<ClassElement>(); | |
| 405 | |
| 406 /** | |
| 407 * Set of classes whose `operator ==` methods handle `null` themselves. | 357 * Set of classes whose `operator ==` methods handle `null` themselves. |
| 408 */ | 358 */ |
| 409 final Set<ClassElement> specialOperatorEqClasses = new Set<ClassElement>(); | 359 final Set<ClassElement> specialOperatorEqClasses = new Set<ClassElement>(); |
| 410 | 360 |
| 411 /** | 361 /** |
| 412 * A set of members that are called from subclasses via `super`. | 362 * A set of members that are called from subclasses via `super`. |
| 413 */ | 363 */ |
| 414 final Set<MethodElement> aliasedSuperMembers = new Setlet<MethodElement>(); | 364 final Set<MethodElement> aliasedSuperMembers = new Setlet<MethodElement>(); |
| 415 | 365 |
| 416 List<CompilerTask> get tasks { | 366 List<CompilerTask> get tasks { |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 /// Interface for serialization of backend specific data. | 500 /// Interface for serialization of backend specific data. |
| 551 JavaScriptBackendSerialization serialization; | 501 JavaScriptBackendSerialization serialization; |
| 552 | 502 |
| 553 StagedWorldImpactBuilder constantImpactsForResolution = | 503 StagedWorldImpactBuilder constantImpactsForResolution = |
| 554 new StagedWorldImpactBuilder(); | 504 new StagedWorldImpactBuilder(); |
| 555 | 505 |
| 556 StagedWorldImpactBuilder constantImpactsForCodegen = | 506 StagedWorldImpactBuilder constantImpactsForCodegen = |
| 557 new StagedWorldImpactBuilder(); | 507 new StagedWorldImpactBuilder(); |
| 558 | 508 |
| 559 final NativeData nativeData = new NativeData(); | 509 final NativeData nativeData = new NativeData(); |
| 510 InterceptorData _interceptorData; |
| 560 | 511 |
| 561 BackendHelpers helpers; | 512 BackendHelpers helpers; |
| 562 final BackendImpacts impacts; | 513 final BackendImpacts impacts; |
| 563 | 514 |
| 564 /// Common classes used by the backend. | 515 /// Common classes used by the backend. |
| 565 BackendClasses backendClasses; | 516 BackendClasses backendClasses; |
| 566 | 517 |
| 567 /// Backend access to the front-end. | 518 /// Backend access to the front-end. |
| 568 final JSFrontendAccess frontend; | 519 final JSFrontendAccess frontend; |
| 569 | 520 |
| 570 Tracer tracer; | 521 Tracer tracer; |
| 571 | 522 |
| 572 JavaScriptBackend(Compiler compiler, | 523 JavaScriptBackend(Compiler compiler, |
| 573 {bool generateSourceMap: true, | 524 {bool generateSourceMap: true, |
| 574 bool useStartupEmitter: false, | 525 bool useStartupEmitter: false, |
| 575 bool useNewSourceInfo: false, | 526 bool useNewSourceInfo: false, |
| 576 bool useKernel: false}) | 527 bool useKernel: false}) |
| 577 : oneShotInterceptors = new Map<jsAst.Name, Selector>(), | 528 : rti = new _RuntimeTypes(compiler), |
| 578 interceptedElements = new Map<String, Set<Element>>(), | |
| 579 rti = new _RuntimeTypes(compiler), | |
| 580 rtiEncoder = new _RuntimeTypesEncoder(compiler), | 529 rtiEncoder = new _RuntimeTypesEncoder(compiler), |
| 581 specializedGetInterceptors = new Map<jsAst.Name, Set<ClassElement>>(), | |
| 582 annotations = new Annotations(compiler), | 530 annotations = new Annotations(compiler), |
| 583 this.sourceInformationStrategy = generateSourceMap | 531 this.sourceInformationStrategy = generateSourceMap |
| 584 ? (useNewSourceInfo | 532 ? (useNewSourceInfo |
| 585 ? new PositionSourceInformationStrategy() | 533 ? new PositionSourceInformationStrategy() |
| 586 : const StartEndSourceInformationStrategy()) | 534 : const StartEndSourceInformationStrategy()) |
| 587 : const JavaScriptSourceInformationStrategy(), | 535 : const JavaScriptSourceInformationStrategy(), |
| 588 impacts = new BackendImpacts(compiler), | 536 impacts = new BackendImpacts(compiler), |
| 589 frontend = new JSFrontendAccess(compiler), | 537 frontend = new JSFrontendAccess(compiler), |
| 590 this.compiler = compiler { | 538 this.compiler = compiler { |
| 591 helpers = | 539 helpers = |
| 592 new BackendHelpers(compiler.elementEnvironment, this, commonElements); | 540 new BackendHelpers(compiler.elementEnvironment, this, commonElements); |
| 593 emitter = | 541 emitter = |
| 594 new CodeEmitterTask(compiler, generateSourceMap, useStartupEmitter); | 542 new CodeEmitterTask(compiler, generateSourceMap, useStartupEmitter); |
| 595 typeVariableHandler = new TypeVariableHandler(compiler); | 543 typeVariableHandler = new TypeVariableHandler(compiler); |
| 596 customElementsAnalysis = new CustomElementsAnalysis(this); | 544 customElementsAnalysis = new CustomElementsAnalysis(this); |
| 597 lookupMapAnalysis = new LookupMapAnalysis(this, reporter); | 545 lookupMapAnalysis = new LookupMapAnalysis(this, reporter); |
| 598 jsInteropAnalysis = new JsInteropAnalysis(this); | 546 jsInteropAnalysis = new JsInteropAnalysis(this); |
| 599 mirrorsAnalysis = new MirrorsAnalysis(this, compiler.resolution); | 547 mirrorsAnalysis = new MirrorsAnalysis(this, compiler.resolution); |
| 600 | 548 |
| 601 noSuchMethodRegistry = new NoSuchMethodRegistry(this); | 549 noSuchMethodRegistry = new NoSuchMethodRegistry(this); |
| 602 kernelTask = new KernelTask(compiler); | 550 kernelTask = new KernelTask(compiler); |
| 603 constantCompilerTask = new JavaScriptConstantTask(compiler); | 551 constantCompilerTask = new JavaScriptConstantTask(compiler); |
| 604 impactTransformer = new JavaScriptImpactTransformer(this); | 552 impactTransformer = new JavaScriptImpactTransformer(this); |
| 605 patchResolverTask = new PatchResolverTask(compiler); | 553 patchResolverTask = new PatchResolverTask(compiler); |
| 606 functionCompiler = | 554 functionCompiler = |
| 607 new SsaFunctionCompiler(this, sourceInformationStrategy, useKernel); | 555 new SsaFunctionCompiler(this, sourceInformationStrategy, useKernel); |
| 608 serialization = new JavaScriptBackendSerialization(this); | 556 serialization = new JavaScriptBackendSerialization(this); |
| 609 backendClasses = new JavaScriptBackendClasses(helpers); | 557 _interceptorData = new InterceptorData(nativeData, helpers, commonElements); |
| 558 backendClasses = new JavaScriptBackendClasses( |
| 559 compiler.elementEnvironment, helpers, nativeData, _interceptorData); |
| 610 } | 560 } |
| 611 | 561 |
| 612 /// The [ConstantSystem] used to interpret compile-time constants for this | 562 /// The [ConstantSystem] used to interpret compile-time constants for this |
| 613 /// backend. | 563 /// backend. |
| 614 ConstantSystem get constantSystem => constants.constantSystem; | 564 ConstantSystem get constantSystem => constants.constantSystem; |
| 615 | 565 |
| 616 DiagnosticReporter get reporter => compiler.reporter; | 566 DiagnosticReporter get reporter => compiler.reporter; |
| 617 | 567 |
| 618 CommonElements get commonElements => compiler.commonElements; | 568 CommonElements get commonElements => compiler.commonElements; |
| 619 | 569 |
| 620 Resolution get resolution => compiler.resolution; | 570 Resolution get resolution => compiler.resolution; |
| 621 | 571 |
| 572 InterceptorData get interceptorData => _interceptorData; |
| 573 |
| 622 /// Returns constant environment for the JavaScript interpretation of the | 574 /// Returns constant environment for the JavaScript interpretation of the |
| 623 /// constants. | 575 /// constants. |
| 624 JavaScriptConstantCompiler get constants { | 576 JavaScriptConstantCompiler get constants { |
| 625 return constantCompilerTask.jsConstantCompiler; | 577 return constantCompilerTask.jsConstantCompiler; |
| 626 } | 578 } |
| 627 | 579 |
| 628 @override | 580 @override |
| 629 bool isDefaultNoSuchMethod(MethodElement element) { | 581 bool isDefaultNoSuchMethod(MethodElement element) { |
| 630 return noSuchMethodRegistry.isDefaultNoSuchMethodImplementation(element); | 582 return noSuchMethodRegistry.isDefaultNoSuchMethodImplementation(element); |
| 631 } | 583 } |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 } | 699 } |
| 748 | 700 |
| 749 /// Returns true if global optimizations such as type inferencing | 701 /// Returns true if global optimizations such as type inferencing |
| 750 /// can apply to this element. One category of elements that do not | 702 /// can apply to this element. One category of elements that do not |
| 751 /// apply is runtime helpers that the backend calls, but the | 703 /// apply is runtime helpers that the backend calls, but the |
| 752 /// optimizations don't see those calls. | 704 /// optimizations don't see those calls. |
| 753 bool canBeUsedForGlobalOptimizations(Element element) { | 705 bool canBeUsedForGlobalOptimizations(Element element) { |
| 754 return !usedByBackend(element) && !invokedReflectively(element); | 706 return !usedByBackend(element) && !invokedReflectively(element); |
| 755 } | 707 } |
| 756 | 708 |
| 757 bool isInterceptorClass(ClassElement element) { | |
| 758 if (element == null) return false; | |
| 759 if (isNativeOrExtendsNative(element)) return true; | |
| 760 if (interceptedClasses.contains(element)) return true; | |
| 761 if (classesMixedIntoInterceptedClasses.contains(element)) return true; | |
| 762 return false; | |
| 763 } | |
| 764 | |
| 765 jsAst.Name registerOneShotInterceptor(Selector selector) { | |
| 766 Set<ClassElement> classes = getInterceptedClassesOn(selector.name); | |
| 767 jsAst.Name name = namer.nameForGetOneShotInterceptor(selector, classes); | |
| 768 if (!oneShotInterceptors.containsKey(name)) { | |
| 769 registerSpecializedGetInterceptor(classes); | |
| 770 oneShotInterceptors[name] = selector; | |
| 771 } | |
| 772 return name; | |
| 773 } | |
| 774 | |
| 775 /** | 709 /** |
| 776 * Record that [method] is called from a subclass via `super`. | 710 * Record that [method] is called from a subclass via `super`. |
| 777 */ | 711 */ |
| 778 bool maybeRegisterAliasedSuperMember( | 712 bool maybeRegisterAliasedSuperMember( |
| 779 MemberElement member, Selector selector) { | 713 MemberElement member, Selector selector) { |
| 780 if (!canUseAliasedSuperMember(member, selector)) { | 714 if (!canUseAliasedSuperMember(member, selector)) { |
| 781 // Invoking a super getter isn't supported, this would require changes to | 715 // Invoking a super getter isn't supported, this would require changes to |
| 782 // compact field descriptors in the emitter. | 716 // compact field descriptors in the emitter. |
| 783 return false; | 717 return false; |
| 784 } | 718 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 857 // TODO(sra): Process fields for storing separately. | 791 // TODO(sra): Process fields for storing separately. |
| 858 // We have to handle both loading and storing to the field because we | 792 // We have to handle both loading and storing to the field because we |
| 859 // only get one look at each member and there might be a load or store | 793 // only get one look at each member and there might be a load or store |
| 860 // we have not seen yet. | 794 // we have not seen yet. |
| 861 registry.registerNativeData(fieldLoadBehavior); | 795 registry.registerNativeData(fieldLoadBehavior); |
| 862 registry.registerNativeData(fieldStoreBehavior); | 796 registry.registerNativeData(fieldStoreBehavior); |
| 863 } | 797 } |
| 864 } | 798 } |
| 865 } | 799 } |
| 866 | 800 |
| 867 bool isNativeOrExtendsNative(ClassElement element) { | |
| 868 if (element == null) return false; | |
| 869 if (isNative(element) || isJsInterop(element)) { | |
| 870 return true; | |
| 871 } | |
| 872 assert(element.isResolved); | |
| 873 return isNativeOrExtendsNative(element.superclass); | |
| 874 } | |
| 875 | |
| 876 bool isInterceptedMethod(MemberElement element) { | |
| 877 if (!element.isInstanceMember) return false; | |
| 878 if (element.isGenerativeConstructorBody) { | |
| 879 return isNativeOrExtendsNative(element.enclosingClass); | |
| 880 } | |
| 881 return interceptedElements[element.name] != null; | |
| 882 } | |
| 883 | |
| 884 bool fieldHasInterceptedGetter(Element element) { | |
| 885 assert(element.isField); | |
| 886 return interceptedElements[element.name] != null; | |
| 887 } | |
| 888 | |
| 889 bool fieldHasInterceptedSetter(Element element) { | |
| 890 assert(element.isField); | |
| 891 return interceptedElements[element.name] != null; | |
| 892 } | |
| 893 | |
| 894 bool isInterceptedName(String name) { | |
| 895 return interceptedElements[name] != null; | |
| 896 } | |
| 897 | |
| 898 bool isInterceptedSelector(Selector selector) { | |
| 899 return interceptedElements[selector.name] != null; | |
| 900 } | |
| 901 | |
| 902 /** | |
| 903 * Returns `true` iff [selector] matches an element defined in a class mixed | |
| 904 * into an intercepted class. These selectors are not eligible for the 'dummy | |
| 905 * explicit receiver' optimization. | |
| 906 */ | |
| 907 bool isInterceptedMixinSelector(Selector selector, TypeMask mask) { | |
| 908 Set<Element> elements = | |
| 909 interceptedMixinElements.putIfAbsent(selector.name, () { | |
| 910 Set<Element> elements = interceptedElements[selector.name]; | |
| 911 if (elements == null) return null; | |
| 912 return elements | |
| 913 .where((element) => classesMixedIntoInterceptedClasses | |
| 914 .contains(element.enclosingClass)) | |
| 915 .toSet(); | |
| 916 }); | |
| 917 | |
| 918 if (elements == null) return false; | |
| 919 if (elements.isEmpty) return false; | |
| 920 return elements.any((element) { | |
| 921 return selector.applies(element) && | |
| 922 (mask == null || | |
| 923 mask.canHit(element as MemberElement, selector, _closedWorld)); | |
| 924 }); | |
| 925 } | |
| 926 | |
| 927 /// True if the given class is an internal class used for type inference | |
| 928 /// and never exists at runtime. | |
| 929 bool isCompileTimeOnlyClass(ClassElement class_) { | |
| 930 return class_ == helpers.jsPositiveIntClass || | |
| 931 class_ == helpers.jsUInt32Class || | |
| 932 class_ == helpers.jsUInt31Class || | |
| 933 class_ == helpers.jsFixedArrayClass || | |
| 934 class_ == helpers.jsUnmodifiableArrayClass || | |
| 935 class_ == helpers.jsMutableArrayClass || | |
| 936 class_ == helpers.jsExtendableArrayClass; | |
| 937 } | |
| 938 | |
| 939 /// Maps compile-time classes to their runtime class. The runtime class is | 801 /// Maps compile-time classes to their runtime class. The runtime class is |
| 940 /// always a superclass or the class itself. | 802 /// always a superclass or the class itself. |
| 941 ClassElement getRuntimeClass(ClassElement class_) { | 803 ClassElement getRuntimeClass(ClassElement class_) { |
| 942 if (class_.isSubclassOf(helpers.jsIntClass)) return helpers.jsIntClass; | 804 if (class_.isSubclassOf(helpers.jsIntClass)) return helpers.jsIntClass; |
| 943 if (class_.isSubclassOf(helpers.jsArrayClass)) return helpers.jsArrayClass; | 805 if (class_.isSubclassOf(helpers.jsArrayClass)) return helpers.jsArrayClass; |
| 944 return class_; | 806 return class_; |
| 945 } | 807 } |
| 946 | 808 |
| 947 final Map<String, Set<ClassElement>> interceptedClassesCache = | |
| 948 new Map<String, Set<ClassElement>>(); | |
| 949 final Set<ClassElement> _noClasses = new Set<ClassElement>(); | |
| 950 | |
| 951 /// Returns a set of interceptor classes that contain a member named [name] | |
| 952 /// | |
| 953 /// Returns an empty set if there is no class. Do not modify the returned set. | |
| 954 Set<ClassElement> getInterceptedClassesOn(String name) { | |
| 955 Set<Element> intercepted = interceptedElements[name]; | |
| 956 if (intercepted == null) return _noClasses; | |
| 957 return interceptedClassesCache.putIfAbsent(name, () { | |
| 958 // Populate the cache by running through all the elements and | |
| 959 // determine if the given selector applies to them. | |
| 960 Set<ClassElement> result = new Set<ClassElement>(); | |
| 961 for (Element element in intercepted) { | |
| 962 ClassElement classElement = element.enclosingClass; | |
| 963 if (isCompileTimeOnlyClass(classElement)) continue; | |
| 964 if (isNativeOrExtendsNative(classElement) || | |
| 965 interceptedClasses.contains(classElement)) { | |
| 966 result.add(classElement); | |
| 967 } | |
| 968 if (classesMixedIntoInterceptedClasses.contains(classElement)) { | |
| 969 Set<ClassElement> nativeSubclasses = | |
| 970 nativeSubclassesOfMixin(classElement); | |
| 971 if (nativeSubclasses != null) result.addAll(nativeSubclasses); | |
| 972 } | |
| 973 } | |
| 974 return result; | |
| 975 }); | |
| 976 } | |
| 977 | |
| 978 Set<ClassElement> nativeSubclassesOfMixin(ClassElement mixin) { | |
| 979 Iterable<MixinApplicationElement> uses = _closedWorld.mixinUsesOf(mixin); | |
| 980 Set<ClassElement> result = null; | |
| 981 for (MixinApplicationElement use in uses) { | |
| 982 _closedWorld.forEachStrictSubclassOf(use, (ClassElement subclass) { | |
| 983 if (isNativeOrExtendsNative(subclass)) { | |
| 984 if (result == null) result = new Set<ClassElement>(); | |
| 985 result.add(subclass); | |
| 986 } | |
| 987 }); | |
| 988 } | |
| 989 return result; | |
| 990 } | |
| 991 | |
| 992 bool operatorEqHandlesNullArgument(FunctionElement operatorEqfunction) { | 809 bool operatorEqHandlesNullArgument(FunctionElement operatorEqfunction) { |
| 993 return specialOperatorEqClasses.contains(operatorEqfunction.enclosingClass); | 810 return specialOperatorEqClasses.contains(operatorEqfunction.enclosingClass); |
| 994 } | 811 } |
| 995 | 812 |
| 996 void validateInterceptorImplementsAllObjectMethods( | 813 void validateInterceptorImplementsAllObjectMethods( |
| 997 ClassElement interceptorClass) { | 814 ClassElement interceptorClass) { |
| 998 if (interceptorClass == null) return; | 815 if (interceptorClass == null) return; |
| 999 interceptorClass.ensureResolved(resolution); | 816 interceptorClass.ensureResolved(resolution); |
| 1000 ClassElement objectClass = commonElements.objectClass; | 817 ClassElement objectClass = commonElements.objectClass; |
| 1001 objectClass.forEachMember((_, Element member) { | 818 objectClass.forEachMember((_, Element member) { |
| 1002 if (member.isGenerativeConstructor) return; | 819 if (member.isGenerativeConstructor) return; |
| 1003 Element interceptorMember = interceptorClass.lookupMember(member.name); | 820 Element interceptorMember = interceptorClass.lookupMember(member.name); |
| 1004 // Interceptors must override all Object methods due to calling convention | 821 // Interceptors must override all Object methods due to calling convention |
| 1005 // differences. | 822 // differences. |
| 1006 assert(invariant(interceptorMember, | 823 assert(invariant(interceptorMember, |
| 1007 interceptorMember.enclosingClass == interceptorClass, | 824 interceptorMember.enclosingClass == interceptorClass, |
| 1008 message: | 825 message: |
| 1009 "Member ${member.name} not overridden in ${interceptorClass}. " | 826 "Member ${member.name} not overridden in ${interceptorClass}. " |
| 1010 "Found $interceptorMember from " | 827 "Found $interceptorMember from " |
| 1011 "${interceptorMember.enclosingClass}.")); | 828 "${interceptorMember.enclosingClass}.")); |
| 1012 }); | 829 }); |
| 1013 } | 830 } |
| 1014 | 831 |
| 1015 void addInterceptorsForNativeClassMembers(ClassElement cls, | 832 void addInterceptorsForNativeClassMembers(ClassElement cls, |
| 1016 {bool forResolution}) { | 833 {bool forResolution}) { |
| 1017 if (forResolution) { | 834 if (forResolution) { |
| 1018 cls.ensureResolved(resolution); | 835 cls.ensureResolved(resolution); |
| 1019 cls.forEachMember((ClassElement classElement, Element member) { | 836 interceptorData.addInterceptorsForNativeClassMembers(cls); |
| 1020 if (member.name == Identifiers.call) { | |
| 1021 return; | |
| 1022 } | |
| 1023 if (member.isSynthesized) return; | |
| 1024 // All methods on [Object] are shadowed by [Interceptor]. | |
| 1025 if (classElement == commonElements.objectClass) return; | |
| 1026 Set<Element> set = interceptedElements.putIfAbsent( | |
| 1027 member.name, () => new Set<Element>()); | |
| 1028 set.add(member); | |
| 1029 }, includeSuperAndInjectedMembers: true); | |
| 1030 | |
| 1031 // Walk superclass chain to find mixins. | |
| 1032 for (; cls != null; cls = cls.superclass) { | |
| 1033 if (cls.isMixinApplication) { | |
| 1034 MixinApplicationElement mixinApplication = cls; | |
| 1035 classesMixedIntoInterceptedClasses.add(mixinApplication.mixin); | |
| 1036 } | |
| 1037 } | |
| 1038 } | 837 } |
| 1039 } | 838 } |
| 1040 | 839 |
| 1041 void addInterceptors(ClassElement cls, WorldImpactBuilder impactBuilder, | 840 void addInterceptors(ClassElement cls, WorldImpactBuilder impactBuilder, |
| 1042 {bool forResolution}) { | 841 {bool forResolution}) { |
| 1043 if (forResolution) { | 842 if (forResolution) { |
| 1044 if (_interceptedClasses.add(cls)) { | 843 cls.ensureResolved(resolution); |
| 1045 cls.ensureResolved(resolution); | 844 interceptorData.addInterceptors(cls); |
| 1046 cls.forEachMember((ClassElement classElement, Element member) { | |
| 1047 // All methods on [Object] are shadowed by [Interceptor]. | |
| 1048 if (classElement == commonElements.objectClass) return; | |
| 1049 Set<Element> set = interceptedElements.putIfAbsent( | |
| 1050 member.name, () => new Set<Element>()); | |
| 1051 set.add(member); | |
| 1052 }, includeSuperAndInjectedMembers: true); | |
| 1053 } | |
| 1054 _interceptedClasses.add(helpers.jsInterceptorClass); | |
| 1055 } | 845 } |
| 1056 impactTransformer.registerBackendInstantiation(impactBuilder, cls); | 846 impactTransformer.registerBackendInstantiation(impactBuilder, cls); |
| 1057 } | 847 } |
| 1058 | 848 |
| 1059 Set<ClassElement> get interceptedClasses { | |
| 1060 assert(compiler.enqueuer.resolution.queueIsClosed); | |
| 1061 return _interceptedClasses; | |
| 1062 } | |
| 1063 | |
| 1064 void registerSpecializedGetInterceptor(Set<ClassElement> classes) { | |
| 1065 jsAst.Name name = namer.nameForGetInterceptor(classes); | |
| 1066 if (classes.contains(helpers.jsInterceptorClass)) { | |
| 1067 // We can't use a specialized [getInterceptorMethod], so we make | |
| 1068 // sure we emit the one with all checks. | |
| 1069 specializedGetInterceptors[name] = interceptedClasses; | |
| 1070 } else { | |
| 1071 specializedGetInterceptors[name] = classes; | |
| 1072 } | |
| 1073 } | |
| 1074 | |
| 1075 /// Called during codegen when [constant] has been used. | 849 /// Called during codegen when [constant] has been used. |
| 1076 void computeImpactForCompileTimeConstant(ConstantValue constant, | 850 void computeImpactForCompileTimeConstant(ConstantValue constant, |
| 1077 WorldImpactBuilder impactBuilder, bool isForResolution) { | 851 WorldImpactBuilder impactBuilder, bool isForResolution) { |
| 1078 computeImpactForCompileTimeConstantInternal( | 852 computeImpactForCompileTimeConstantInternal( |
| 1079 constant, impactBuilder, isForResolution); | 853 constant, impactBuilder, isForResolution); |
| 1080 | 854 |
| 1081 if (!isForResolution && lookupMapAnalysis.isLookupMap(constant)) { | 855 if (!isForResolution && lookupMapAnalysis.isLookupMap(constant)) { |
| 1082 // Note: internally, this registration will temporarily remove the | 856 // Note: internally, this registration will temporarily remove the |
| 1083 // constant dependencies and add them later on-demand. | 857 // constant dependencies and add them later on-demand. |
| 1084 lookupMapAnalysis.registerLookupMapReference(constant); | 858 lookupMapAnalysis.registerLookupMapReference(constant); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1182 impactBuilder, impacts.functionClass); | 956 impactBuilder, impacts.functionClass); |
| 1183 } else if (cls == commonElements.mapClass) { | 957 } else if (cls == commonElements.mapClass) { |
| 1184 impactTransformer.registerBackendImpact( | 958 impactTransformer.registerBackendImpact( |
| 1185 impactBuilder, impacts.mapClass); | 959 impactBuilder, impacts.mapClass); |
| 1186 // For map literals, the dependency between the implementation class | 960 // For map literals, the dependency between the implementation class |
| 1187 // and [Map] is not visible, so we have to add it manually. | 961 // and [Map] is not visible, so we have to add it manually. |
| 1188 rti.registerRtiDependency(helpers.mapLiteralClass, cls); | 962 rti.registerRtiDependency(helpers.mapLiteralClass, cls); |
| 1189 } else if (cls == helpers.boundClosureClass) { | 963 } else if (cls == helpers.boundClosureClass) { |
| 1190 impactTransformer.registerBackendImpact( | 964 impactTransformer.registerBackendImpact( |
| 1191 impactBuilder, impacts.boundClosureClass); | 965 impactBuilder, impacts.boundClosureClass); |
| 1192 } else if (isNativeOrExtendsNative(cls)) { | 966 } else if (nativeData.isNativeOrExtendsNative(cls)) { |
| 1193 impactTransformer.registerBackendImpact( | 967 impactTransformer.registerBackendImpact( |
| 1194 impactBuilder, impacts.nativeOrExtendsClass); | 968 impactBuilder, impacts.nativeOrExtendsClass); |
| 1195 } else if (cls == helpers.mapLiteralClass) { | 969 } else if (cls == helpers.mapLiteralClass) { |
| 1196 impactTransformer.registerBackendImpact( | 970 impactTransformer.registerBackendImpact( |
| 1197 impactBuilder, impacts.mapLiteralClass); | 971 impactBuilder, impacts.mapLiteralClass); |
| 1198 } | 972 } |
| 1199 } | 973 } |
| 1200 if (cls == helpers.closureClass) { | 974 if (cls == helpers.closureClass) { |
| 1201 impactTransformer.registerBackendImpact( | 975 impactTransformer.registerBackendImpact( |
| 1202 impactBuilder, impacts.closureClass); | 976 impactBuilder, impacts.closureClass); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1264 forResolution: forResolution); | 1038 forResolution: forResolution); |
| 1265 } else if (cls == helpers.jsPlainJavaScriptObjectClass) { | 1039 } else if (cls == helpers.jsPlainJavaScriptObjectClass) { |
| 1266 addInterceptors(helpers.jsPlainJavaScriptObjectClass, impactBuilder, | 1040 addInterceptors(helpers.jsPlainJavaScriptObjectClass, impactBuilder, |
| 1267 forResolution: forResolution); | 1041 forResolution: forResolution); |
| 1268 } else if (cls == helpers.jsUnknownJavaScriptObjectClass) { | 1042 } else if (cls == helpers.jsUnknownJavaScriptObjectClass) { |
| 1269 addInterceptors(helpers.jsUnknownJavaScriptObjectClass, impactBuilder, | 1043 addInterceptors(helpers.jsUnknownJavaScriptObjectClass, impactBuilder, |
| 1270 forResolution: forResolution); | 1044 forResolution: forResolution); |
| 1271 } else if (cls == helpers.jsJavaScriptFunctionClass) { | 1045 } else if (cls == helpers.jsJavaScriptFunctionClass) { |
| 1272 addInterceptors(helpers.jsJavaScriptFunctionClass, impactBuilder, | 1046 addInterceptors(helpers.jsJavaScriptFunctionClass, impactBuilder, |
| 1273 forResolution: forResolution); | 1047 forResolution: forResolution); |
| 1274 } else if (isNativeOrExtendsNative(cls)) { | 1048 } else if (nativeData.isNativeOrExtendsNative(cls)) { |
| 1275 addInterceptorsForNativeClassMembers(cls, forResolution: forResolution); | 1049 addInterceptorsForNativeClassMembers(cls, forResolution: forResolution); |
| 1276 } else if (cls == helpers.jsIndexingBehaviorInterface) { | 1050 } else if (cls == helpers.jsIndexingBehaviorInterface) { |
| 1277 impactTransformer.registerBackendImpact( | 1051 impactTransformer.registerBackendImpact( |
| 1278 impactBuilder, impacts.jsIndexingBehavior); | 1052 impactBuilder, impacts.jsIndexingBehavior); |
| 1279 } | 1053 } |
| 1280 | 1054 |
| 1281 customElementsAnalysis.registerInstantiatedClass(cls, | 1055 customElementsAnalysis.registerInstantiatedClass(cls, |
| 1282 forResolution: forResolution); | 1056 forResolution: forResolution); |
| 1283 if (!forResolution) { | 1057 if (!forResolution) { |
| 1284 lookupMapAnalysis.registerInstantiatedClass(cls); | 1058 lookupMapAnalysis.registerInstantiatedClass(cls); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1319 | 1093 |
| 1320 void onResolutionComplete( | 1094 void onResolutionComplete( |
| 1321 ClosedWorld closedWorld, ClosedWorldRefiner closedWorldRefiner) { | 1095 ClosedWorld closedWorld, ClosedWorldRefiner closedWorldRefiner) { |
| 1322 for (Entity entity in compiler.enqueuer.resolution.processedEntities) { | 1096 for (Entity entity in compiler.enqueuer.resolution.processedEntities) { |
| 1323 processAnnotations(entity, closedWorldRefiner); | 1097 processAnnotations(entity, closedWorldRefiner); |
| 1324 } | 1098 } |
| 1325 computeMembersNeededForReflection(closedWorld); | 1099 computeMembersNeededForReflection(closedWorld); |
| 1326 rti.computeClassesNeedingRti( | 1100 rti.computeClassesNeedingRti( |
| 1327 compiler.enqueuer.resolution.worldBuilder, closedWorld); | 1101 compiler.enqueuer.resolution.worldBuilder, closedWorld); |
| 1328 _registeredMetadata.clear(); | 1102 _registeredMetadata.clear(); |
| 1103 interceptorData.onResolutionComplete(closedWorld); |
| 1329 } | 1104 } |
| 1330 | 1105 |
| 1331 void onTypeInferenceComplete() { | 1106 void onTypeInferenceComplete() { |
| 1332 noSuchMethodRegistry.onTypeInferenceComplete(); | 1107 noSuchMethodRegistry.onTypeInferenceComplete(); |
| 1333 } | 1108 } |
| 1334 | 1109 |
| 1335 /// Called to register that an instantiated generic class has a call method. | 1110 /// Called to register that an instantiated generic class has a call method. |
| 1336 /// Any backend specific [WorldImpact] of this is returned. | 1111 /// Any backend specific [WorldImpact] of this is returned. |
| 1337 /// | 1112 /// |
| 1338 /// Note: The [callMethod] is registered even thought it doesn't reference | 1113 /// Note: The [callMethod] is registered even thought it doesn't reference |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1795 element == helpers.jsFixedArrayClass || | 1570 element == helpers.jsFixedArrayClass || |
| 1796 element == helpers.jsUnmodifiableArrayClass; | 1571 element == helpers.jsUnmodifiableArrayClass; |
| 1797 } | 1572 } |
| 1798 | 1573 |
| 1799 bool mayGenerateInstanceofCheck(ResolutionDartType type) { | 1574 bool mayGenerateInstanceofCheck(ResolutionDartType type) { |
| 1800 // We can use an instanceof check for raw types that have no subclass that | 1575 // We can use an instanceof check for raw types that have no subclass that |
| 1801 // is mixed-in or in an implements clause. | 1576 // is mixed-in or in an implements clause. |
| 1802 | 1577 |
| 1803 if (!type.isRaw) return false; | 1578 if (!type.isRaw) return false; |
| 1804 ClassElement classElement = type.element; | 1579 ClassElement classElement = type.element; |
| 1805 if (isInterceptorClass(classElement)) return false; | 1580 if (interceptorData.isInterceptorClass(classElement)) return false; |
| 1806 return _closedWorld.hasOnlySubclasses(classElement); | 1581 return _closedWorld.hasOnlySubclasses(classElement); |
| 1807 } | 1582 } |
| 1808 | 1583 |
| 1809 /// Called to register that [element] is statically known to be used. Any | 1584 /// Called to register that [element] is statically known to be used. Any |
| 1810 /// backend specific [WorldImpact] of this is returned. | 1585 /// backend specific [WorldImpact] of this is returned. |
| 1811 WorldImpact registerUsedElement(MemberElement element, {bool forResolution}) { | 1586 WorldImpact registerUsedElement(MemberElement element, {bool forResolution}) { |
| 1812 WorldImpactBuilderImpl worldImpact = new WorldImpactBuilderImpl(); | 1587 WorldImpactBuilderImpl worldImpact = new WorldImpactBuilderImpl(); |
| 1813 if (element == helpers.disableTreeShakingMarker) { | 1588 if (element == helpers.disableTreeShakingMarker) { |
| 1814 isTreeShakingDisabled = true; | 1589 isTreeShakingDisabled = true; |
| 1815 } else if (element == helpers.preserveNamesMarker) { | 1590 } else if (element == helpers.preserveNamesMarker) { |
| (...skipping 1429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3245 break; | 3020 break; |
| 3246 default: | 3021 default: |
| 3247 } | 3022 } |
| 3248 } | 3023 } |
| 3249 | 3024 |
| 3250 for (String name in impact.constSymbols) { | 3025 for (String name in impact.constSymbols) { |
| 3251 backend.registerConstSymbol(name); | 3026 backend.registerConstSymbol(name); |
| 3252 } | 3027 } |
| 3253 | 3028 |
| 3254 for (Set<ClassElement> classes in impact.specializedGetInterceptors) { | 3029 for (Set<ClassElement> classes in impact.specializedGetInterceptors) { |
| 3255 backend.registerSpecializedGetInterceptor(classes); | 3030 backend.interceptorData |
| 3031 .registerSpecializedGetInterceptor(classes, backend.namer); |
| 3256 } | 3032 } |
| 3257 | 3033 |
| 3258 if (impact.usesInterceptor) { | 3034 if (impact.usesInterceptor) { |
| 3259 if (backend.codegenEnqueuer.nativeEnqueuer.hasInstantiatedNativeClasses) { | 3035 if (backend.codegenEnqueuer.nativeEnqueuer.hasInstantiatedNativeClasses) { |
| 3260 registerBackendImpact(transformed, impacts.interceptorUse); | 3036 registerBackendImpact(transformed, impacts.interceptorUse); |
| 3261 } | 3037 } |
| 3262 } | 3038 } |
| 3263 | 3039 |
| 3264 for (ClassElement element in impact.typeConstants) { | 3040 for (ClassElement element in impact.typeConstants) { |
| 3265 backend.customElementsAnalysis.registerTypeConstant(element); | 3041 backend.customElementsAnalysis.registerTypeConstant(element); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3335 void onImpactUsed(ImpactUseCase impactUse) { | 3111 void onImpactUsed(ImpactUseCase impactUse) { |
| 3336 if (impactUse == DeferredLoadTask.IMPACT_USE && !supportSerialization) { | 3112 if (impactUse == DeferredLoadTask.IMPACT_USE && !supportSerialization) { |
| 3337 // TODO(johnniwinther): Allow emptying when serialization has been | 3113 // TODO(johnniwinther): Allow emptying when serialization has been |
| 3338 // performed. | 3114 // performed. |
| 3339 resolution.emptyCache(); | 3115 resolution.emptyCache(); |
| 3340 } | 3116 } |
| 3341 } | 3117 } |
| 3342 } | 3118 } |
| 3343 | 3119 |
| 3344 class JavaScriptBackendClasses implements BackendClasses { | 3120 class JavaScriptBackendClasses implements BackendClasses { |
| 3121 final ElementEnvironment _env; |
| 3345 final BackendHelpers helpers; | 3122 final BackendHelpers helpers; |
| 3123 final NativeData _nativeData; |
| 3124 final InterceptorData _interceptorData; |
| 3346 | 3125 |
| 3347 JavaScriptBackendClasses(this.helpers); | 3126 JavaScriptBackendClasses( |
| 3127 this._env, this.helpers, this._nativeData, this._interceptorData); |
| 3348 | 3128 |
| 3349 ClassElement get intClass => helpers.jsIntClass; | 3129 ClassElement get intClass => helpers.jsIntClass; |
| 3350 ClassElement get uint32Class => helpers.jsUInt32Class; | 3130 ClassElement get uint32Class => helpers.jsUInt32Class; |
| 3351 ClassElement get uint31Class => helpers.jsUInt31Class; | 3131 ClassElement get uint31Class => helpers.jsUInt31Class; |
| 3352 ClassElement get positiveIntClass => helpers.jsPositiveIntClass; | 3132 ClassElement get positiveIntClass => helpers.jsPositiveIntClass; |
| 3353 ClassElement get doubleClass => helpers.jsDoubleClass; | 3133 ClassElement get doubleClass => helpers.jsDoubleClass; |
| 3354 ClassElement get numClass => helpers.jsNumberClass; | 3134 ClassElement get numClass => helpers.jsNumberClass; |
| 3355 ClassElement get stringClass => helpers.jsStringClass; | 3135 ClassElement get stringClass => helpers.jsStringClass; |
| 3356 ClassElement get listClass => helpers.jsArrayClass; | 3136 ClassElement get listClass => helpers.jsArrayClass; |
| 3357 ClassElement get mutableListClass => helpers.jsMutableArrayClass; | 3137 ClassElement get mutableListClass => helpers.jsMutableArrayClass; |
| 3358 ClassElement get constListClass => helpers.jsUnmodifiableArrayClass; | 3138 ClassElement get constListClass => helpers.jsUnmodifiableArrayClass; |
| 3359 ClassElement get fixedListClass => helpers.jsFixedArrayClass; | 3139 ClassElement get fixedListClass => helpers.jsFixedArrayClass; |
| 3360 ClassElement get growableListClass => helpers.jsExtendableArrayClass; | 3140 ClassElement get growableListClass => helpers.jsExtendableArrayClass; |
| 3361 ClassElement get mapClass => helpers.mapLiteralClass; | 3141 ClassElement get mapClass => helpers.mapLiteralClass; |
| 3362 ClassElement get constMapClass => helpers.constMapLiteralClass; | 3142 ClassElement get constMapClass => helpers.constMapLiteralClass; |
| 3363 ClassElement get typeClass => helpers.typeLiteralClass; | 3143 ClassElement get typeClass => helpers.typeLiteralClass; |
| 3364 ResolutionInterfaceType get typeType { | 3144 InterfaceType get typeType => _env.getRawType(typeClass); |
| 3365 return typeClass.computeType(helpers.backend.compiler.resolution); | |
| 3366 } | |
| 3367 | 3145 |
| 3368 ClassElement get boolClass => helpers.jsBoolClass; | 3146 ClassElement get boolClass => helpers.jsBoolClass; |
| 3369 ClassElement get nullClass => helpers.jsNullClass; | 3147 ClassElement get nullClass => helpers.jsNullClass; |
| 3370 ClassElement get syncStarIterableClass => helpers.syncStarIterable; | 3148 ClassElement get syncStarIterableClass => helpers.syncStarIterable; |
| 3371 ClassElement get asyncFutureClass => helpers.futureImplementation; | 3149 ClassElement get asyncFutureClass => helpers.futureImplementation; |
| 3372 ClassElement get asyncStarStreamClass => helpers.controllerStream; | 3150 ClassElement get asyncStarStreamClass => helpers.controllerStream; |
| 3373 ClassElement get functionClass => helpers.commonElements.functionClass; | 3151 ClassElement get functionClass => helpers.commonElements.functionClass; |
| 3374 ClassElement get indexableClass => helpers.jsIndexableClass; | 3152 ClassElement get indexableClass => helpers.jsIndexableClass; |
| 3375 ClassElement get mutableIndexableClass => helpers.jsMutableIndexableClass; | 3153 ClassElement get mutableIndexableClass => helpers.jsMutableIndexableClass; |
| 3376 ClassElement get indexingBehaviorClass => helpers.jsIndexingBehaviorInterface; | 3154 ClassElement get indexingBehaviorClass => helpers.jsIndexingBehaviorInterface; |
| 3377 ClassElement get interceptorClass => helpers.jsInterceptorClass; | 3155 ClassElement get interceptorClass => helpers.jsInterceptorClass; |
| 3378 | 3156 |
| 3379 bool isDefaultEqualityImplementation(MemberElement element) { | 3157 bool isDefaultEqualityImplementation(MemberElement element) { |
| 3380 assert(element.name == '=='); | 3158 assert(element.name == '=='); |
| 3381 ClassElement classElement = element.enclosingClass; | 3159 ClassElement classElement = element.enclosingClass; |
| 3382 return classElement == helpers.commonElements.objectClass || | 3160 return classElement == helpers.commonElements.objectClass || |
| 3383 classElement == helpers.jsInterceptorClass || | 3161 classElement == helpers.jsInterceptorClass || |
| 3384 classElement == helpers.jsNullClass; | 3162 classElement == helpers.jsNullClass; |
| 3385 } | 3163 } |
| 3386 | 3164 |
| 3387 @override | 3165 @override |
| 3388 bool isInterceptorClass(ClassElement cls) { | 3166 bool isInterceptorClass(ClassElement cls) { |
| 3389 return helpers.backend.isInterceptorClass(cls); | 3167 return _interceptorData.isInterceptorClass(cls); |
| 3390 } | 3168 } |
| 3391 | 3169 |
| 3392 @override | 3170 @override |
| 3393 bool isNativeClass(ClassElement element) { | 3171 bool isNativeClass(ClassElement element) { |
| 3394 return helpers.backend.isNative(element); | 3172 return _nativeData.isNative(element); |
| 3395 } | 3173 } |
| 3396 | 3174 |
| 3397 @override | 3175 @override |
| 3398 bool isNativeMember(MemberElement element) { | 3176 bool isNativeMember(MemberElement element) { |
| 3399 return helpers.backend.isNative(element); | 3177 return _nativeData.isNative(element); |
| 3400 } | 3178 } |
| 3401 } | 3179 } |
| OLD | NEW |