| 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 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 import '../io/start_end_information.dart' | 40 import '../io/start_end_information.dart' |
| 41 show StartEndSourceInformationStrategy; | 41 show StartEndSourceInformationStrategy; |
| 42 import '../js/js.dart' as jsAst; | 42 import '../js/js.dart' as jsAst; |
| 43 import '../js/js.dart' show js; | 43 import '../js/js.dart' show js; |
| 44 import '../js/js_source_mapping.dart' show JavaScriptSourceInformationStrategy; | 44 import '../js/js_source_mapping.dart' show JavaScriptSourceInformationStrategy; |
| 45 import '../js/rewrite_async.dart'; | 45 import '../js/rewrite_async.dart'; |
| 46 import '../js_emitter/js_emitter.dart' show CodeEmitterTask; | 46 import '../js_emitter/js_emitter.dart' show CodeEmitterTask; |
| 47 import '../kernel/task.dart'; | 47 import '../kernel/task.dart'; |
| 48 import '../library_loader.dart' show LibraryLoader, LoadedLibraries; | 48 import '../library_loader.dart' show LibraryLoader, LoadedLibraries; |
| 49 import '../native/native.dart' as native; | 49 import '../native/native.dart' as native; |
| 50 import '../options.dart' show CompilerOptions; |
| 50 import '../patch_parser.dart' | 51 import '../patch_parser.dart' |
| 51 show checkNativeAnnotation, checkJsInteropAnnotation; | 52 show checkNativeAnnotation, checkJsInteropAnnotation; |
| 52 import '../ssa/ssa.dart' show SsaFunctionCompiler; | 53 import '../ssa/ssa.dart' show SsaFunctionCompiler; |
| 53 import '../tracer.dart'; | 54 import '../tracer.dart'; |
| 54 import '../tree/tree.dart'; | 55 import '../tree/tree.dart'; |
| 55 import '../universe/call_structure.dart' show CallStructure; | 56 import '../universe/call_structure.dart' show CallStructure; |
| 56 import '../universe/feature.dart'; | 57 import '../universe/feature.dart'; |
| 57 import '../universe/selector.dart' show Selector; | 58 import '../universe/selector.dart' show Selector; |
| 58 import '../universe/world_builder.dart'; | 59 import '../universe/world_builder.dart'; |
| 59 import '../universe/use.dart' | 60 import '../universe/use.dart' |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 } | 303 } |
| 303 } | 304 } |
| 304 | 305 |
| 305 enum SyntheticConstantKind { | 306 enum SyntheticConstantKind { |
| 306 DUMMY_INTERCEPTOR, | 307 DUMMY_INTERCEPTOR, |
| 307 EMPTY_VALUE, | 308 EMPTY_VALUE, |
| 308 TYPEVARIABLE_REFERENCE, // Reference to a type in reflection data. | 309 TYPEVARIABLE_REFERENCE, // Reference to a type in reflection data. |
| 309 NAME | 310 NAME |
| 310 } | 311 } |
| 311 | 312 |
| 312 class JavaScriptBackend extends Target implements EnqueuerListener { | 313 class JavaScriptBackend extends Target { |
| 313 final Compiler compiler; | 314 final Compiler compiler; |
| 314 | 315 |
| 315 String get patchVersion => emitter.patchVersion; | 316 String get patchVersion => emitter.patchVersion; |
| 316 | 317 |
| 317 /// Returns true if the backend supports reflection. | 318 /// Returns true if the backend supports reflection. |
| 318 bool get supportsReflection => emitter.supportsReflection; | 319 bool get supportsReflection => emitter.supportsReflection; |
| 319 | 320 |
| 320 final Annotations annotations; | 321 final Annotations annotations; |
| 321 | 322 |
| 322 /// Set of classes that need to be considered for reflection although not | 323 /// Set of classes that need to be considered for reflection although not |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 List<CompilerTask> result = functionCompiler.tasks; | 372 List<CompilerTask> result = functionCompiler.tasks; |
| 372 result.add(emitter); | 373 result.add(emitter); |
| 373 result.add(patchResolverTask); | 374 result.add(patchResolverTask); |
| 374 result.add(kernelTask); | 375 result.add(kernelTask); |
| 375 return result; | 376 return result; |
| 376 } | 377 } |
| 377 | 378 |
| 378 final RuntimeTypes rti; | 379 final RuntimeTypes rti; |
| 379 final RuntimeTypesEncoder rtiEncoder; | 380 final RuntimeTypesEncoder rtiEncoder; |
| 380 | 381 |
| 381 /// True if a call to preserveUris has been seen and the preserve-uris flag | |
| 382 /// is set. | |
| 383 bool mustPreserveUris = false; | |
| 384 | |
| 385 /// True if a core-library function requires the preamble file to function. | |
| 386 bool requiresPreamble = false; | |
| 387 | |
| 388 /// True if the html library has been loaded. | 382 /// True if the html library has been loaded. |
| 389 bool htmlLibraryIsLoaded = false; | 383 bool htmlLibraryIsLoaded = false; |
| 390 | 384 |
| 391 /// True when we enqueue the loadLibrary code. | |
| 392 bool isLoadLibraryFunctionResolved = false; | |
| 393 | |
| 394 /// `true` if access to [BackendHelpers.invokeOnMethod] is supported. | |
| 395 bool hasInvokeOnSupport = false; | |
| 396 | |
| 397 /// `true` of `Object.runtimeType` is supported. | |
| 398 bool hasRuntimeTypeSupport = false; | |
| 399 | |
| 400 /// `true` of use of the `dart:isolate` library is supported. | |
| 401 bool hasIsolateSupport = false; | |
| 402 | |
| 403 /// `true` of `Function.apply` is supported. | |
| 404 bool hasFunctionApplySupport = false; | |
| 405 | |
| 406 /// List of constants from metadata. If metadata must be preserved, | 385 /// List of constants from metadata. If metadata must be preserved, |
| 407 /// these constants must be registered. | 386 /// these constants must be registered. |
| 408 final List<Dependency> metadataConstants = <Dependency>[]; | 387 final List<Dependency> metadataConstants = <Dependency>[]; |
| 409 | 388 |
| 410 /// Set of elements for which metadata has been registered as dependencies. | 389 /// Set of elements for which metadata has been registered as dependencies. |
| 411 final Set<Element> _registeredMetadata = new Set<Element>(); | 390 final Set<Element> _registeredMetadata = new Set<Element>(); |
| 412 | 391 |
| 413 TypeVariableHandler typeVariableHandler; | 392 TypeVariableHandler typeVariableHandler; |
| 414 | 393 |
| 415 /// Number of methods compiled before considering reflection. | 394 /// Number of methods compiled before considering reflection. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 | 437 |
| 459 StagedWorldImpactBuilder constantImpactsForCodegen = | 438 StagedWorldImpactBuilder constantImpactsForCodegen = |
| 460 new StagedWorldImpactBuilder(); | 439 new StagedWorldImpactBuilder(); |
| 461 | 440 |
| 462 final NativeData nativeData = new NativeData(); | 441 final NativeData nativeData = new NativeData(); |
| 463 InterceptorData _interceptorData; | 442 InterceptorData _interceptorData; |
| 464 BackendUsageImpl _backendUsage; | 443 BackendUsageImpl _backendUsage; |
| 465 final MirrorsData mirrorsData; | 444 final MirrorsData mirrorsData; |
| 466 CheckedModeHelpers _checkedModeHelpers; | 445 CheckedModeHelpers _checkedModeHelpers; |
| 467 | 446 |
| 447 ResolutionEnqueuerListener _resolutionEnqueuerListener; |
| 448 CodegenEnqueuerListener _codegenEnqueuerListener; |
| 449 |
| 468 BackendHelpers helpers; | 450 BackendHelpers helpers; |
| 469 final BackendImpacts impacts; | 451 final BackendImpacts impacts; |
| 470 | 452 |
| 471 /// Common classes used by the backend. | 453 /// Common classes used by the backend. |
| 472 BackendClasses backendClasses; | 454 BackendClasses backendClasses; |
| 473 | 455 |
| 474 /// Backend access to the front-end. | 456 /// Backend access to the front-end. |
| 475 final JSFrontendAccess frontend; | 457 final JSFrontendAccess frontend; |
| 476 | 458 |
| 477 Tracer tracer; | 459 Tracer tracer; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 508 kernelTask = new KernelTask(compiler); | 490 kernelTask = new KernelTask(compiler); |
| 509 constantCompilerTask = new JavaScriptConstantTask(compiler); | 491 constantCompilerTask = new JavaScriptConstantTask(compiler); |
| 510 impactTransformer = new JavaScriptImpactTransformer(this); | 492 impactTransformer = new JavaScriptImpactTransformer(this); |
| 511 patchResolverTask = new PatchResolverTask(compiler); | 493 patchResolverTask = new PatchResolverTask(compiler); |
| 512 functionCompiler = | 494 functionCompiler = |
| 513 new SsaFunctionCompiler(this, sourceInformationStrategy, useKernel); | 495 new SsaFunctionCompiler(this, sourceInformationStrategy, useKernel); |
| 514 serialization = new JavaScriptBackendSerialization(this); | 496 serialization = new JavaScriptBackendSerialization(this); |
| 515 _interceptorData = new InterceptorData(nativeData, helpers, commonElements); | 497 _interceptorData = new InterceptorData(nativeData, helpers, commonElements); |
| 516 backendClasses = new JavaScriptBackendClasses( | 498 backendClasses = new JavaScriptBackendClasses( |
| 517 compiler.elementEnvironment, helpers, nativeData, _interceptorData); | 499 compiler.elementEnvironment, helpers, nativeData, _interceptorData); |
| 500 _resolutionEnqueuerListener = new ResolutionEnqueuerListener(this); |
| 501 _codegenEnqueuerListener = new CodegenEnqueuerListener(this); |
| 518 } | 502 } |
| 519 | 503 |
| 520 /// The [ConstantSystem] used to interpret compile-time constants for this | 504 /// The [ConstantSystem] used to interpret compile-time constants for this |
| 521 /// backend. | 505 /// backend. |
| 522 ConstantSystem get constantSystem => constants.constantSystem; | 506 ConstantSystem get constantSystem => constants.constantSystem; |
| 523 | 507 |
| 524 DiagnosticReporter get reporter => compiler.reporter; | 508 DiagnosticReporter get reporter => compiler.reporter; |
| 525 | 509 |
| 526 CommonElements get commonElements => compiler.commonElements; | 510 CommonElements get commonElements => compiler.commonElements; |
| 527 | 511 |
| 528 Resolution get resolution => compiler.resolution; | 512 Resolution get resolution => compiler.resolution; |
| 529 | 513 |
| 530 InterceptorData get interceptorData => _interceptorData; | 514 InterceptorData get interceptorData => _interceptorData; |
| 531 | 515 |
| 532 BackendUsage get backendUsage => _backendUsage; | 516 BackendUsage get backendUsage => _backendUsage; |
| 533 | 517 |
| 534 BackendUsageBuilder get backendUsageBuilder => _backendUsage; | 518 BackendUsageBuilder get backendUsageBuilder => _backendUsage; |
| 535 | 519 |
| 536 CheckedModeHelpers get checkedModeHelpers => _checkedModeHelpers; | 520 CheckedModeHelpers get checkedModeHelpers => _checkedModeHelpers; |
| 537 | 521 |
| 522 EnqueuerListener get resolutionEnqueuerListener => |
| 523 _resolutionEnqueuerListener; |
| 524 |
| 525 EnqueuerListener get codegenEnqueuerListener => _codegenEnqueuerListener; |
| 526 |
| 538 /// Returns constant environment for the JavaScript interpretation of the | 527 /// Returns constant environment for the JavaScript interpretation of the |
| 539 /// constants. | 528 /// constants. |
| 540 JavaScriptConstantCompiler get constants { | 529 JavaScriptConstantCompiler get constants { |
| 541 return constantCompilerTask.jsConstantCompiler; | 530 return constantCompilerTask.jsConstantCompiler; |
| 542 } | 531 } |
| 543 | 532 |
| 544 @override | 533 @override |
| 545 bool isDefaultNoSuchMethod(MethodElement element) { | 534 bool isDefaultNoSuchMethod(MethodElement element) { |
| 546 return noSuchMethodRegistry.isDefaultNoSuchMethodImplementation(element); | 535 return noSuchMethodRegistry.isDefaultNoSuchMethodImplementation(element); |
| 547 } | 536 } |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 704 // differences. | 693 // differences. |
| 705 assert(invariant(interceptorMember, | 694 assert(invariant(interceptorMember, |
| 706 interceptorMember.enclosingClass == interceptorClass, | 695 interceptorMember.enclosingClass == interceptorClass, |
| 707 message: | 696 message: |
| 708 "Member ${member.name} not overridden in ${interceptorClass}. " | 697 "Member ${member.name} not overridden in ${interceptorClass}. " |
| 709 "Found $interceptorMember from " | 698 "Found $interceptorMember from " |
| 710 "${interceptorMember.enclosingClass}.")); | 699 "${interceptorMember.enclosingClass}.")); |
| 711 }); | 700 }); |
| 712 } | 701 } |
| 713 | 702 |
| 714 void addInterceptorsForNativeClassMembers(ClassElement cls, | |
| 715 {bool forResolution}) { | |
| 716 if (forResolution) { | |
| 717 cls.ensureResolved(resolution); | |
| 718 interceptorData.addInterceptorsForNativeClassMembers(cls); | |
| 719 } | |
| 720 } | |
| 721 | |
| 722 void addInterceptors(ClassElement cls, WorldImpactBuilder impactBuilder, | |
| 723 {bool forResolution}) { | |
| 724 if (forResolution) { | |
| 725 cls.ensureResolved(resolution); | |
| 726 interceptorData.addInterceptors(cls); | |
| 727 } | |
| 728 backendUsageBuilder.registerBackendInstantiation(impactBuilder, cls); | |
| 729 } | |
| 730 | |
| 731 /// Called during codegen when [constant] has been used. | 703 /// Called during codegen when [constant] has been used. |
| 732 void computeImpactForCompileTimeConstant(ConstantValue constant, | 704 void computeImpactForCompileTimeConstant(ConstantValue constant, |
| 733 WorldImpactBuilder impactBuilder, bool isForResolution) { | 705 WorldImpactBuilder impactBuilder, bool isForResolution) { |
| 734 computeImpactForCompileTimeConstantInternal( | 706 computeImpactForCompileTimeConstantInternal( |
| 735 constant, impactBuilder, isForResolution); | 707 constant, impactBuilder, isForResolution); |
| 736 | 708 |
| 737 if (!isForResolution && lookupMapAnalysis.isLookupMap(constant)) { | 709 if (!isForResolution && lookupMapAnalysis.isLookupMap(constant)) { |
| 738 // Note: internally, this registration will temporarily remove the | 710 // Note: internally, this registration will temporarily remove the |
| 739 // constant dependencies and add them later on-demand. | 711 // constant dependencies and add them later on-demand. |
| 740 lookupMapAnalysis.registerLookupMapReference(constant); | 712 lookupMapAnalysis.registerLookupMapReference(constant); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 794 // constant emitter will generate a call to the createRuntimeType | 766 // constant emitter will generate a call to the createRuntimeType |
| 795 // helper so we register a use of that. | 767 // helper so we register a use of that. |
| 796 impactBuilder.registerStaticUse(new StaticUse.staticInvoke( | 768 impactBuilder.registerStaticUse(new StaticUse.staticInvoke( |
| 797 // TODO(johnniwinther): Find the right [CallStructure]. | 769 // TODO(johnniwinther): Find the right [CallStructure]. |
| 798 helpers.createRuntimeType, | 770 helpers.createRuntimeType, |
| 799 null)); | 771 null)); |
| 800 } | 772 } |
| 801 } | 773 } |
| 802 } | 774 } |
| 803 | 775 |
| 804 WorldImpact registerInstantiatedClass(ClassElement cls, | 776 // TODO(johnniwinther): Avoid the need for this. |
| 805 {bool forResolution}) { | 777 WorldImpact computeHelpersImpact() => |
| 806 return _processClass(cls, forResolution: forResolution); | 778 _resolutionEnqueuerListener.computeHelpersImpact(); |
| 807 } | |
| 808 | |
| 809 WorldImpact registerImplementedClass(ClassElement cls, {bool forResolution}) { | |
| 810 return _processClass(cls, forResolution: forResolution); | |
| 811 } | |
| 812 | |
| 813 WorldImpact _processClass(ClassElement cls, {bool forResolution}) { | |
| 814 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl(); | |
| 815 if (!cls.typeVariables.isEmpty) { | |
| 816 typeVariableHandler.registerClassWithTypeVariables(cls, | |
| 817 forResolution: forResolution); | |
| 818 } | |
| 819 | |
| 820 // Register any helper that will be needed by the backend. | |
| 821 if (forResolution) { | |
| 822 if (cls == commonElements.intClass || | |
| 823 cls == commonElements.doubleClass || | |
| 824 cls == commonElements.numClass) { | |
| 825 backendUsageBuilder.registerBackendImpact( | |
| 826 impactBuilder, impacts.numClasses); | |
| 827 } else if (cls == commonElements.listClass || | |
| 828 cls == commonElements.stringClass) { | |
| 829 backendUsageBuilder.registerBackendImpact( | |
| 830 impactBuilder, impacts.listOrStringClasses); | |
| 831 } else if (cls == commonElements.functionClass) { | |
| 832 backendUsageBuilder.registerBackendImpact( | |
| 833 impactBuilder, impacts.functionClass); | |
| 834 } else if (cls == commonElements.mapClass) { | |
| 835 backendUsageBuilder.registerBackendImpact( | |
| 836 impactBuilder, impacts.mapClass); | |
| 837 // For map literals, the dependency between the implementation class | |
| 838 // and [Map] is not visible, so we have to add it manually. | |
| 839 rti.registerRtiDependency(helpers.mapLiteralClass, cls); | |
| 840 } else if (cls == helpers.boundClosureClass) { | |
| 841 backendUsageBuilder.registerBackendImpact( | |
| 842 impactBuilder, impacts.boundClosureClass); | |
| 843 } else if (nativeData.isNativeOrExtendsNative(cls)) { | |
| 844 backendUsageBuilder.registerBackendImpact( | |
| 845 impactBuilder, impacts.nativeOrExtendsClass); | |
| 846 } else if (cls == helpers.mapLiteralClass) { | |
| 847 backendUsageBuilder.registerBackendImpact( | |
| 848 impactBuilder, impacts.mapLiteralClass); | |
| 849 } | |
| 850 } | |
| 851 if (cls == helpers.closureClass) { | |
| 852 backendUsageBuilder.registerBackendImpact( | |
| 853 impactBuilder, impacts.closureClass); | |
| 854 } | |
| 855 if (cls == commonElements.stringClass || cls == helpers.jsStringClass) { | |
| 856 addInterceptors(helpers.jsStringClass, impactBuilder, | |
| 857 forResolution: forResolution); | |
| 858 } else if (cls == commonElements.listClass || | |
| 859 cls == helpers.jsArrayClass || | |
| 860 cls == helpers.jsFixedArrayClass || | |
| 861 cls == helpers.jsExtendableArrayClass || | |
| 862 cls == helpers.jsUnmodifiableArrayClass) { | |
| 863 addInterceptors(helpers.jsArrayClass, impactBuilder, | |
| 864 forResolution: forResolution); | |
| 865 addInterceptors(helpers.jsMutableArrayClass, impactBuilder, | |
| 866 forResolution: forResolution); | |
| 867 addInterceptors(helpers.jsFixedArrayClass, impactBuilder, | |
| 868 forResolution: forResolution); | |
| 869 addInterceptors(helpers.jsExtendableArrayClass, impactBuilder, | |
| 870 forResolution: forResolution); | |
| 871 addInterceptors(helpers.jsUnmodifiableArrayClass, impactBuilder, | |
| 872 forResolution: forResolution); | |
| 873 if (forResolution) { | |
| 874 backendUsageBuilder.registerBackendImpact( | |
| 875 impactBuilder, impacts.listClasses); | |
| 876 } | |
| 877 } else if (cls == commonElements.intClass || cls == helpers.jsIntClass) { | |
| 878 addInterceptors(helpers.jsIntClass, impactBuilder, | |
| 879 forResolution: forResolution); | |
| 880 addInterceptors(helpers.jsPositiveIntClass, impactBuilder, | |
| 881 forResolution: forResolution); | |
| 882 addInterceptors(helpers.jsUInt32Class, impactBuilder, | |
| 883 forResolution: forResolution); | |
| 884 addInterceptors(helpers.jsUInt31Class, impactBuilder, | |
| 885 forResolution: forResolution); | |
| 886 addInterceptors(helpers.jsNumberClass, impactBuilder, | |
| 887 forResolution: forResolution); | |
| 888 } else if (cls == commonElements.doubleClass || | |
| 889 cls == helpers.jsDoubleClass) { | |
| 890 addInterceptors(helpers.jsDoubleClass, impactBuilder, | |
| 891 forResolution: forResolution); | |
| 892 addInterceptors(helpers.jsNumberClass, impactBuilder, | |
| 893 forResolution: forResolution); | |
| 894 } else if (cls == commonElements.boolClass || cls == helpers.jsBoolClass) { | |
| 895 addInterceptors(helpers.jsBoolClass, impactBuilder, | |
| 896 forResolution: forResolution); | |
| 897 } else if (cls == commonElements.nullClass || cls == helpers.jsNullClass) { | |
| 898 addInterceptors(helpers.jsNullClass, impactBuilder, | |
| 899 forResolution: forResolution); | |
| 900 } else if (cls == commonElements.numClass || cls == helpers.jsNumberClass) { | |
| 901 addInterceptors(helpers.jsIntClass, impactBuilder, | |
| 902 forResolution: forResolution); | |
| 903 addInterceptors(helpers.jsPositiveIntClass, impactBuilder, | |
| 904 forResolution: forResolution); | |
| 905 addInterceptors(helpers.jsUInt32Class, impactBuilder, | |
| 906 forResolution: forResolution); | |
| 907 addInterceptors(helpers.jsUInt31Class, impactBuilder, | |
| 908 forResolution: forResolution); | |
| 909 addInterceptors(helpers.jsDoubleClass, impactBuilder, | |
| 910 forResolution: forResolution); | |
| 911 addInterceptors(helpers.jsNumberClass, impactBuilder, | |
| 912 forResolution: forResolution); | |
| 913 } else if (cls == helpers.jsJavaScriptObjectClass) { | |
| 914 addInterceptors(helpers.jsJavaScriptObjectClass, impactBuilder, | |
| 915 forResolution: forResolution); | |
| 916 } else if (cls == helpers.jsPlainJavaScriptObjectClass) { | |
| 917 addInterceptors(helpers.jsPlainJavaScriptObjectClass, impactBuilder, | |
| 918 forResolution: forResolution); | |
| 919 } else if (cls == helpers.jsUnknownJavaScriptObjectClass) { | |
| 920 addInterceptors(helpers.jsUnknownJavaScriptObjectClass, impactBuilder, | |
| 921 forResolution: forResolution); | |
| 922 } else if (cls == helpers.jsJavaScriptFunctionClass) { | |
| 923 addInterceptors(helpers.jsJavaScriptFunctionClass, impactBuilder, | |
| 924 forResolution: forResolution); | |
| 925 } else if (nativeData.isNativeOrExtendsNative(cls)) { | |
| 926 addInterceptorsForNativeClassMembers(cls, forResolution: forResolution); | |
| 927 } else if (cls == helpers.jsIndexingBehaviorInterface) { | |
| 928 backendUsageBuilder.registerBackendImpact( | |
| 929 impactBuilder, impacts.jsIndexingBehavior); | |
| 930 } | |
| 931 | |
| 932 customElementsAnalysis.registerInstantiatedClass(cls, | |
| 933 forResolution: forResolution); | |
| 934 if (!forResolution) { | |
| 935 lookupMapAnalysis.registerInstantiatedClass(cls); | |
| 936 } | |
| 937 | |
| 938 return impactBuilder; | |
| 939 } | |
| 940 | |
| 941 void registerInstantiatedType(ResolutionInterfaceType type, | |
| 942 {bool isGlobal: false}) { | |
| 943 if (isGlobal) { | |
| 944 backendUsageBuilder.registerGlobalDependency(type.element); | |
| 945 } | |
| 946 lookupMapAnalysis.registerInstantiatedType(type); | |
| 947 } | |
| 948 | |
| 949 /// Compute the [WorldImpact] for backend helper methods. | |
| 950 WorldImpact computeHelpersImpact() { | |
| 951 assert(helpers.interceptorsLibrary != null); | |
| 952 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl(); | |
| 953 // TODO(ngeoffray): Not enqueuing those two classes currently make | |
| 954 // the compiler potentially crash. However, any reasonable program | |
| 955 // will instantiate those two classes. | |
| 956 addInterceptors(helpers.jsBoolClass, impactBuilder, forResolution: true); | |
| 957 addInterceptors(helpers.jsNullClass, impactBuilder, forResolution: true); | |
| 958 if (compiler.options.enableTypeAssertions) { | |
| 959 backendUsageBuilder.registerBackendImpact( | |
| 960 impactBuilder, impacts.enableTypeAssertions); | |
| 961 } | |
| 962 | |
| 963 if (TRACE_CALLS) { | |
| 964 backendUsageBuilder.registerBackendImpact( | |
| 965 impactBuilder, impacts.traceHelper); | |
| 966 } | |
| 967 backendUsageBuilder.registerBackendImpact( | |
| 968 impactBuilder, impacts.assertUnreachable); | |
| 969 _registerCheckedModeHelpers(impactBuilder); | |
| 970 return impactBuilder; | |
| 971 } | |
| 972 | 779 |
| 973 void onResolutionComplete( | 780 void onResolutionComplete( |
| 974 ClosedWorld closedWorld, ClosedWorldRefiner closedWorldRefiner) { | 781 ClosedWorld closedWorld, ClosedWorldRefiner closedWorldRefiner) { |
| 975 for (Entity entity in compiler.enqueuer.resolution.processedEntities) { | 782 for (Entity entity in compiler.enqueuer.resolution.processedEntities) { |
| 976 processAnnotations(entity, closedWorldRefiner); | 783 processAnnotations(entity, closedWorldRefiner); |
| 977 } | 784 } |
| 978 mirrorsData.computeMembersNeededForReflection(closedWorld); | 785 mirrorsData.computeMembersNeededForReflection(closedWorld); |
| 979 rti.computeClassesNeedingRti( | 786 rti.computeClassesNeedingRti( |
| 980 compiler.enqueuer.resolution.worldBuilder, closedWorld); | 787 compiler.enqueuer.resolution.worldBuilder, closedWorld); |
| 981 _registeredMetadata.clear(); | 788 _registeredMetadata.clear(); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1100 backendUsageBuilder.registerBackendImpact( | 907 backendUsageBuilder.registerBackendImpact( |
| 1101 impactBuilder, impacts.isolateSupport); | 908 impactBuilder, impacts.isolateSupport); |
| 1102 if (forResolution) { | 909 if (forResolution) { |
| 1103 backendUsageBuilder.registerBackendImpact( | 910 backendUsageBuilder.registerBackendImpact( |
| 1104 impactBuilder, impacts.isolateSupportForResolution); | 911 impactBuilder, impacts.isolateSupportForResolution); |
| 1105 } | 912 } |
| 1106 return impactBuilder; | 913 return impactBuilder; |
| 1107 } | 914 } |
| 1108 | 915 |
| 1109 bool classNeedsRti(ClassElement cls) { | 916 bool classNeedsRti(ClassElement cls) { |
| 1110 if (hasRuntimeTypeSupport) return true; | 917 if (backendUsage.isRuntimeTypeUsed) return true; |
| 1111 return rti.classesNeedingRti.contains(cls.declaration); | 918 return rti.classesNeedingRti.contains(cls.declaration); |
| 1112 } | 919 } |
| 1113 | 920 |
| 1114 bool classNeedsRtiField(ClassElement cls) { | 921 bool classNeedsRtiField(ClassElement cls) { |
| 1115 if (cls.rawType.typeArguments.isEmpty) return false; | 922 if (cls.rawType.typeArguments.isEmpty) return false; |
| 1116 if (hasRuntimeTypeSupport) return true; | 923 if (backendUsage.isRuntimeTypeUsed) return true; |
| 1117 return rti.classesNeedingRti.contains(cls.declaration); | 924 return rti.classesNeedingRti.contains(cls.declaration); |
| 1118 } | 925 } |
| 1119 | 926 |
| 1120 bool isComplexNoSuchMethod(FunctionElement element) => | 927 bool isComplexNoSuchMethod(FunctionElement element) => |
| 1121 noSuchMethodRegistry.isComplex(element); | 928 noSuchMethodRegistry.isComplex(element); |
| 1122 | 929 |
| 1123 bool methodNeedsRti(FunctionElement function) { | 930 bool methodNeedsRti(FunctionElement function) { |
| 1124 return rti.methodsNeedingRti.contains(function) || hasRuntimeTypeSupport; | 931 return rti.methodsNeedingRti.contains(function) || |
| 932 backendUsage.isRuntimeTypeUsed; |
| 1125 } | 933 } |
| 1126 | 934 |
| 1127 CodegenEnqueuer get codegenEnqueuer => compiler.enqueuer.codegen; | 935 CodegenEnqueuer get codegenEnqueuer => compiler.enqueuer.codegen; |
| 1128 | 936 |
| 1129 /// Creates an [Enqueuer] for code generation specific to this backend. | 937 /// Creates an [Enqueuer] for code generation specific to this backend. |
| 1130 CodegenEnqueuer createCodegenEnqueuer(CompilerTask task, Compiler compiler) { | 938 CodegenEnqueuer createCodegenEnqueuer(CompilerTask task, Compiler compiler) { |
| 1131 return new CodegenEnqueuer( | 939 return new CodegenEnqueuer( |
| 1132 task, this, compiler.options, const TreeShakingEnqueuerStrategy()); | 940 task, this, compiler.options, const TreeShakingEnqueuerStrategy()); |
| 1133 } | 941 } |
| 1134 | 942 |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1269 | 1077 |
| 1270 Element getDartClass(Element element) { | 1078 Element getDartClass(Element element) { |
| 1271 for (ClassElement dartClass in implementationClasses.keys) { | 1079 for (ClassElement dartClass in implementationClasses.keys) { |
| 1272 if (element == implementationClasses[dartClass]) { | 1080 if (element == implementationClasses[dartClass]) { |
| 1273 return dartClass; | 1081 return dartClass; |
| 1274 } | 1082 } |
| 1275 } | 1083 } |
| 1276 return element; | 1084 return element; |
| 1277 } | 1085 } |
| 1278 | 1086 |
| 1279 void _registerCheckedModeHelpers(WorldImpactBuilder impactBuilder) { | |
| 1280 // We register all the helpers in the resolution queue. | |
| 1281 // TODO(13155): Find a way to register fewer helpers. | |
| 1282 List<Element> staticUses = <Element>[]; | |
| 1283 for (CheckedModeHelper helper in CheckedModeHelpers.helpers) { | |
| 1284 staticUses.add(helper.getStaticUse(helpers).element); | |
| 1285 } | |
| 1286 backendUsageBuilder.registerBackendImpact( | |
| 1287 impactBuilder, new BackendImpact(globalUses: staticUses)); | |
| 1288 } | |
| 1289 | |
| 1290 /** | 1087 /** |
| 1291 * Returns [:true:] if the checking of [type] is performed directly on the | 1088 * Returns [:true:] if the checking of [type] is performed directly on the |
| 1292 * object and not on an interceptor. | 1089 * object and not on an interceptor. |
| 1293 */ | 1090 */ |
| 1294 bool hasDirectCheckFor(ResolutionDartType type) { | 1091 bool hasDirectCheckFor(ResolutionDartType type) { |
| 1295 Element element = type.element; | 1092 Element element = type.element; |
| 1296 return element == commonElements.stringClass || | 1093 return element == commonElements.stringClass || |
| 1297 element == commonElements.boolClass || | 1094 element == commonElements.boolClass || |
| 1298 element == commonElements.numClass || | 1095 element == commonElements.numClass || |
| 1299 element == commonElements.intClass || | 1096 element == commonElements.intClass || |
| 1300 element == commonElements.doubleClass || | 1097 element == commonElements.doubleClass || |
| 1301 element == helpers.jsArrayClass || | 1098 element == helpers.jsArrayClass || |
| 1302 element == helpers.jsMutableArrayClass || | 1099 element == helpers.jsMutableArrayClass || |
| 1303 element == helpers.jsExtendableArrayClass || | 1100 element == helpers.jsExtendableArrayClass || |
| 1304 element == helpers.jsFixedArrayClass || | 1101 element == helpers.jsFixedArrayClass || |
| 1305 element == helpers.jsUnmodifiableArrayClass; | 1102 element == helpers.jsUnmodifiableArrayClass; |
| 1306 } | 1103 } |
| 1307 | 1104 |
| 1308 bool mayGenerateInstanceofCheck(ResolutionDartType type) { | 1105 bool mayGenerateInstanceofCheck(ResolutionDartType type) { |
| 1309 // We can use an instanceof check for raw types that have no subclass that | 1106 // We can use an instanceof check for raw types that have no subclass that |
| 1310 // is mixed-in or in an implements clause. | 1107 // is mixed-in or in an implements clause. |
| 1311 | 1108 |
| 1312 if (!type.isRaw) return false; | 1109 if (!type.isRaw) return false; |
| 1313 ClassElement classElement = type.element; | 1110 ClassElement classElement = type.element; |
| 1314 if (interceptorData.isInterceptorClass(classElement)) return false; | 1111 if (interceptorData.isInterceptorClass(classElement)) return false; |
| 1315 return _closedWorld.hasOnlySubclasses(classElement); | 1112 return _closedWorld.hasOnlySubclasses(classElement); |
| 1316 } | 1113 } |
| 1317 | 1114 |
| 1318 WorldImpact registerUsedElement(MemberElement element, {bool forResolution}) { | |
| 1319 WorldImpactBuilderImpl worldImpact = new WorldImpactBuilderImpl(); | |
| 1320 backendUsageBuilder.registerUsedMember(element); | |
| 1321 if (element == helpers.disableTreeShakingMarker) { | |
| 1322 mirrorsData.isTreeShakingDisabled = true; | |
| 1323 } else if (element == helpers.preserveNamesMarker) { | |
| 1324 mirrorsData.mustPreserveNames = true; | |
| 1325 } else if (element == helpers.preserveMetadataMarker) { | |
| 1326 mirrorsData.mustRetainMetadata = true; | |
| 1327 } else if (element == helpers.preserveUrisMarker) { | |
| 1328 if (compiler.options.preserveUris) mustPreserveUris = true; | |
| 1329 } else if (element == helpers.preserveLibraryNamesMarker) { | |
| 1330 mirrorsData.mustRetainLibraryNames = true; | |
| 1331 } else if (element.isDeferredLoaderGetter) { | |
| 1332 // TODO(sigurdm): Create a function registerLoadLibraryAccess. | |
| 1333 if (!isLoadLibraryFunctionResolved) { | |
| 1334 isLoadLibraryFunctionResolved = true; | |
| 1335 if (forResolution) { | |
| 1336 backendUsageBuilder.registerBackendImpact( | |
| 1337 worldImpact, impacts.loadLibrary); | |
| 1338 } | |
| 1339 } | |
| 1340 } else if (element == helpers.requiresPreambleMarker) { | |
| 1341 requiresPreamble = true; | |
| 1342 } else if (element == helpers.invokeOnMethod && forResolution) { | |
| 1343 hasInvokeOnSupport = true; | |
| 1344 } | |
| 1345 customElementsAnalysis.registerStaticUse(element, | |
| 1346 forResolution: forResolution); | |
| 1347 | |
| 1348 if (element.isFunction && element.isInstanceMember) { | |
| 1349 MemberElement function = element; | |
| 1350 ClassElement cls = function.enclosingClass; | |
| 1351 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { | |
| 1352 worldImpact.addImpact(registerCallMethodWithFreeTypeVariables(function, | |
| 1353 forResolution: forResolution)); | |
| 1354 } | |
| 1355 } | |
| 1356 if (forResolution) { | |
| 1357 // Enable isolate support if we start using something from the isolate | |
| 1358 // library, or timers for the async library. We exclude constant fields, | |
| 1359 // which are ending here because their initializing expression is | |
| 1360 // compiled. | |
| 1361 LibraryElement library = element.library; | |
| 1362 if (!hasIsolateSupport && !(element.isField && element.isConst)) { | |
| 1363 Uri uri = library.canonicalUri; | |
| 1364 if (uri == Uris.dart_isolate) { | |
| 1365 hasIsolateSupport = true; | |
| 1366 worldImpact | |
| 1367 .addImpact(enableIsolateSupport(forResolution: forResolution)); | |
| 1368 } else if (uri == Uris.dart_async) { | |
| 1369 if (element.name == '_createTimer' || | |
| 1370 element.name == '_createPeriodicTimer') { | |
| 1371 // The [:Timer:] class uses the event queue of the isolate | |
| 1372 // library, so we make sure that event queue is generated. | |
| 1373 hasIsolateSupport = true; | |
| 1374 worldImpact | |
| 1375 .addImpact(enableIsolateSupport(forResolution: forResolution)); | |
| 1376 } | |
| 1377 } | |
| 1378 } | |
| 1379 | |
| 1380 if (element.isGetter && element.name == Identifiers.runtimeType_) { | |
| 1381 // Enable runtime type support if we discover a getter called | |
| 1382 // runtimeType. We have to enable runtime type before hitting the | |
| 1383 // codegen, so that constructors know whether they need to generate code | |
| 1384 // for runtime type. | |
| 1385 hasRuntimeTypeSupport = true; | |
| 1386 // TODO(ahe): Record precise dependency here. | |
| 1387 worldImpact.addImpact(registerRuntimeType()); | |
| 1388 } else if (compiler.commonElements.isFunctionApplyMethod(element)) { | |
| 1389 hasFunctionApplySupport = true; | |
| 1390 } | |
| 1391 } else { | |
| 1392 // TODO(sigmund): add other missing dependencies (internals, selectors | |
| 1393 // enqueued after allocations). | |
| 1394 compiler.dumpInfoTask.registerDependency(element); | |
| 1395 } | |
| 1396 return worldImpact; | |
| 1397 } | |
| 1398 | |
| 1399 /// This method is called immediately after the [library] and its parts have | 1115 /// This method is called immediately after the [library] and its parts have |
| 1400 /// been scanned. | 1116 /// been scanned. |
| 1401 Future onLibraryScanned(LibraryElement library, LibraryLoader loader) { | 1117 Future onLibraryScanned(LibraryElement library, LibraryLoader loader) { |
| 1402 if (!compiler.serialization.isDeserialized(library)) { | 1118 if (!compiler.serialization.isDeserialized(library)) { |
| 1403 if (canLibraryUseNative(library)) { | 1119 if (canLibraryUseNative(library)) { |
| 1404 library.forEachLocalMember((Element element) { | 1120 library.forEachLocalMember((Element element) { |
| 1405 if (element.isClass) { | 1121 if (element.isClass) { |
| 1406 checkNativeAnnotation(compiler, element); | 1122 checkNativeAnnotation(compiler, element); |
| 1407 } | 1123 } |
| 1408 }); | 1124 }); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1513 if (target == null) continue; | 1229 if (target == null) continue; |
| 1514 if (target.isField) { | 1230 if (target.isField) { |
| 1515 staticFields.add(target); | 1231 staticFields.add(target); |
| 1516 } else if (target.isLibrary || target.isClass) { | 1232 } else if (target.isLibrary || target.isClass) { |
| 1517 addFieldsInContainer(target); | 1233 addFieldsInContainer(target); |
| 1518 } | 1234 } |
| 1519 } | 1235 } |
| 1520 return staticFields; | 1236 return staticFields; |
| 1521 } | 1237 } |
| 1522 | 1238 |
| 1523 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses) { | 1239 // TODO(johnniwinther): Split this into [ResolutionEnqueuerListener] |
| 1240 // and [CodegenEnqueuerListener]. |
| 1241 bool _onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses) { |
| 1524 // Add elements used synthetically, that is, through features rather than | 1242 // Add elements used synthetically, that is, through features rather than |
| 1525 // syntax, for instance custom elements. | 1243 // syntax, for instance custom elements. |
| 1526 // | 1244 // |
| 1527 // Return early if any elements are added to avoid counting the elements as | 1245 // Return early if any elements are added to avoid counting the elements as |
| 1528 // due to mirrors. | 1246 // due to mirrors. |
| 1529 enqueuer.applyImpact(customElementsAnalysis.flush( | 1247 enqueuer.applyImpact(customElementsAnalysis.flush( |
| 1530 forResolution: enqueuer.isResolutionQueue)); | 1248 forResolution: enqueuer.isResolutionQueue)); |
| 1531 enqueuer.applyImpact( | 1249 enqueuer.applyImpact( |
| 1532 lookupMapAnalysis.flush(forResolution: enqueuer.isResolutionQueue)); | 1250 lookupMapAnalysis.flush(forResolution: enqueuer.isResolutionQueue)); |
| 1533 enqueuer.applyImpact( | 1251 enqueuer.applyImpact( |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1681 } | 1399 } |
| 1682 | 1400 |
| 1683 /// Called when the compiler starts running the codegen enqueuer. The | 1401 /// Called when the compiler starts running the codegen enqueuer. The |
| 1684 /// [WorldImpact] of enabled backend features is returned. | 1402 /// [WorldImpact] of enabled backend features is returned. |
| 1685 WorldImpact onCodegenStart(ClosedWorld closedWorld) { | 1403 WorldImpact onCodegenStart(ClosedWorld closedWorld) { |
| 1686 _closedWorld = closedWorld; | 1404 _closedWorld = closedWorld; |
| 1687 _namer = determineNamer(_closedWorld, compiler.codegenWorldBuilder); | 1405 _namer = determineNamer(_closedWorld, compiler.codegenWorldBuilder); |
| 1688 tracer = new Tracer(_closedWorld, namer, compiler.outputProvider); | 1406 tracer = new Tracer(_closedWorld, namer, compiler.outputProvider); |
| 1689 emitter.createEmitter(_namer, _closedWorld); | 1407 emitter.createEmitter(_namer, _closedWorld); |
| 1690 lookupMapAnalysis.onCodegenStart(); | 1408 lookupMapAnalysis.onCodegenStart(); |
| 1691 if (hasIsolateSupport) { | 1409 if (backendUsage.isIsolateInUse) { |
| 1692 return enableIsolateSupport(forResolution: false); | 1410 return enableIsolateSupport(forResolution: false); |
| 1693 } | 1411 } |
| 1694 return const WorldImpact(); | 1412 return const WorldImpact(); |
| 1695 } | 1413 } |
| 1696 | 1414 |
| 1697 /// Called when code generation has been completed. | 1415 /// Called when code generation has been completed. |
| 1698 void onCodegenEnd() { | 1416 void onCodegenEnd() { |
| 1699 sourceInformationStrategy.onComplete(); | 1417 sourceInformationStrategy.onComplete(); |
| 1700 tracer.close(); | 1418 tracer.close(); |
| 1701 } | 1419 } |
| (...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2573 } | 2291 } |
| 2574 | 2292 |
| 2575 @override | 2293 @override |
| 2576 FieldEntity get symbolField => helpers.symbolImplementationField; | 2294 FieldEntity get symbolField => helpers.symbolImplementationField; |
| 2577 | 2295 |
| 2578 @override | 2296 @override |
| 2579 InterfaceType get symbolType { | 2297 InterfaceType get symbolType { |
| 2580 return _env.getRawType(helpers.symbolImplementationClass); | 2298 return _env.getRawType(helpers.symbolImplementationClass); |
| 2581 } | 2299 } |
| 2582 } | 2300 } |
| 2301 |
| 2302 abstract class EnqueuerListenerBase implements EnqueuerListener { |
| 2303 // TODO(johnniwinther): Avoid the need for accessing through [_backend]. |
| 2304 JavaScriptBackend _backend; |
| 2305 |
| 2306 EnqueuerListenerBase(this._backend); |
| 2307 |
| 2308 // TODO(johnniwinther): Change these to final fields. |
| 2309 CommonElements get commonElements => _backend.commonElements; |
| 2310 BackendHelpers get helpers => _backend.helpers; |
| 2311 BackendImpacts get impacts => _backend.impacts; |
| 2312 BackendUsageBuilder get backendUsage => _backend.backendUsageBuilder; |
| 2313 CustomElementsAnalysis get customElementsAnalysis => |
| 2314 _backend.customElementsAnalysis; |
| 2315 NativeData get nativeData => _backend.nativeData; |
| 2316 InterceptorData get interceptorData => _backend.interceptorData; |
| 2317 RuntimeTypes get rti => _backend.rti; |
| 2318 TypeVariableHandler get typeVariableHandler => _backend.typeVariableHandler; |
| 2319 Resolution get resolution => _backend.resolution; |
| 2320 MirrorsData get mirrorsData => _backend.mirrorsData; |
| 2321 CompilerOptions get options => _backend.compiler.options; |
| 2322 |
| 2323 WorldImpact registerBoundClosure() { |
| 2324 return backendUsage.createImpactFor(impacts.memberClosure); |
| 2325 } |
| 2326 |
| 2327 WorldImpact registerGetOfStaticFunction() { |
| 2328 return backendUsage.createImpactFor(impacts.staticClosure); |
| 2329 } |
| 2330 |
| 2331 WorldImpact _registerComputeSignature() { |
| 2332 return backendUsage.createImpactFor(impacts.computeSignature); |
| 2333 } |
| 2334 |
| 2335 /// Called to register that an instantiated generic class has a call method. |
| 2336 /// Any backend specific [WorldImpact] of this is returned. |
| 2337 /// |
| 2338 /// Note: The [callMethod] is registered even thought it doesn't reference |
| 2339 /// the type variables. |
| 2340 WorldImpact registerCallMethodWithFreeTypeVariables(Element callMethod); |
| 2341 |
| 2342 WorldImpact _processClass(ClassElement cls, {bool forResolution}) { |
| 2343 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl(); |
| 2344 if (!cls.typeVariables.isEmpty) { |
| 2345 typeVariableHandler.registerClassWithTypeVariables(cls, |
| 2346 forResolution: forResolution); |
| 2347 } |
| 2348 |
| 2349 // Register any helper that will be needed by the backend. |
| 2350 if (forResolution) { |
| 2351 if (cls == commonElements.intClass || |
| 2352 cls == commonElements.doubleClass || |
| 2353 cls == commonElements.numClass) { |
| 2354 backendUsage.registerBackendImpact(impactBuilder, impacts.numClasses); |
| 2355 } else if (cls == commonElements.listClass || |
| 2356 cls == commonElements.stringClass) { |
| 2357 backendUsage.registerBackendImpact( |
| 2358 impactBuilder, impacts.listOrStringClasses); |
| 2359 } else if (cls == commonElements.functionClass) { |
| 2360 backendUsage.registerBackendImpact( |
| 2361 impactBuilder, impacts.functionClass); |
| 2362 } else if (cls == commonElements.mapClass) { |
| 2363 backendUsage.registerBackendImpact(impactBuilder, impacts.mapClass); |
| 2364 // For map literals, the dependency between the implementation class |
| 2365 // and [Map] is not visible, so we have to add it manually. |
| 2366 rti.registerRtiDependency(helpers.mapLiteralClass, cls); |
| 2367 } else if (cls == helpers.boundClosureClass) { |
| 2368 backendUsage.registerBackendImpact( |
| 2369 impactBuilder, impacts.boundClosureClass); |
| 2370 } else if (nativeData.isNativeOrExtendsNative(cls)) { |
| 2371 backendUsage.registerBackendImpact( |
| 2372 impactBuilder, impacts.nativeOrExtendsClass); |
| 2373 } else if (cls == helpers.mapLiteralClass) { |
| 2374 backendUsage.registerBackendImpact( |
| 2375 impactBuilder, impacts.mapLiteralClass); |
| 2376 } |
| 2377 } |
| 2378 if (cls == helpers.closureClass) { |
| 2379 backendUsage.registerBackendImpact(impactBuilder, impacts.closureClass); |
| 2380 } |
| 2381 if (cls == commonElements.stringClass || cls == helpers.jsStringClass) { |
| 2382 addInterceptors(helpers.jsStringClass, impactBuilder, |
| 2383 forResolution: forResolution); |
| 2384 } else if (cls == commonElements.listClass || |
| 2385 cls == helpers.jsArrayClass || |
| 2386 cls == helpers.jsFixedArrayClass || |
| 2387 cls == helpers.jsExtendableArrayClass || |
| 2388 cls == helpers.jsUnmodifiableArrayClass) { |
| 2389 addInterceptors(helpers.jsArrayClass, impactBuilder, |
| 2390 forResolution: forResolution); |
| 2391 addInterceptors(helpers.jsMutableArrayClass, impactBuilder, |
| 2392 forResolution: forResolution); |
| 2393 addInterceptors(helpers.jsFixedArrayClass, impactBuilder, |
| 2394 forResolution: forResolution); |
| 2395 addInterceptors(helpers.jsExtendableArrayClass, impactBuilder, |
| 2396 forResolution: forResolution); |
| 2397 addInterceptors(helpers.jsUnmodifiableArrayClass, impactBuilder, |
| 2398 forResolution: forResolution); |
| 2399 if (forResolution) { |
| 2400 backendUsage.registerBackendImpact(impactBuilder, impacts.listClasses); |
| 2401 } |
| 2402 } else if (cls == commonElements.intClass || cls == helpers.jsIntClass) { |
| 2403 addInterceptors(helpers.jsIntClass, impactBuilder, |
| 2404 forResolution: forResolution); |
| 2405 addInterceptors(helpers.jsPositiveIntClass, impactBuilder, |
| 2406 forResolution: forResolution); |
| 2407 addInterceptors(helpers.jsUInt32Class, impactBuilder, |
| 2408 forResolution: forResolution); |
| 2409 addInterceptors(helpers.jsUInt31Class, impactBuilder, |
| 2410 forResolution: forResolution); |
| 2411 addInterceptors(helpers.jsNumberClass, impactBuilder, |
| 2412 forResolution: forResolution); |
| 2413 } else if (cls == commonElements.doubleClass || |
| 2414 cls == helpers.jsDoubleClass) { |
| 2415 addInterceptors(helpers.jsDoubleClass, impactBuilder, |
| 2416 forResolution: forResolution); |
| 2417 addInterceptors(helpers.jsNumberClass, impactBuilder, |
| 2418 forResolution: forResolution); |
| 2419 } else if (cls == commonElements.boolClass || cls == helpers.jsBoolClass) { |
| 2420 addInterceptors(helpers.jsBoolClass, impactBuilder, |
| 2421 forResolution: forResolution); |
| 2422 } else if (cls == commonElements.nullClass || cls == helpers.jsNullClass) { |
| 2423 addInterceptors(helpers.jsNullClass, impactBuilder, |
| 2424 forResolution: forResolution); |
| 2425 } else if (cls == commonElements.numClass || cls == helpers.jsNumberClass) { |
| 2426 addInterceptors(helpers.jsIntClass, impactBuilder, |
| 2427 forResolution: forResolution); |
| 2428 addInterceptors(helpers.jsPositiveIntClass, impactBuilder, |
| 2429 forResolution: forResolution); |
| 2430 addInterceptors(helpers.jsUInt32Class, impactBuilder, |
| 2431 forResolution: forResolution); |
| 2432 addInterceptors(helpers.jsUInt31Class, impactBuilder, |
| 2433 forResolution: forResolution); |
| 2434 addInterceptors(helpers.jsDoubleClass, impactBuilder, |
| 2435 forResolution: forResolution); |
| 2436 addInterceptors(helpers.jsNumberClass, impactBuilder, |
| 2437 forResolution: forResolution); |
| 2438 } else if (cls == helpers.jsJavaScriptObjectClass) { |
| 2439 addInterceptors(helpers.jsJavaScriptObjectClass, impactBuilder, |
| 2440 forResolution: forResolution); |
| 2441 } else if (cls == helpers.jsPlainJavaScriptObjectClass) { |
| 2442 addInterceptors(helpers.jsPlainJavaScriptObjectClass, impactBuilder, |
| 2443 forResolution: forResolution); |
| 2444 } else if (cls == helpers.jsUnknownJavaScriptObjectClass) { |
| 2445 addInterceptors(helpers.jsUnknownJavaScriptObjectClass, impactBuilder, |
| 2446 forResolution: forResolution); |
| 2447 } else if (cls == helpers.jsJavaScriptFunctionClass) { |
| 2448 addInterceptors(helpers.jsJavaScriptFunctionClass, impactBuilder, |
| 2449 forResolution: forResolution); |
| 2450 } else if (nativeData.isNativeOrExtendsNative(cls)) { |
| 2451 addInterceptorsForNativeClassMembers(cls, forResolution: forResolution); |
| 2452 } else if (cls == helpers.jsIndexingBehaviorInterface) { |
| 2453 backendUsage.registerBackendImpact( |
| 2454 impactBuilder, impacts.jsIndexingBehavior); |
| 2455 } |
| 2456 |
| 2457 customElementsAnalysis.registerInstantiatedClass(cls, |
| 2458 forResolution: forResolution); |
| 2459 |
| 2460 return impactBuilder; |
| 2461 } |
| 2462 |
| 2463 void addInterceptorsForNativeClassMembers(ClassElement cls, |
| 2464 {bool forResolution}) { |
| 2465 if (forResolution) { |
| 2466 cls.ensureResolved(resolution); |
| 2467 interceptorData.addInterceptorsForNativeClassMembers(cls); |
| 2468 } |
| 2469 } |
| 2470 |
| 2471 void addInterceptors(ClassElement cls, WorldImpactBuilder impactBuilder, |
| 2472 {bool forResolution}) { |
| 2473 if (forResolution) { |
| 2474 cls.ensureResolved(resolution); |
| 2475 interceptorData.addInterceptors(cls); |
| 2476 } |
| 2477 backendUsage.registerBackendInstantiation(impactBuilder, cls); |
| 2478 } |
| 2479 |
| 2480 void _registerUsedElement( |
| 2481 WorldImpactBuilderImpl worldImpact, MemberElement element, |
| 2482 {bool forResolution}) { |
| 2483 backendUsage.registerUsedMember(element); |
| 2484 mirrorsData.registerUsedMember(element); |
| 2485 customElementsAnalysis.registerStaticUse(element, |
| 2486 forResolution: forResolution); |
| 2487 |
| 2488 if (element.isFunction && element.isInstanceMember) { |
| 2489 MemberElement function = element; |
| 2490 ClassElement cls = function.enclosingClass; |
| 2491 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { |
| 2492 worldImpact |
| 2493 .addImpact(registerCallMethodWithFreeTypeVariables(function)); |
| 2494 } |
| 2495 } |
| 2496 } |
| 2497 } |
| 2498 |
| 2499 class ResolutionEnqueuerListener extends EnqueuerListenerBase { |
| 2500 ResolutionEnqueuerListener(JavaScriptBackend backend) : super(backend); |
| 2501 |
| 2502 // TODO(johnniwinther): Change this to a final field. |
| 2503 NoSuchMethodRegistry get noSuchMethodRegistry => |
| 2504 _backend.noSuchMethodRegistry; |
| 2505 |
| 2506 /// True when we enqueue the loadLibrary code. |
| 2507 bool _isLoadLibraryFunctionResolved = false; |
| 2508 |
| 2509 @override |
| 2510 void registerInstantiatedType(ResolutionInterfaceType type, |
| 2511 {bool isGlobal: false}) { |
| 2512 if (isGlobal) { |
| 2513 backendUsage.registerGlobalDependency(type.element); |
| 2514 } |
| 2515 } |
| 2516 |
| 2517 @override |
| 2518 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses) { |
| 2519 return _backend._onQueueEmpty(enqueuer, recentClasses); |
| 2520 } |
| 2521 |
| 2522 @override |
| 2523 WorldImpact registerUsedElement(MemberElement member) { |
| 2524 WorldImpactBuilderImpl worldImpact = new WorldImpactBuilderImpl(); |
| 2525 _registerUsedElement(worldImpact, member, forResolution: true); |
| 2526 |
| 2527 if (member.isDeferredLoaderGetter) { |
| 2528 // TODO(sigurdm): Create a function registerLoadLibraryAccess. |
| 2529 if (!_isLoadLibraryFunctionResolved) { |
| 2530 _isLoadLibraryFunctionResolved = true; |
| 2531 backendUsage.registerBackendImpact(worldImpact, impacts.loadLibrary); |
| 2532 } |
| 2533 } |
| 2534 |
| 2535 // Enable isolate support if we start using something from the isolate |
| 2536 // library, or timers for the async library. We exclude constant fields, |
| 2537 // which are ending here because their initializing expression is |
| 2538 // compiled. |
| 2539 LibraryElement library = member.library; |
| 2540 if (!backendUsage.isIsolateInUse && !(member.isField && member.isConst)) { |
| 2541 Uri uri = library.canonicalUri; |
| 2542 if (uri == Uris.dart_isolate) { |
| 2543 backendUsage.isIsolateInUse = true; |
| 2544 worldImpact.addImpact(enableIsolateSupport()); |
| 2545 } else if (uri == Uris.dart_async) { |
| 2546 if (member.name == '_createTimer' || |
| 2547 member.name == '_createPeriodicTimer') { |
| 2548 // The [:Timer:] class uses the event queue of the isolate |
| 2549 // library, so we make sure that event queue is generated. |
| 2550 backendUsage.isIsolateInUse = true; |
| 2551 worldImpact.addImpact(enableIsolateSupport()); |
| 2552 } |
| 2553 } |
| 2554 } |
| 2555 |
| 2556 if (member.isGetter && member.name == Identifiers.runtimeType_) { |
| 2557 // Enable runtime type support if we discover a getter called |
| 2558 // runtimeType. We have to enable runtime type before hitting the |
| 2559 // codegen, so that constructors know whether they need to generate code |
| 2560 // for runtime type. |
| 2561 backendUsage.isRuntimeTypeUsed = true; |
| 2562 // TODO(ahe): Record precise dependency here. |
| 2563 worldImpact.addImpact(registerRuntimeType()); |
| 2564 } |
| 2565 |
| 2566 return worldImpact; |
| 2567 } |
| 2568 |
| 2569 WorldImpact enableIsolateSupport() => |
| 2570 _backend.enableIsolateSupport(forResolution: true); |
| 2571 |
| 2572 /// Called to register that the `runtimeType` property has been accessed. Any |
| 2573 /// backend specific [WorldImpact] of this is returned. |
| 2574 WorldImpact registerRuntimeType() { |
| 2575 return backendUsage.createImpactFor(impacts.runtimeTypeSupport); |
| 2576 } |
| 2577 |
| 2578 WorldImpact registerClosureWithFreeTypeVariables(MethodElement closure) { |
| 2579 return _registerComputeSignature(); |
| 2580 } |
| 2581 |
| 2582 WorldImpact registerCallMethodWithFreeTypeVariables(Element callMethod, |
| 2583 {bool forResolution}) { |
| 2584 return _registerComputeSignature(); |
| 2585 } |
| 2586 |
| 2587 @override |
| 2588 WorldImpact registerImplementedClass(ClassEntity cls) { |
| 2589 return _processClass(cls, forResolution: true); |
| 2590 } |
| 2591 |
| 2592 @override |
| 2593 WorldImpact registerInstantiatedClass(ClassEntity cls) { |
| 2594 return _processClass(cls, forResolution: true); |
| 2595 } |
| 2596 |
| 2597 /// Compute the [WorldImpact] for backend helper methods. |
| 2598 WorldImpact computeHelpersImpact() { |
| 2599 assert(helpers.interceptorsLibrary != null); |
| 2600 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl(); |
| 2601 // TODO(ngeoffray): Not enqueuing those two classes currently make |
| 2602 // the compiler potentially crash. However, any reasonable program |
| 2603 // will instantiate those two classes. |
| 2604 addInterceptors(helpers.jsBoolClass, impactBuilder, forResolution: true); |
| 2605 addInterceptors(helpers.jsNullClass, impactBuilder, forResolution: true); |
| 2606 if (options.enableTypeAssertions) { |
| 2607 backendUsage.registerBackendImpact( |
| 2608 impactBuilder, impacts.enableTypeAssertions); |
| 2609 } |
| 2610 |
| 2611 if (JavaScriptBackend.TRACE_CALLS) { |
| 2612 backendUsage.registerBackendImpact(impactBuilder, impacts.traceHelper); |
| 2613 } |
| 2614 backendUsage.registerBackendImpact( |
| 2615 impactBuilder, impacts.assertUnreachable); |
| 2616 _registerCheckedModeHelpers(impactBuilder); |
| 2617 return impactBuilder; |
| 2618 } |
| 2619 |
| 2620 /// Called to register a `noSuchMethod` implementation. |
| 2621 void registerNoSuchMethod(MethodElement noSuchMethod) { |
| 2622 noSuchMethodRegistry.registerNoSuchMethod(noSuchMethod); |
| 2623 } |
| 2624 |
| 2625 void _registerCheckedModeHelpers(WorldImpactBuilder impactBuilder) { |
| 2626 // We register all the helpers in the resolution queue. |
| 2627 // TODO(13155): Find a way to register fewer helpers. |
| 2628 List<Element> staticUses = <Element>[]; |
| 2629 for (CheckedModeHelper helper in CheckedModeHelpers.helpers) { |
| 2630 staticUses.add(helper.getStaticUse(helpers).element); |
| 2631 } |
| 2632 backendUsage.registerBackendImpact( |
| 2633 impactBuilder, new BackendImpact(globalUses: staticUses)); |
| 2634 } |
| 2635 } |
| 2636 |
| 2637 class CodegenEnqueuerListener extends EnqueuerListenerBase { |
| 2638 CodegenEnqueuerListener(JavaScriptBackend backend) : super(backend); |
| 2639 |
| 2640 // TODO(johnniwinther): Change these to final fields. |
| 2641 LookupMapAnalysis get lookupMapAnalysis => _backend.lookupMapAnalysis; |
| 2642 DumpInfoTask get dumpInfoTask => _backend.compiler.dumpInfoTask; |
| 2643 |
| 2644 @override |
| 2645 void registerInstantiatedType(ResolutionInterfaceType type, |
| 2646 {bool isGlobal: false}) { |
| 2647 lookupMapAnalysis.registerInstantiatedType(type); |
| 2648 } |
| 2649 |
| 2650 @override |
| 2651 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses) { |
| 2652 // TODO(johnniwinther): Avoid the need for accessing [_backend]. |
| 2653 return _backend._onQueueEmpty(enqueuer, recentClasses); |
| 2654 } |
| 2655 |
| 2656 @override |
| 2657 WorldImpact registerUsedElement(MemberElement member) { |
| 2658 WorldImpactBuilderImpl worldImpact = new WorldImpactBuilderImpl(); |
| 2659 _registerUsedElement(worldImpact, member, forResolution: false); |
| 2660 |
| 2661 // TODO(sigmund): add other missing dependencies (internals, selectors |
| 2662 // enqueued after allocations). |
| 2663 dumpInfoTask.registerDependency(member); |
| 2664 |
| 2665 return worldImpact; |
| 2666 } |
| 2667 |
| 2668 WorldImpact registerClosureWithFreeTypeVariables(MethodElement closure) { |
| 2669 if (methodNeedsRti(closure)) { |
| 2670 return _registerComputeSignature(); |
| 2671 } |
| 2672 return const WorldImpact(); |
| 2673 } |
| 2674 |
| 2675 WorldImpact registerCallMethodWithFreeTypeVariables(Element callMethod) { |
| 2676 if (methodNeedsRti(callMethod)) { |
| 2677 return _registerComputeSignature(); |
| 2678 } |
| 2679 return const WorldImpact(); |
| 2680 } |
| 2681 |
| 2682 @override |
| 2683 WorldImpact registerImplementedClass(ClassEntity cls) { |
| 2684 WorldImpact worldImpact = _processClass(cls, forResolution: false); |
| 2685 lookupMapAnalysis.registerInstantiatedClass(cls); |
| 2686 return worldImpact; |
| 2687 } |
| 2688 |
| 2689 @override |
| 2690 WorldImpact registerInstantiatedClass(ClassEntity cls) { |
| 2691 WorldImpact worldImpact = _processClass(cls, forResolution: false); |
| 2692 lookupMapAnalysis.registerInstantiatedClass(cls); |
| 2693 return worldImpact; |
| 2694 } |
| 2695 |
| 2696 // TODO(johnniwinther): Avoid the need for accessing [_backend]. |
| 2697 bool methodNeedsRti(FunctionElement function) => |
| 2698 _backend.methodNeedsRti(function); |
| 2699 } |
| OLD | NEW |