| 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 11 matching lines...) Expand all Loading... |
| 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, ElementEnvironment; | 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 |
| 33 Enqueuer, |
| 34 EnqueuerListener, |
| 35 EnqueueTask, |
| 36 ResolutionEnqueuer, |
| 37 TreeShakingEnqueuerStrategy; |
| 33 import '../io/position_information.dart' show PositionSourceInformationStrategy; | 38 import '../io/position_information.dart' show PositionSourceInformationStrategy; |
| 34 import '../io/source_information.dart' show SourceInformationStrategy; | 39 import '../io/source_information.dart' show SourceInformationStrategy; |
| 35 import '../io/start_end_information.dart' | 40 import '../io/start_end_information.dart' |
| 36 show StartEndSourceInformationStrategy; | 41 show StartEndSourceInformationStrategy; |
| 37 import '../js/js.dart' as jsAst; | 42 import '../js/js.dart' as jsAst; |
| 38 import '../js/js.dart' show js; | 43 import '../js/js.dart' show js; |
| 39 import '../js/js_source_mapping.dart' show JavaScriptSourceInformationStrategy; | 44 import '../js/js_source_mapping.dart' show JavaScriptSourceInformationStrategy; |
| 40 import '../js/rewrite_async.dart'; | 45 import '../js/rewrite_async.dart'; |
| 41 import '../js_emitter/js_emitter.dart' show CodeEmitterTask; | 46 import '../js_emitter/js_emitter.dart' show CodeEmitterTask; |
| 42 import '../kernel/task.dart'; | 47 import '../kernel/task.dart'; |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 } | 302 } |
| 298 } | 303 } |
| 299 | 304 |
| 300 enum SyntheticConstantKind { | 305 enum SyntheticConstantKind { |
| 301 DUMMY_INTERCEPTOR, | 306 DUMMY_INTERCEPTOR, |
| 302 EMPTY_VALUE, | 307 EMPTY_VALUE, |
| 303 TYPEVARIABLE_REFERENCE, // Reference to a type in reflection data. | 308 TYPEVARIABLE_REFERENCE, // Reference to a type in reflection data. |
| 304 NAME | 309 NAME |
| 305 } | 310 } |
| 306 | 311 |
| 307 class JavaScriptBackend extends Target { | 312 class JavaScriptBackend extends Target implements EnqueuerListener { |
| 308 final Compiler compiler; | 313 final Compiler compiler; |
| 309 | 314 |
| 310 String get patchVersion => emitter.patchVersion; | 315 String get patchVersion => emitter.patchVersion; |
| 311 | 316 |
| 312 /// Returns true if the backend supports reflection. | 317 /// Returns true if the backend supports reflection. |
| 313 bool get supportsReflection => emitter.supportsReflection; | 318 bool get supportsReflection => emitter.supportsReflection; |
| 314 | 319 |
| 315 final Annotations annotations; | 320 final Annotations annotations; |
| 316 | 321 |
| 317 /// Set of classes that need to be considered for reflection although not | 322 /// Set of classes that need to be considered for reflection although not |
| (...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 787 // constant emitter will generate a call to the createRuntimeType | 792 // constant emitter will generate a call to the createRuntimeType |
| 788 // helper so we register a use of that. | 793 // helper so we register a use of that. |
| 789 impactBuilder.registerStaticUse(new StaticUse.staticInvoke( | 794 impactBuilder.registerStaticUse(new StaticUse.staticInvoke( |
| 790 // TODO(johnniwinther): Find the right [CallStructure]. | 795 // TODO(johnniwinther): Find the right [CallStructure]. |
| 791 helpers.createRuntimeType, | 796 helpers.createRuntimeType, |
| 792 null)); | 797 null)); |
| 793 } | 798 } |
| 794 } | 799 } |
| 795 } | 800 } |
| 796 | 801 |
| 797 /// Called to notify to the backend that a class is being instantiated. Any | |
| 798 /// backend specific [WorldImpact] of this is returned. | |
| 799 WorldImpact registerInstantiatedClass(ClassElement cls, | 802 WorldImpact registerInstantiatedClass(ClassElement cls, |
| 800 {bool forResolution}) { | 803 {bool forResolution}) { |
| 801 return _processClass(cls, forResolution: forResolution); | 804 return _processClass(cls, forResolution: forResolution); |
| 802 } | 805 } |
| 803 | 806 |
| 804 /// Called to notify to the backend that a class is implemented by an | |
| 805 /// instantiated class. Any backend specific [WorldImpact] of this is | |
| 806 /// returned. | |
| 807 WorldImpact registerImplementedClass(ClassElement cls, {bool forResolution}) { | 807 WorldImpact registerImplementedClass(ClassElement cls, {bool forResolution}) { |
| 808 return _processClass(cls, forResolution: forResolution); | 808 return _processClass(cls, forResolution: forResolution); |
| 809 } | 809 } |
| 810 | 810 |
| 811 WorldImpact _processClass(ClassElement cls, {bool forResolution}) { | 811 WorldImpact _processClass(ClassElement cls, {bool forResolution}) { |
| 812 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl(); | 812 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl(); |
| 813 if (!cls.typeVariables.isEmpty) { | 813 if (!cls.typeVariables.isEmpty) { |
| 814 typeVariableHandler.registerClassWithTypeVariables(cls, | 814 typeVariableHandler.registerClassWithTypeVariables(cls, |
| 815 forResolution: forResolution); | 815 forResolution: forResolution); |
| 816 } | 816 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 929 | 929 |
| 930 customElementsAnalysis.registerInstantiatedClass(cls, | 930 customElementsAnalysis.registerInstantiatedClass(cls, |
| 931 forResolution: forResolution); | 931 forResolution: forResolution); |
| 932 if (!forResolution) { | 932 if (!forResolution) { |
| 933 lookupMapAnalysis.registerInstantiatedClass(cls); | 933 lookupMapAnalysis.registerInstantiatedClass(cls); |
| 934 } | 934 } |
| 935 | 935 |
| 936 return impactBuilder; | 936 return impactBuilder; |
| 937 } | 937 } |
| 938 | 938 |
| 939 /// Called to instruct to the backend register [type] as instantiated on | |
| 940 /// [enqueuer]. | |
| 941 void registerInstantiatedType(ResolutionInterfaceType type) { | 939 void registerInstantiatedType(ResolutionInterfaceType type) { |
| 942 lookupMapAnalysis.registerInstantiatedType(type); | 940 lookupMapAnalysis.registerInstantiatedType(type); |
| 943 } | 941 } |
| 944 | 942 |
| 945 /// Compute the [WorldImpact] for backend helper methods. | 943 /// Compute the [WorldImpact] for backend helper methods. |
| 946 WorldImpact computeHelpersImpact() { | 944 WorldImpact computeHelpersImpact() { |
| 947 assert(helpers.interceptorsLibrary != null); | 945 assert(helpers.interceptorsLibrary != null); |
| 948 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl(); | 946 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl(); |
| 949 // TODO(ngeoffray): Not enqueuing those two classes currently make | 947 // TODO(ngeoffray): Not enqueuing those two classes currently make |
| 950 // the compiler potentially crash. However, any reasonable program | 948 // the compiler potentially crash. However, any reasonable program |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 988 /// Note: The [callMethod] is registered even thought it doesn't reference | 986 /// Note: The [callMethod] is registered even thought it doesn't reference |
| 989 /// the type variables. | 987 /// the type variables. |
| 990 WorldImpact registerCallMethodWithFreeTypeVariables(Element callMethod, | 988 WorldImpact registerCallMethodWithFreeTypeVariables(Element callMethod, |
| 991 {bool forResolution}) { | 989 {bool forResolution}) { |
| 992 if (forResolution || methodNeedsRti(callMethod)) { | 990 if (forResolution || methodNeedsRti(callMethod)) { |
| 993 return _registerComputeSignature(); | 991 return _registerComputeSignature(); |
| 994 } | 992 } |
| 995 return const WorldImpact(); | 993 return const WorldImpact(); |
| 996 } | 994 } |
| 997 | 995 |
| 998 /// Called to instruct the backend to register that a closure exists for a | 996 WorldImpact registerClosureWithFreeTypeVariables(MethodElement closure, |
| 999 /// function on an instantiated generic class. Any backend specific | |
| 1000 /// [WorldImpact] of this is returned. | |
| 1001 WorldImpact registerClosureWithFreeTypeVariables(Element closure, | |
| 1002 {bool forResolution}) { | 997 {bool forResolution}) { |
| 1003 if (forResolution || methodNeedsRti(closure)) { | 998 if (forResolution || methodNeedsRti(closure)) { |
| 1004 return _registerComputeSignature(); | 999 return _registerComputeSignature(); |
| 1005 } | 1000 } |
| 1006 return const WorldImpact(); | 1001 return const WorldImpact(); |
| 1007 } | 1002 } |
| 1008 | 1003 |
| 1009 /// Called to register that a member has been closurized. Any backend specific | |
| 1010 /// [WorldImpact] of this is returned. | |
| 1011 WorldImpact registerBoundClosure() { | 1004 WorldImpact registerBoundClosure() { |
| 1012 return impactTransformer.createImpactFor(impacts.memberClosure); | 1005 return impactTransformer.createImpactFor(impacts.memberClosure); |
| 1013 } | 1006 } |
| 1014 | 1007 |
| 1015 /// Called to register that a static function has been closurized. Any backend | |
| 1016 /// specific [WorldImpact] of this is returned. | |
| 1017 WorldImpact registerGetOfStaticFunction() { | 1008 WorldImpact registerGetOfStaticFunction() { |
| 1018 return impactTransformer.createImpactFor(impacts.staticClosure); | 1009 return impactTransformer.createImpactFor(impacts.staticClosure); |
| 1019 } | 1010 } |
| 1020 | 1011 |
| 1021 WorldImpact _registerComputeSignature() { | 1012 WorldImpact _registerComputeSignature() { |
| 1022 return impactTransformer.createImpactFor(impacts.computeSignature); | 1013 return impactTransformer.createImpactFor(impacts.computeSignature); |
| 1023 } | 1014 } |
| 1024 | 1015 |
| 1025 /// Called to register that the `runtimeType` property has been accessed. Any | 1016 /// Called to register that the `runtimeType` property has been accessed. Any |
| 1026 /// backend specific [WorldImpact] of this is returned. | 1017 /// backend specific [WorldImpact] of this is returned. |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1311 bool mayGenerateInstanceofCheck(ResolutionDartType type) { | 1302 bool mayGenerateInstanceofCheck(ResolutionDartType type) { |
| 1312 // We can use an instanceof check for raw types that have no subclass that | 1303 // We can use an instanceof check for raw types that have no subclass that |
| 1313 // is mixed-in or in an implements clause. | 1304 // is mixed-in or in an implements clause. |
| 1314 | 1305 |
| 1315 if (!type.isRaw) return false; | 1306 if (!type.isRaw) return false; |
| 1316 ClassElement classElement = type.element; | 1307 ClassElement classElement = type.element; |
| 1317 if (interceptorData.isInterceptorClass(classElement)) return false; | 1308 if (interceptorData.isInterceptorClass(classElement)) return false; |
| 1318 return _closedWorld.hasOnlySubclasses(classElement); | 1309 return _closedWorld.hasOnlySubclasses(classElement); |
| 1319 } | 1310 } |
| 1320 | 1311 |
| 1321 /// Called to register that [element] is statically known to be used. Any | |
| 1322 /// backend specific [WorldImpact] of this is returned. | |
| 1323 WorldImpact registerUsedElement(MemberElement element, {bool forResolution}) { | 1312 WorldImpact registerUsedElement(MemberElement element, {bool forResolution}) { |
| 1324 WorldImpactBuilderImpl worldImpact = new WorldImpactBuilderImpl(); | 1313 WorldImpactBuilderImpl worldImpact = new WorldImpactBuilderImpl(); |
| 1325 if (element == helpers.disableTreeShakingMarker) { | 1314 if (element == helpers.disableTreeShakingMarker) { |
| 1326 mirrorsData.isTreeShakingDisabled = true; | 1315 mirrorsData.isTreeShakingDisabled = true; |
| 1327 } else if (element == helpers.preserveNamesMarker) { | 1316 } else if (element == helpers.preserveNamesMarker) { |
| 1328 mirrorsData.mustPreserveNames = true; | 1317 mirrorsData.mustPreserveNames = true; |
| 1329 } else if (element == helpers.preserveMetadataMarker) { | 1318 } else if (element == helpers.preserveMetadataMarker) { |
| 1330 mirrorsData.mustRetainMetadata = true; | 1319 mirrorsData.mustRetainMetadata = true; |
| 1331 } else if (element == helpers.preserveUrisMarker) { | 1320 } else if (element == helpers.preserveUrisMarker) { |
| 1332 if (compiler.options.preserveUris) mustPreserveUris = true; | 1321 if (compiler.options.preserveUris) mustPreserveUris = true; |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1519 if (target == null) continue; | 1508 if (target == null) continue; |
| 1520 if (target.isField) { | 1509 if (target.isField) { |
| 1521 staticFields.add(target); | 1510 staticFields.add(target); |
| 1522 } else if (target.isLibrary || target.isClass) { | 1511 } else if (target.isLibrary || target.isClass) { |
| 1523 addFieldsInContainer(target); | 1512 addFieldsInContainer(target); |
| 1524 } | 1513 } |
| 1525 } | 1514 } |
| 1526 return staticFields; | 1515 return staticFields; |
| 1527 } | 1516 } |
| 1528 | 1517 |
| 1529 /// Called when [enqueuer]'s queue is empty, but before it is closed. | |
| 1530 /// | |
| 1531 /// This is used, for example, by the JS backend to enqueue additional | |
| 1532 /// elements needed for reflection. [recentClasses] is a collection of | |
| 1533 /// all classes seen for the first time by the [enqueuer] since the last call | |
| 1534 /// to [onQueueEmpty]. | |
| 1535 /// | |
| 1536 /// A return value of [:true:] indicates that [recentClasses] has been | |
| 1537 /// processed and its elements do not need to be seen in the next round. When | |
| 1538 /// [:false:] is returned, [onQueueEmpty] will be called again once the | |
| 1539 /// resolution queue has drained and [recentClasses] will be a superset of the | |
| 1540 /// current value. | |
| 1541 /// | |
| 1542 /// There is no guarantee that a class is only present once in | |
| 1543 /// [recentClasses], but every class seen by the [enqueuer] will be present in | |
| 1544 /// [recentClasses] at least once. | |
| 1545 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses) { | 1518 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses) { |
| 1546 // Add elements used synthetically, that is, through features rather than | 1519 // Add elements used synthetically, that is, through features rather than |
| 1547 // syntax, for instance custom elements. | 1520 // syntax, for instance custom elements. |
| 1548 // | 1521 // |
| 1549 // Return early if any elements are added to avoid counting the elements as | 1522 // Return early if any elements are added to avoid counting the elements as |
| 1550 // due to mirrors. | 1523 // due to mirrors. |
| 1551 enqueuer.applyImpact(customElementsAnalysis.flush( | 1524 enqueuer.applyImpact(customElementsAnalysis.flush( |
| 1552 forResolution: enqueuer.isResolutionQueue)); | 1525 forResolution: enqueuer.isResolutionQueue)); |
| 1553 enqueuer.applyImpact( | 1526 enqueuer.applyImpact( |
| 1554 lookupMapAnalysis.flush(forResolution: enqueuer.isResolutionQueue)); | 1527 lookupMapAnalysis.flush(forResolution: enqueuer.isResolutionQueue)); |
| (...skipping 1080 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2635 } | 2608 } |
| 2636 | 2609 |
| 2637 @override | 2610 @override |
| 2638 FieldEntity get symbolField => helpers.symbolImplementationField; | 2611 FieldEntity get symbolField => helpers.symbolImplementationField; |
| 2639 | 2612 |
| 2640 @override | 2613 @override |
| 2641 InterfaceType get symbolType { | 2614 InterfaceType get symbolType { |
| 2642 return _env.getRawType(helpers.symbolImplementationClass); | 2615 return _env.getRawType(helpers.symbolImplementationClass); |
| 2643 } | 2616 } |
| 2644 } | 2617 } |
| OLD | NEW |