| 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 |