| 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 27 matching lines...) Expand all Loading... |
| 38 import '../io/start_end_information.dart' | 38 import '../io/start_end_information.dart' |
| 39 show StartEndSourceInformationStrategy; | 39 show StartEndSourceInformationStrategy; |
| 40 import '../js/js.dart' as jsAst; | 40 import '../js/js.dart' as jsAst; |
| 41 import '../js/js.dart' show js; | 41 import '../js/js.dart' show js; |
| 42 import '../js/js_source_mapping.dart' show JavaScriptSourceInformationStrategy; | 42 import '../js/js_source_mapping.dart' show JavaScriptSourceInformationStrategy; |
| 43 import '../js/rewrite_async.dart'; | 43 import '../js/rewrite_async.dart'; |
| 44 import '../js_emitter/js_emitter.dart' show CodeEmitterTask; | 44 import '../js_emitter/js_emitter.dart' show CodeEmitterTask; |
| 45 import '../library_loader.dart' show LibraryLoader, LoadedLibraries; | 45 import '../library_loader.dart' show LibraryLoader, LoadedLibraries; |
| 46 import '../native/native.dart' as native; | 46 import '../native/native.dart' as native; |
| 47 import '../ssa/ssa.dart' show SsaFunctionCompiler; | 47 import '../ssa/ssa.dart' show SsaFunctionCompiler; |
| 48 import '../tracer.dart'; |
| 48 import '../tree/tree.dart'; | 49 import '../tree/tree.dart'; |
| 49 import '../types/types.dart'; | 50 import '../types/types.dart'; |
| 50 import '../universe/call_structure.dart' show CallStructure; | 51 import '../universe/call_structure.dart' show CallStructure; |
| 51 import '../universe/feature.dart'; | 52 import '../universe/feature.dart'; |
| 52 import '../universe/selector.dart' show Selector; | 53 import '../universe/selector.dart' show Selector; |
| 53 import '../universe/world_builder.dart'; | 54 import '../universe/world_builder.dart'; |
| 54 import '../universe/use.dart' | 55 import '../universe/use.dart' |
| 55 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; | 56 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; |
| 56 import '../universe/world_impact.dart' | 57 import '../universe/world_impact.dart' |
| 57 show | 58 show |
| (...skipping 23 matching lines...) Expand all Loading... |
| 81 import 'no_such_method_registry.dart'; | 82 import 'no_such_method_registry.dart'; |
| 82 import 'patch_resolver.dart'; | 83 import 'patch_resolver.dart'; |
| 83 import 'type_variable_handler.dart'; | 84 import 'type_variable_handler.dart'; |
| 84 | 85 |
| 85 part 'runtime_types.dart'; | 86 part 'runtime_types.dart'; |
| 86 | 87 |
| 87 const VERBOSE_OPTIMIZER_HINTS = false; | 88 const VERBOSE_OPTIMIZER_HINTS = false; |
| 88 | 89 |
| 89 abstract class FunctionCompiler { | 90 abstract class FunctionCompiler { |
| 90 /// Generates JavaScript code for `work.element`. | 91 /// Generates JavaScript code for `work.element`. |
| 91 jsAst.Fun compile(CodegenWorkItem work); | 92 jsAst.Fun compile(CodegenWorkItem work, ClosedWorld closedWorld); |
| 92 | 93 |
| 93 Iterable get tasks; | 94 Iterable get tasks; |
| 94 } | 95 } |
| 95 | 96 |
| 96 /* | 97 /* |
| 97 * Invariants: | 98 * Invariants: |
| 98 * canInline(function) implies canInline(function, insideLoop:true) | 99 * canInline(function) implies canInline(function, insideLoop:true) |
| 99 * !canInline(function, insideLoop: true) implies !canInline(function) | 100 * !canInline(function, insideLoop: true) implies !canInline(function) |
| 100 */ | 101 */ |
| 101 class FunctionInlineCache { | 102 class FunctionInlineCache { |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 552 new StagedWorldImpactBuilder(); | 553 new StagedWorldImpactBuilder(); |
| 553 | 554 |
| 554 final NativeData nativeData = new NativeData(); | 555 final NativeData nativeData = new NativeData(); |
| 555 | 556 |
| 556 final BackendHelpers helpers; | 557 final BackendHelpers helpers; |
| 557 final BackendImpacts impacts; | 558 final BackendImpacts impacts; |
| 558 BackendClasses backendClasses; | 559 BackendClasses backendClasses; |
| 559 | 560 |
| 560 final JSFrontendAccess frontend; | 561 final JSFrontendAccess frontend; |
| 561 | 562 |
| 563 Tracer tracer; |
| 564 |
| 562 JavaScriptBackend(Compiler compiler, | 565 JavaScriptBackend(Compiler compiler, |
| 563 {bool generateSourceMap: true, | 566 {bool generateSourceMap: true, |
| 564 bool useStartupEmitter: false, | 567 bool useStartupEmitter: false, |
| 565 bool useNewSourceInfo: false, | 568 bool useNewSourceInfo: false, |
| 566 bool useKernel: false}) | 569 bool useKernel: false}) |
| 567 : oneShotInterceptors = new Map<jsAst.Name, Selector>(), | 570 : oneShotInterceptors = new Map<jsAst.Name, Selector>(), |
| 568 interceptedElements = new Map<String, Set<Element>>(), | 571 interceptedElements = new Map<String, Set<Element>>(), |
| 569 rti = new _RuntimeTypes(compiler), | 572 rti = new _RuntimeTypes(compiler), |
| 570 rtiEncoder = new _RuntimeTypesEncoder(compiler), | 573 rtiEncoder = new _RuntimeTypesEncoder(compiler), |
| 571 specializedGetInterceptors = new Map<jsAst.Name, Set<ClassElement>>(), | 574 specializedGetInterceptors = new Map<jsAst.Name, Set<ClassElement>>(), |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 891 return elements | 894 return elements |
| 892 .where((element) => classesMixedIntoInterceptedClasses | 895 .where((element) => classesMixedIntoInterceptedClasses |
| 893 .contains(element.enclosingClass)) | 896 .contains(element.enclosingClass)) |
| 894 .toSet(); | 897 .toSet(); |
| 895 }); | 898 }); |
| 896 | 899 |
| 897 if (elements == null) return false; | 900 if (elements == null) return false; |
| 898 if (elements.isEmpty) return false; | 901 if (elements.isEmpty) return false; |
| 899 return elements.any((element) { | 902 return elements.any((element) { |
| 900 return selector.applies(element) && | 903 return selector.applies(element) && |
| 901 (mask == null || | 904 (mask == null || mask.canHit(element, selector, _closedWorld)); |
| 902 mask.canHit(element, selector, compiler.closedWorld)); | |
| 903 }); | 905 }); |
| 904 } | 906 } |
| 905 | 907 |
| 906 /// True if the given class is an internal class used for type inference | 908 /// True if the given class is an internal class used for type inference |
| 907 /// and never exists at runtime. | 909 /// and never exists at runtime. |
| 908 bool isCompileTimeOnlyClass(ClassElement class_) { | 910 bool isCompileTimeOnlyClass(ClassElement class_) { |
| 909 return class_ == helpers.jsPositiveIntClass || | 911 return class_ == helpers.jsPositiveIntClass || |
| 910 class_ == helpers.jsUInt32Class || | 912 class_ == helpers.jsUInt32Class || |
| 911 class_ == helpers.jsUInt31Class || | 913 class_ == helpers.jsUInt31Class || |
| 912 class_ == helpers.jsFixedArrayClass || | 914 class_ == helpers.jsFixedArrayClass || |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 948 Set<ClassElement> nativeSubclasses = | 950 Set<ClassElement> nativeSubclasses = |
| 949 nativeSubclassesOfMixin(classElement); | 951 nativeSubclassesOfMixin(classElement); |
| 950 if (nativeSubclasses != null) result.addAll(nativeSubclasses); | 952 if (nativeSubclasses != null) result.addAll(nativeSubclasses); |
| 951 } | 953 } |
| 952 } | 954 } |
| 953 return result; | 955 return result; |
| 954 }); | 956 }); |
| 955 } | 957 } |
| 956 | 958 |
| 957 Set<ClassElement> nativeSubclassesOfMixin(ClassElement mixin) { | 959 Set<ClassElement> nativeSubclassesOfMixin(ClassElement mixin) { |
| 958 ClosedWorld closedWorld = compiler.closedWorld; | 960 Iterable<MixinApplicationElement> uses = _closedWorld.mixinUsesOf(mixin); |
| 959 Iterable<MixinApplicationElement> uses = closedWorld.mixinUsesOf(mixin); | |
| 960 Set<ClassElement> result = null; | 961 Set<ClassElement> result = null; |
| 961 for (MixinApplicationElement use in uses) { | 962 for (MixinApplicationElement use in uses) { |
| 962 closedWorld.forEachStrictSubclassOf(use, (ClassElement subclass) { | 963 _closedWorld.forEachStrictSubclassOf(use, (ClassElement subclass) { |
| 963 if (isNativeOrExtendsNative(subclass)) { | 964 if (isNativeOrExtendsNative(subclass)) { |
| 964 if (result == null) result = new Set<ClassElement>(); | 965 if (result == null) result = new Set<ClassElement>(); |
| 965 result.add(subclass); | 966 result.add(subclass); |
| 966 } | 967 } |
| 967 }); | 968 }); |
| 968 } | 969 } |
| 969 return result; | 970 return result; |
| 970 } | 971 } |
| 971 | 972 |
| 972 bool operatorEqHandlesNullArgument(FunctionElement operatorEqfunction) { | 973 bool operatorEqHandlesNullArgument(FunctionElement operatorEqfunction) { |
| (...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1492 } else { | 1493 } else { |
| 1493 // If the constant-handler was not able to produce a result we have to | 1494 // If the constant-handler was not able to produce a result we have to |
| 1494 // go through the builder (below) to generate the lazy initializer for | 1495 // go through the builder (below) to generate the lazy initializer for |
| 1495 // the static variable. | 1496 // the static variable. |
| 1496 // We also need to register the use of the cyclic-error helper. | 1497 // We also need to register the use of the cyclic-error helper. |
| 1497 work.registry.worldImpact.registerStaticUse(new StaticUse.staticInvoke( | 1498 work.registry.worldImpact.registerStaticUse(new StaticUse.staticInvoke( |
| 1498 helpers.cyclicThrowHelper, CallStructure.ONE_ARG)); | 1499 helpers.cyclicThrowHelper, CallStructure.ONE_ARG)); |
| 1499 } | 1500 } |
| 1500 } | 1501 } |
| 1501 | 1502 |
| 1502 jsAst.Fun function = functionCompiler.compile(work); | 1503 jsAst.Fun function = functionCompiler.compile(work, _closedWorld); |
| 1503 if (function.sourceInformation == null) { | 1504 if (function.sourceInformation == null) { |
| 1504 function = function.withSourceInformation( | 1505 function = function.withSourceInformation( |
| 1505 sourceInformationStrategy.buildSourceMappedMarker()); | 1506 sourceInformationStrategy.buildSourceMappedMarker()); |
| 1506 } | 1507 } |
| 1507 generatedCode[element] = function; | 1508 generatedCode[element] = function; |
| 1508 WorldImpact worldImpact = | 1509 WorldImpact worldImpact = |
| 1509 impactTransformer.transformCodegenImpact(work.registry.worldImpact); | 1510 impactTransformer.transformCodegenImpact(work.registry.worldImpact); |
| 1510 compiler.dumpInfoTask.registerImpact(element, worldImpact); | 1511 compiler.dumpInfoTask.registerImpact(element, worldImpact); |
| 1511 return worldImpact; | 1512 return worldImpact; |
| 1512 } | 1513 } |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1745 element == helpers.jsUnmodifiableArrayClass; | 1746 element == helpers.jsUnmodifiableArrayClass; |
| 1746 } | 1747 } |
| 1747 | 1748 |
| 1748 bool mayGenerateInstanceofCheck(DartType type) { | 1749 bool mayGenerateInstanceofCheck(DartType type) { |
| 1749 // We can use an instanceof check for raw types that have no subclass that | 1750 // We can use an instanceof check for raw types that have no subclass that |
| 1750 // is mixed-in or in an implements clause. | 1751 // is mixed-in or in an implements clause. |
| 1751 | 1752 |
| 1752 if (!type.isRaw) return false; | 1753 if (!type.isRaw) return false; |
| 1753 ClassElement classElement = type.element; | 1754 ClassElement classElement = type.element; |
| 1754 if (isInterceptorClass(classElement)) return false; | 1755 if (isInterceptorClass(classElement)) return false; |
| 1755 return compiler.closedWorld.hasOnlySubclasses(classElement); | 1756 return _closedWorld.hasOnlySubclasses(classElement); |
| 1756 } | 1757 } |
| 1757 | 1758 |
| 1758 WorldImpact registerUsedElement(Element element, {bool forResolution}) { | 1759 WorldImpact registerUsedElement(Element element, {bool forResolution}) { |
| 1759 WorldImpactBuilderImpl worldImpact = new WorldImpactBuilderImpl(); | 1760 WorldImpactBuilderImpl worldImpact = new WorldImpactBuilderImpl(); |
| 1760 if (element == helpers.disableTreeShakingMarker) { | 1761 if (element == helpers.disableTreeShakingMarker) { |
| 1761 isTreeShakingDisabled = true; | 1762 isTreeShakingDisabled = true; |
| 1762 } else if (element == helpers.preserveNamesMarker) { | 1763 } else if (element == helpers.preserveNamesMarker) { |
| 1763 mustPreserveNames = true; | 1764 mustPreserveNames = true; |
| 1764 } else if (element == helpers.preserveMetadataMarker) { | 1765 } else if (element == helpers.preserveMetadataMarker) { |
| 1765 mustRetainMetadata = true; | 1766 mustRetainMetadata = true; |
| (...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2355 } | 2356 } |
| 2356 | 2357 |
| 2357 entities.forEach(processElementMetadata); | 2358 entities.forEach(processElementMetadata); |
| 2358 } | 2359 } |
| 2359 | 2360 |
| 2360 void onQueueClosed() { | 2361 void onQueueClosed() { |
| 2361 lookupMapAnalysis.onQueueClosed(); | 2362 lookupMapAnalysis.onQueueClosed(); |
| 2362 jsInteropAnalysis.onQueueClosed(); | 2363 jsInteropAnalysis.onQueueClosed(); |
| 2363 } | 2364 } |
| 2364 | 2365 |
| 2366 // TODO(johnniwinther): Create a CodegenPhase object for the backend to hold |
| 2367 // data only available during code generation. |
| 2368 ClosedWorld _closedWorldCache; |
| 2369 ClosedWorld get _closedWorld { |
| 2370 assert(invariant(NO_LOCATION_SPANNABLE, _closedWorldCache != null, |
| 2371 message: "ClosedWorld has not be set yet.")); |
| 2372 return _closedWorldCache; |
| 2373 } |
| 2374 |
| 2375 void set _closedWorld(ClosedWorld value) { |
| 2376 _closedWorldCache = value; |
| 2377 } |
| 2378 |
| 2365 WorldImpact onCodegenStart(ClosedWorld closedWorld) { | 2379 WorldImpact onCodegenStart(ClosedWorld closedWorld) { |
| 2366 _namer = determineNamer(closedWorld); | 2380 _closedWorld = closedWorld; |
| 2367 emitter.createEmitter(_namer, closedWorld); | 2381 _namer = determineNamer(_closedWorld); |
| 2382 tracer = new Tracer(_closedWorld, namer, compiler.outputProvider); |
| 2383 emitter.createEmitter(_namer, _closedWorld); |
| 2368 lookupMapAnalysis.onCodegenStart(); | 2384 lookupMapAnalysis.onCodegenStart(); |
| 2369 if (hasIsolateSupport) { | 2385 if (hasIsolateSupport) { |
| 2370 return enableIsolateSupport(forResolution: false); | 2386 return enableIsolateSupport(forResolution: false); |
| 2371 } | 2387 } |
| 2372 return const WorldImpact(); | 2388 return const WorldImpact(); |
| 2373 } | 2389 } |
| 2374 | 2390 |
| 2391 void onCodegenEnd() { |
| 2392 sourceInformationStrategy.onComplete(); |
| 2393 tracer.close(); |
| 2394 } |
| 2395 |
| 2375 /// Process backend specific annotations. | 2396 /// Process backend specific annotations. |
| 2376 void processAnnotations( | 2397 void processAnnotations( |
| 2377 Element element, ClosedWorldRefiner closedWorldRefiner) { | 2398 Element element, ClosedWorldRefiner closedWorldRefiner) { |
| 2378 if (element.isMalformed) { | 2399 if (element.isMalformed) { |
| 2379 // Elements that are marked as malformed during parsing or resolution | 2400 // Elements that are marked as malformed during parsing or resolution |
| 2380 // might be registered here. These should just be ignored. | 2401 // might be registered here. These should just be ignored. |
| 2381 return; | 2402 return; |
| 2382 } | 2403 } |
| 2383 | 2404 |
| 2384 Element implementation = element.implementation; | 2405 Element implementation = element.implementation; |
| (...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3225 @override | 3246 @override |
| 3226 bool isInterceptorClass(ClassElement cls) { | 3247 bool isInterceptorClass(ClassElement cls) { |
| 3227 return helpers.backend.isInterceptorClass(cls); | 3248 return helpers.backend.isInterceptorClass(cls); |
| 3228 } | 3249 } |
| 3229 | 3250 |
| 3230 @override | 3251 @override |
| 3231 bool isNative(Element element) { | 3252 bool isNative(Element element) { |
| 3232 return helpers.backend.isNative(element); | 3253 return helpers.backend.isNative(element); |
| 3233 } | 3254 } |
| 3234 } | 3255 } |
| OLD | NEW |