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 Backend, ImpactTransformer, ForeignResolver, NativeRegistry; | 14 show Backend, 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, Selectors, Uris; | 16 import '../common/names.dart' show Identifiers, Selectors, Uris; |
17 import '../common/registry.dart' show EagerRegistry, Registry; | 17 import '../common/registry.dart' show EagerRegistry, Registry; |
18 import '../common/resolution.dart' | 18 import '../common/resolution.dart' show Frontend, Resolution, ResolutionImpact; |
19 show | |
20 Frontend, | |
21 Resolution, | |
22 ResolutionImpact; | |
23 import '../common/tasks.dart' show CompilerTask; | 19 import '../common/tasks.dart' show CompilerTask; |
24 import '../common/work.dart' show ItemCompilationContext; | 20 import '../common/work.dart' show ItemCompilationContext; |
25 import '../compiler.dart' show Compiler; | 21 import '../compiler.dart' show Compiler; |
26 import '../constants/constant_system.dart'; | 22 import '../constants/constant_system.dart'; |
27 import '../constants/expressions.dart'; | 23 import '../constants/expressions.dart'; |
28 import '../constants/values.dart'; | 24 import '../constants/values.dart'; |
29 import '../core_types.dart' show CoreClasses, CoreTypes; | 25 import '../core_types.dart' show CoreClasses, CoreTypes; |
30 import '../dart_types.dart'; | 26 import '../dart_types.dart'; |
31 import '../deferred_load.dart' show DeferredLoadTask; | 27 import '../deferred_load.dart' show DeferredLoadTask; |
32 import '../dump_info.dart' show DumpInfoTask; | 28 import '../dump_info.dart' show DumpInfoTask; |
(...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 | 511 |
516 /// True if there isn't sufficient @MirrorsUsed data. | 512 /// True if there isn't sufficient @MirrorsUsed data. |
517 bool hasInsufficientMirrorsUsed = false; | 513 bool hasInsufficientMirrorsUsed = false; |
518 | 514 |
519 /// True if a core-library function requires the preamble file to function. | 515 /// True if a core-library function requires the preamble file to function. |
520 bool requiresPreamble = false; | 516 bool requiresPreamble = false; |
521 | 517 |
522 /// True if the html library has been loaded. | 518 /// True if the html library has been loaded. |
523 bool htmlLibraryIsLoaded = false; | 519 bool htmlLibraryIsLoaded = false; |
524 | 520 |
| 521 /// True when we enqueue the loadLibrary code. |
| 522 bool isLoadLibraryFunctionResolved = false; |
| 523 |
525 /// List of constants from metadata. If metadata must be preserved, | 524 /// List of constants from metadata. If metadata must be preserved, |
526 /// these constants must be registered. | 525 /// these constants must be registered. |
527 final List<Dependency> metadataConstants = <Dependency>[]; | 526 final List<Dependency> metadataConstants = <Dependency>[]; |
528 | 527 |
529 /// Set of elements for which metadata has been registered as dependencies. | 528 /// Set of elements for which metadata has been registered as dependencies. |
530 final Set<Element> _registeredMetadata = new Set<Element>(); | 529 final Set<Element> _registeredMetadata = new Set<Element>(); |
531 | 530 |
532 /// List of elements that the user has requested for reflection. | 531 /// List of elements that the user has requested for reflection. |
533 final Set<Element> targetsUsed = new Set<Element>(); | 532 final Set<Element> targetsUsed = new Set<Element>(); |
534 | 533 |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 // Both declaration and implementation may declare fields, so we | 693 // Both declaration and implementation may declare fields, so we |
695 // add both to the list of helpers. | 694 // add both to the list of helpers. |
696 helpersUsed.add(element.implementation); | 695 helpersUsed.add(element.implementation); |
697 } | 696 } |
698 return element; | 697 return element; |
699 } | 698 } |
700 | 699 |
701 bool _isValidBackendUse(Element element) { | 700 bool _isValidBackendUse(Element element) { |
702 assert(invariant(element, element.isDeclaration, message: "")); | 701 assert(invariant(element, element.isDeclaration, message: "")); |
703 if (element == helpers.streamIteratorConstructor || | 702 if (element == helpers.streamIteratorConstructor || |
704 element == helpers.compiler.symbolConstructor || | 703 compiler.commonElements.isSymbolConstructor(element) || |
705 helpers.isSymbolValidatedConstructor(element) || | 704 helpers.isSymbolValidatedConstructor(element) || |
706 element == helpers.syncCompleterConstructor || | 705 element == helpers.syncCompleterConstructor || |
707 element == coreClasses.symbolClass || | 706 element == coreClasses.symbolClass || |
708 element == helpers.objectNoSuchMethod) { | 707 element == helpers.objectNoSuchMethod) { |
709 // TODO(johnniwinther): These are valid but we could be more precise. | 708 // TODO(johnniwinther): These are valid but we could be more precise. |
710 return true; | 709 return true; |
711 } else if (element.implementationLibrary.isPatch || | 710 } else if (element.implementationLibrary.isPatch || |
712 // Needed to detect deserialized injected elements, that is | 711 // Needed to detect deserialized injected elements, that is |
713 // element declared in patch files. | 712 // element declared in patch files. |
714 (element.library.isPlatformLibrary && | 713 (element.library.isPlatformLibrary && |
(...skipping 963 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1678 'count': mirrorCount, | 1677 'count': mirrorCount, |
1679 'total': totalMethodCount, | 1678 'total': totalMethodCount, |
1680 'percentage': percentage.round() | 1679 'percentage': percentage.round() |
1681 }); | 1680 }); |
1682 | 1681 |
1683 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 1682 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; |
1684 for (LibraryElement library in compiler.libraryLoader.libraries) { | 1683 for (LibraryElement library in compiler.libraryLoader.libraries) { |
1685 if (library.isInternalLibrary) continue; | 1684 if (library.isInternalLibrary) continue; |
1686 for (ImportElement import in library.imports) { | 1685 for (ImportElement import in library.imports) { |
1687 LibraryElement importedLibrary = import.importedLibrary; | 1686 LibraryElement importedLibrary = import.importedLibrary; |
1688 if (importedLibrary != compiler.mirrorsLibrary) continue; | 1687 if (importedLibrary != compiler.commonElements.mirrorsLibrary) |
| 1688 continue; |
1689 MessageKind kind = | 1689 MessageKind kind = |
1690 compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(library) | 1690 compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(library) |
1691 ? MessageKind.MIRROR_IMPORT | 1691 ? MessageKind.MIRROR_IMPORT |
1692 : MessageKind.MIRROR_IMPORT_NO_USAGE; | 1692 : MessageKind.MIRROR_IMPORT_NO_USAGE; |
1693 reporter.withCurrentElement(library, () { | 1693 reporter.withCurrentElement(library, () { |
1694 infos.add(reporter.createMessage(import, kind)); | 1694 infos.add(reporter.createMessage(import, kind)); |
1695 }); | 1695 }); |
1696 } | 1696 } |
1697 } | 1697 } |
1698 reporter.reportHint(hint, infos); | 1698 reporter.reportHint(hint, infos); |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1910 } else if (element == helpers.preserveMetadataMarker) { | 1910 } else if (element == helpers.preserveMetadataMarker) { |
1911 mustRetainMetadata = true; | 1911 mustRetainMetadata = true; |
1912 } else if (element == helpers.preserveUrisMarker) { | 1912 } else if (element == helpers.preserveUrisMarker) { |
1913 if (compiler.options.preserveUris) mustPreserveUris = true; | 1913 if (compiler.options.preserveUris) mustPreserveUris = true; |
1914 } else if (element == helpers.preserveLibraryNamesMarker) { | 1914 } else if (element == helpers.preserveLibraryNamesMarker) { |
1915 mustRetainLibraryNames = true; | 1915 mustRetainLibraryNames = true; |
1916 } else if (element == helpers.getIsolateAffinityTagMarker) { | 1916 } else if (element == helpers.getIsolateAffinityTagMarker) { |
1917 needToInitializeIsolateAffinityTag = true; | 1917 needToInitializeIsolateAffinityTag = true; |
1918 } else if (element.isDeferredLoaderGetter) { | 1918 } else if (element.isDeferredLoaderGetter) { |
1919 // TODO(sigurdm): Create a function registerLoadLibraryAccess. | 1919 // TODO(sigurdm): Create a function registerLoadLibraryAccess. |
1920 if (compiler.loadLibraryFunction == null) { | 1920 if (!isLoadLibraryFunctionResolved) { |
1921 compiler.loadLibraryFunction = helpers.loadLibraryWrapper; | 1921 isLoadLibraryFunctionResolved = true; |
1922 enqueueInResolution( | 1922 enqueueInResolution( |
1923 compiler.loadLibraryFunction, compiler.globalDependencies); | 1923 helpers.loadLibraryWrapper, compiler.globalDependencies); |
1924 } | 1924 } |
1925 } else if (element == helpers.requiresPreambleMarker) { | 1925 } else if (element == helpers.requiresPreambleMarker) { |
1926 requiresPreamble = true; | 1926 requiresPreamble = true; |
1927 } | 1927 } |
1928 customElementsAnalysis.registerStaticUse(element, enqueuer); | 1928 customElementsAnalysis.registerStaticUse(element, enqueuer); |
1929 } | 1929 } |
1930 | 1930 |
1931 /// Called when [:const Symbol(name):] is seen. | 1931 /// Called when [:const Symbol(name):] is seen. |
1932 void registerConstSymbol(String name) { | 1932 void registerConstSymbol(String name) { |
1933 symbolsUsed.add(name); | 1933 symbolsUsed.add(name); |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2125 * We have to precompute this set as we cannot easily answer the need for | 2125 * We have to precompute this set as we cannot easily answer the need for |
2126 * reflection locally when looking at the member: We lack the information by | 2126 * reflection locally when looking at the member: We lack the information by |
2127 * which classes a member is inherited. Called after resolution is complete. | 2127 * which classes a member is inherited. Called after resolution is complete. |
2128 * | 2128 * |
2129 * We filter out private libraries here, as their elements should not | 2129 * We filter out private libraries here, as their elements should not |
2130 * be visible by reflection unless some other interfaces makes them | 2130 * be visible by reflection unless some other interfaces makes them |
2131 * accessible. | 2131 * accessible. |
2132 */ | 2132 */ |
2133 computeMembersNeededForReflection() { | 2133 computeMembersNeededForReflection() { |
2134 if (_membersNeededForReflection != null) return; | 2134 if (_membersNeededForReflection != null) return; |
2135 if (compiler.mirrorsLibrary == null) { | 2135 if (compiler.commonElements.mirrorsLibrary == null) { |
2136 _membersNeededForReflection = const ImmutableEmptySet<Element>(); | 2136 _membersNeededForReflection = const ImmutableEmptySet<Element>(); |
2137 return; | 2137 return; |
2138 } | 2138 } |
2139 // Compute a mapping from class to the closures it contains, so we | 2139 // Compute a mapping from class to the closures it contains, so we |
2140 // can include the correct ones when including the class. | 2140 // can include the correct ones when including the class. |
2141 Map<ClassElement, List<LocalFunctionElement>> closureMap = | 2141 Map<ClassElement, List<LocalFunctionElement>> closureMap = |
2142 new Map<ClassElement, List<LocalFunctionElement>>(); | 2142 new Map<ClassElement, List<LocalFunctionElement>>(); |
2143 for (LocalFunctionElement closure in compiler.resolverWorld.allClosures) { | 2143 for (LocalFunctionElement closure in compiler.resolverWorld.allClosures) { |
2144 closureMap.putIfAbsent(closure.enclosingClass, () => []).add(closure); | 2144 closureMap.putIfAbsent(closure.enclosingClass, () => []).add(closure); |
2145 } | 2145 } |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2283 List<jsAst.Expression> arguments = <jsAst.Expression>[use1, record]; | 2283 List<jsAst.Expression> arguments = <jsAst.Expression>[use1, record]; |
2284 FunctionElement helper = helpers.isJsIndexable; | 2284 FunctionElement helper = helpers.isJsIndexable; |
2285 jsAst.Expression helperExpression = emitter.staticFunctionAccess(helper); | 2285 jsAst.Expression helperExpression = emitter.staticFunctionAccess(helper); |
2286 return new jsAst.Call(helperExpression, arguments); | 2286 return new jsAst.Call(helperExpression, arguments); |
2287 } | 2287 } |
2288 | 2288 |
2289 bool isTypedArray(TypeMask mask) { | 2289 bool isTypedArray(TypeMask mask) { |
2290 // Just checking for [:TypedData:] is not sufficient, as it is an | 2290 // Just checking for [:TypedData:] is not sufficient, as it is an |
2291 // abstract class any user-defined class can implement. So we also | 2291 // abstract class any user-defined class can implement. So we also |
2292 // check for the interface [JavaScriptIndexingBehavior]. | 2292 // check for the interface [JavaScriptIndexingBehavior]. |
2293 return compiler.typedDataClass != null && | 2293 ClassElement typedDataClass = compiler.commonElements.typedDataClass; |
2294 compiler.world.isInstantiated(compiler.typedDataClass) && | 2294 return typedDataClass != null && |
2295 mask.satisfies(compiler.typedDataClass, compiler.world) && | 2295 compiler.world.isInstantiated(typedDataClass) && |
| 2296 mask.satisfies(typedDataClass, compiler.world) && |
2296 mask.satisfies(helpers.jsIndexingBehaviorInterface, compiler.world); | 2297 mask.satisfies(helpers.jsIndexingBehaviorInterface, compiler.world); |
2297 } | 2298 } |
2298 | 2299 |
2299 bool couldBeTypedArray(TypeMask mask) { | 2300 bool couldBeTypedArray(TypeMask mask) { |
2300 bool intersects(TypeMask type1, TypeMask type2) => | 2301 bool intersects(TypeMask type1, TypeMask type2) => |
2301 !type1.intersection(type2, compiler.world).isEmpty; | 2302 !type1.intersection(type2, compiler.world).isEmpty; |
2302 // TODO(herhut): Maybe cache the TypeMask for typedDataClass and | 2303 // TODO(herhut): Maybe cache the TypeMask for typedDataClass and |
2303 // jsIndexingBehaviourInterface. | 2304 // jsIndexingBehaviourInterface. |
2304 return compiler.typedDataClass != null && | 2305 ClassElement typedDataClass = compiler.commonElements.typedDataClass; |
2305 compiler.world.isInstantiated(compiler.typedDataClass) && | 2306 return typedDataClass != null && |
2306 intersects(mask, | 2307 compiler.world.isInstantiated(typedDataClass) && |
2307 new TypeMask.subtype(compiler.typedDataClass, compiler.world)) && | 2308 intersects( |
| 2309 mask, new TypeMask.subtype(typedDataClass, compiler.world)) && |
2308 intersects( | 2310 intersects( |
2309 mask, | 2311 mask, |
2310 new TypeMask.subtype( | 2312 new TypeMask.subtype( |
2311 helpers.jsIndexingBehaviorInterface, compiler.world)); | 2313 helpers.jsIndexingBehaviorInterface, compiler.world)); |
2312 } | 2314 } |
2313 | 2315 |
2314 /// Returns all static fields that are referenced through [targetsUsed]. | 2316 /// Returns all static fields that are referenced through [targetsUsed]. |
2315 /// If the target is a library or class all nested static fields are | 2317 /// If the target is a library or class all nested static fields are |
2316 /// included too. | 2318 /// included too. |
2317 Iterable<Element> _findStaticFieldTargets() { | 2319 Iterable<Element> _findStaticFieldTargets() { |
(...skipping 876 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3194 | 3196 |
3195 @override | 3197 @override |
3196 void onImpactUsed(ImpactUseCase impactUse) { | 3198 void onImpactUsed(ImpactUseCase impactUse) { |
3197 if (impactUse == DeferredLoadTask.IMPACT_USE && !supportSerialization) { | 3199 if (impactUse == DeferredLoadTask.IMPACT_USE && !supportSerialization) { |
3198 // TODO(johnniwinther): Allow emptying when serialization has been | 3200 // TODO(johnniwinther): Allow emptying when serialization has been |
3199 // performed. | 3201 // performed. |
3200 resolution.emptyCache(); | 3202 resolution.emptyCache(); |
3201 } | 3203 } |
3202 } | 3204 } |
3203 } | 3205 } |
OLD | NEW |