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 part of js_backend; | 5 part of js_backend; |
6 | 6 |
7 const VERBOSE_OPTIMIZER_HINTS = false; | 7 const VERBOSE_OPTIMIZER_HINTS = false; |
8 | 8 |
9 class JavaScriptItemCompilationContext extends ItemCompilationContext { | 9 class JavaScriptItemCompilationContext extends ItemCompilationContext { |
10 final Set<HInstruction> boundsChecked = new Set<HInstruction>(); | 10 final Set<HInstruction> boundsChecked = new Set<HInstruction>(); |
(...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
623 LookupMapAnalysis lookupMapAnalysis; | 623 LookupMapAnalysis lookupMapAnalysis; |
624 | 624 |
625 /// Codegen support for typed JavaScript interop. | 625 /// Codegen support for typed JavaScript interop. |
626 JsInteropAnalysis jsInteropAnalysis; | 626 JsInteropAnalysis jsInteropAnalysis; |
627 | 627 |
628 /// Support for classifying `noSuchMethod` implementations. | 628 /// Support for classifying `noSuchMethod` implementations. |
629 NoSuchMethodRegistry noSuchMethodRegistry; | 629 NoSuchMethodRegistry noSuchMethodRegistry; |
630 | 630 |
631 JavaScriptConstantTask constantCompilerTask; | 631 JavaScriptConstantTask constantCompilerTask; |
632 | 632 |
633 JavaScriptResolutionCallbacks resolutionCallbacks; | 633 JavaScriptImpactTransformer impactTransformer; |
634 | 634 |
635 PatchResolverTask patchResolverTask; | 635 PatchResolverTask patchResolverTask; |
636 | 636 |
637 bool enabledNoSuchMethod = false; | 637 bool enabledNoSuchMethod = false; |
638 | 638 |
639 final SourceInformationStrategy sourceInformationStrategy; | 639 final SourceInformationStrategy sourceInformationStrategy; |
640 | 640 |
641 final BackendHelpers helpers; | 641 final BackendHelpers helpers; |
642 final BackendImpacts impacts; | 642 final BackendImpacts impacts; |
643 | 643 |
(...skipping 18 matching lines...) Expand all Loading... |
662 super(compiler) { | 662 super(compiler) { |
663 emitter = new CodeEmitterTask( | 663 emitter = new CodeEmitterTask( |
664 compiler, namer, generateSourceMap, useStartupEmitter); | 664 compiler, namer, generateSourceMap, useStartupEmitter); |
665 typeVariableHandler = new TypeVariableHandler(compiler); | 665 typeVariableHandler = new TypeVariableHandler(compiler); |
666 customElementsAnalysis = new CustomElementsAnalysis(this); | 666 customElementsAnalysis = new CustomElementsAnalysis(this); |
667 lookupMapAnalysis = new LookupMapAnalysis(this, reporter); | 667 lookupMapAnalysis = new LookupMapAnalysis(this, reporter); |
668 jsInteropAnalysis = new JsInteropAnalysis(this); | 668 jsInteropAnalysis = new JsInteropAnalysis(this); |
669 | 669 |
670 noSuchMethodRegistry = new NoSuchMethodRegistry(this); | 670 noSuchMethodRegistry = new NoSuchMethodRegistry(this); |
671 constantCompilerTask = new JavaScriptConstantTask(compiler); | 671 constantCompilerTask = new JavaScriptConstantTask(compiler); |
672 resolutionCallbacks = new JavaScriptResolutionCallbacks(this); | 672 impactTransformer = new JavaScriptImpactTransformer(this); |
673 patchResolverTask = new PatchResolverTask(compiler); | 673 patchResolverTask = new PatchResolverTask(compiler); |
674 functionCompiler = compiler.useCpsIr | 674 functionCompiler = compiler.useCpsIr |
675 ? new CpsFunctionCompiler( | 675 ? new CpsFunctionCompiler( |
676 compiler, this, sourceInformationStrategy) | 676 compiler, this, sourceInformationStrategy) |
677 : new SsaFunctionCompiler(this, sourceInformationStrategy); | 677 : new SsaFunctionCompiler(this, sourceInformationStrategy); |
678 } | 678 } |
679 | 679 |
680 ConstantSystem get constantSystem => constants.constantSystem; | 680 ConstantSystem get constantSystem => constants.constantSystem; |
681 | 681 |
682 DiagnosticReporter get reporter => compiler.reporter; | 682 DiagnosticReporter get reporter => compiler.reporter; |
(...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1442 Enqueuer enqueuer, | 1442 Enqueuer enqueuer, |
1443 Registry registry) { | 1443 Registry registry) { |
1444 if (enqueuer.isResolutionQueue || methodNeedsRti(closure)) { | 1444 if (enqueuer.isResolutionQueue || methodNeedsRti(closure)) { |
1445 registerComputeSignature(enqueuer, registry); | 1445 registerComputeSignature(enqueuer, registry); |
1446 } | 1446 } |
1447 super.registerClosureWithFreeTypeVariables(closure, enqueuer, registry); | 1447 super.registerClosureWithFreeTypeVariables(closure, enqueuer, registry); |
1448 } | 1448 } |
1449 | 1449 |
1450 /// Call during codegen if an instance of [closure] is being created. | 1450 /// Call during codegen if an instance of [closure] is being created. |
1451 void registerInstantiatedClosure(LocalFunctionElement closure, | 1451 void registerInstantiatedClosure(LocalFunctionElement closure, |
1452 CodegenRegistry registry) { | 1452 Registry registry) { |
1453 if (methodNeedsRti(closure)) { | 1453 if (methodNeedsRti(closure)) { |
1454 registerComputeSignature(compiler.enqueuer.codegen, registry); | 1454 registerComputeSignature(compiler.enqueuer.codegen, registry); |
1455 } | 1455 } |
1456 } | 1456 } |
1457 | 1457 |
1458 void registerBoundClosure(Enqueuer enqueuer) { | 1458 void registerBoundClosure(Enqueuer enqueuer) { |
1459 boundClosureClass.ensureResolved(resolution); | 1459 boundClosureClass.ensureResolved(resolution); |
1460 registerInstantiatedType( | 1460 registerInstantiatedType( |
1461 boundClosureClass.rawType, | 1461 boundClosureClass.rawType, |
1462 enqueuer, | 1462 enqueuer, |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1705 for (BackendImpact otherImpact in impact.otherImpacts) { | 1705 for (BackendImpact otherImpact in impact.otherImpacts) { |
1706 enqueueImpact(enqueuer, otherImpact, registry); | 1706 enqueueImpact(enqueuer, otherImpact, registry); |
1707 } | 1707 } |
1708 } | 1708 } |
1709 | 1709 |
1710 WorldImpact codegen(CodegenWorkItem work) { | 1710 WorldImpact codegen(CodegenWorkItem work) { |
1711 Element element = work.element; | 1711 Element element = work.element; |
1712 if (compiler.elementHasCompileTimeError(element)) { | 1712 if (compiler.elementHasCompileTimeError(element)) { |
1713 generatedCode[element] = jsAst.js( | 1713 generatedCode[element] = jsAst.js( |
1714 "function () { throw new Error('Compile time error in $element') }"); | 1714 "function () { throw new Error('Compile time error in $element') }"); |
1715 return const WorldImpact(); | 1715 return const CodegenImpact(); |
1716 } | 1716 } |
1717 var kind = element.kind; | 1717 var kind = element.kind; |
1718 if (kind == ElementKind.TYPEDEF) { | 1718 if (kind == ElementKind.TYPEDEF) { |
1719 return const WorldImpact(); | 1719 return const WorldImpact(); |
1720 } | 1720 } |
1721 if (element.isConstructor && element.enclosingClass == jsNullClass) { | 1721 if (element.isConstructor && element.enclosingClass == jsNullClass) { |
1722 // Work around a problem compiling JSNull's constructor. | 1722 // Work around a problem compiling JSNull's constructor. |
1723 return const WorldImpact(); | 1723 return const CodegenImpact(); |
1724 } | 1724 } |
1725 if (kind.category == ElementCategory.VARIABLE) { | 1725 if (kind.category == ElementCategory.VARIABLE) { |
1726 ConstantValue initialValue = | 1726 ConstantValue initialValue = |
1727 constants.getConstantValueForVariable(element); | 1727 constants.getConstantValueForVariable(element); |
1728 if (initialValue != null) { | 1728 if (initialValue != null) { |
1729 registerCompileTimeConstant(initialValue, work.registry); | 1729 registerCompileTimeConstant(initialValue, work.registry); |
1730 addCompileTimeConstantForEmission(initialValue); | 1730 addCompileTimeConstantForEmission(initialValue); |
1731 // We don't need to generate code for static or top-level | 1731 // We don't need to generate code for static or top-level |
1732 // variables. For instance variables, we may need to generate | 1732 // variables. For instance variables, we may need to generate |
1733 // the checked setter. | 1733 // the checked setter. |
1734 if (Elements.isStaticOrTopLevel(element)) { | 1734 if (Elements.isStaticOrTopLevel(element)) { |
1735 return const WorldImpact(); | 1735 return impactTransformer.transformCodegenImpact( |
| 1736 work.registry.worldImpact); |
1736 } | 1737 } |
1737 } else { | 1738 } else { |
1738 // If the constant-handler was not able to produce a result we have to | 1739 // If the constant-handler was not able to produce a result we have to |
1739 // go through the builder (below) to generate the lazy initializer for | 1740 // go through the builder (below) to generate the lazy initializer for |
1740 // the static variable. | 1741 // the static variable. |
1741 // We also need to register the use of the cyclic-error helper. | 1742 // We also need to register the use of the cyclic-error helper. |
1742 compiler.enqueuer.codegen.registerStaticUse( | 1743 compiler.enqueuer.codegen.registerStaticUse( |
1743 helpers.cyclicThrowHelper); | 1744 helpers.cyclicThrowHelper); |
1744 } | 1745 } |
1745 } | 1746 } |
1746 | 1747 |
1747 generatedCode[element] = functionCompiler.compile(work); | 1748 generatedCode[element] = functionCompiler.compile(work); |
1748 return const WorldImpact(); | 1749 return impactTransformer.transformCodegenImpact(work.registry.worldImpact); |
1749 } | 1750 } |
1750 | 1751 |
1751 native.NativeEnqueuer nativeResolutionEnqueuer(Enqueuer world) { | 1752 native.NativeEnqueuer nativeResolutionEnqueuer(Enqueuer world) { |
1752 return new native.NativeResolutionEnqueuer(world, compiler); | 1753 return new native.NativeResolutionEnqueuer(world, compiler); |
1753 } | 1754 } |
1754 | 1755 |
1755 native.NativeEnqueuer nativeCodegenEnqueuer(Enqueuer world) { | 1756 native.NativeEnqueuer nativeCodegenEnqueuer(Enqueuer world) { |
1756 return new native.NativeCodegenEnqueuer(world, compiler, emitter); | 1757 return new native.NativeCodegenEnqueuer(world, compiler, emitter); |
1757 } | 1758 } |
1758 | 1759 |
(...skipping 884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2643 // necessary, but the backend relies on them being resolved. | 2644 // necessary, but the backend relies on them being resolved. |
2644 enqueuer.enqueueReflectiveStaticFields(_findStaticFieldTargets()); | 2645 enqueuer.enqueueReflectiveStaticFields(_findStaticFieldTargets()); |
2645 } | 2646 } |
2646 | 2647 |
2647 if (mustPreserveNames) reporter.log('Preserving names.'); | 2648 if (mustPreserveNames) reporter.log('Preserving names.'); |
2648 | 2649 |
2649 if (mustRetainMetadata) { | 2650 if (mustRetainMetadata) { |
2650 reporter.log('Retaining metadata.'); | 2651 reporter.log('Retaining metadata.'); |
2651 | 2652 |
2652 compiler.libraryLoader.libraries.forEach(retainMetadataOf); | 2653 compiler.libraryLoader.libraries.forEach(retainMetadataOf); |
2653 if (enqueuer.isResolutionQueue) { | 2654 for (Dependency dependency in metadataConstants) { |
2654 for (Dependency dependency in metadataConstants) { | 2655 registerCompileTimeConstant( |
2655 registerCompileTimeConstant( | 2656 dependency.constant, |
2656 dependency.constant, | 2657 new EagerRegistry('EagerRegistry for ${dependency}', enqueuer)); |
2657 new EagerRegistry(compiler, | 2658 } |
2658 dependency.annotatedElement.analyzableElement.treeElements)); | 2659 if (!enqueuer.isResolutionQueue) { |
2659 } | |
2660 } else { | |
2661 for (Dependency dependency in metadataConstants) { | |
2662 registerCompileTimeConstant( | |
2663 dependency.constant, | |
2664 new CodegenRegistry(compiler, | |
2665 dependency.annotatedElement.analyzableElement.treeElements)); | |
2666 } | |
2667 metadataConstants.clear(); | 2660 metadataConstants.clear(); |
2668 } | 2661 } |
2669 } | 2662 } |
2670 return true; | 2663 return true; |
2671 } | 2664 } |
2672 | 2665 |
2673 void onQueueClosed() { | 2666 void onQueueClosed() { |
2674 lookupMapAnalysis.onQueueClosed(); | 2667 lookupMapAnalysis.onQueueClosed(); |
2675 jsInteropAnalysis.onQueueClosed(); | 2668 jsInteropAnalysis.onQueueClosed(); |
2676 } | 2669 } |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2974 if (constructedConstant.type.element == annotationClass) { | 2967 if (constructedConstant.type.element == annotationClass) { |
2975 return true; | 2968 return true; |
2976 } | 2969 } |
2977 } | 2970 } |
2978 } | 2971 } |
2979 return false; | 2972 return false; |
2980 }); | 2973 }); |
2981 } | 2974 } |
2982 } | 2975 } |
2983 | 2976 |
2984 class JavaScriptResolutionCallbacks extends ResolutionCallbacks { | 2977 class JavaScriptImpactTransformer extends ImpactTransformer { |
2985 final JavaScriptBackend backend; | 2978 final JavaScriptBackend backend; |
2986 | 2979 |
2987 JavaScriptResolutionCallbacks(this.backend); | 2980 JavaScriptImpactTransformer(this.backend); |
2988 | 2981 |
2989 BackendImpacts get impacts => backend.impacts; | 2982 BackendImpacts get impacts => backend.impacts; |
2990 | 2983 |
2991 WorldImpact transformImpact(ResolutionImpact worldImpact) { | 2984 @override |
| 2985 WorldImpact transformResolutionImpact(ResolutionImpact worldImpact) { |
2992 TransformedWorldImpact transformed = | 2986 TransformedWorldImpact transformed = |
2993 new TransformedWorldImpact(worldImpact); | 2987 new TransformedWorldImpact(worldImpact); |
2994 for (Feature feature in worldImpact.features) { | 2988 for (Feature feature in worldImpact.features) { |
2995 switch (feature) { | 2989 switch (feature) { |
2996 case Feature.ABSTRACT_CLASS_INSTANTIATION: | 2990 case Feature.ABSTRACT_CLASS_INSTANTIATION: |
2997 registerBackendImpact( | 2991 registerBackendImpact( |
2998 transformed, impacts.abstractClassInstantiation); | 2992 transformed, impacts.abstractClassInstantiation); |
2999 break; | 2993 break; |
3000 case Feature.ASSERT: | 2994 case Feature.ASSERT: |
3001 registerBackendImpact(transformed, impacts.assertWithoutMessage); | 2995 registerBackendImpact(transformed, impacts.assertWithoutMessage); |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3204 } | 3198 } |
3205 } | 3199 } |
3206 } | 3200 } |
3207 if (type is FunctionType) { | 3201 if (type is FunctionType) { |
3208 registerBackendImpact(transformed, impacts.functionTypeCheck); | 3202 registerBackendImpact(transformed, impacts.functionTypeCheck); |
3209 } | 3203 } |
3210 if (type.element != null && backend.isNative(type.element)) { | 3204 if (type.element != null && backend.isNative(type.element)) { |
3211 registerBackendImpact(transformed, impacts.nativeTypeCheck); | 3205 registerBackendImpact(transformed, impacts.nativeTypeCheck); |
3212 } | 3206 } |
3213 } | 3207 } |
| 3208 |
| 3209 @override |
| 3210 WorldImpact transformCodegenImpact(CodegenImpact impact) { |
| 3211 EagerRegistry registry = impact.registry; |
| 3212 Enqueuer world = registry.world; |
| 3213 |
| 3214 for (InterfaceType type in impact.instantiatedTypes) { |
| 3215 backend.registerInstantiatedType(type, world, registry); |
| 3216 } |
| 3217 |
| 3218 for (Element element in impact.staticUses) { |
| 3219 world.registerStaticUse(element); |
| 3220 } |
| 3221 |
| 3222 for (UniverseSelector selector in impact.dynamicInvocations) { |
| 3223 world.registerDynamicInvocation(selector); |
| 3224 } |
| 3225 |
| 3226 for (UniverseSelector selector in impact.dynamicGetters) { |
| 3227 world.registerDynamicGetter(selector); |
| 3228 } |
| 3229 |
| 3230 for (UniverseSelector selector in impact.dynamicSetters) { |
| 3231 world.registerDynamicSetter(selector); |
| 3232 } |
| 3233 |
| 3234 for (UniverseSelector selector in impact.dynamicSetters) { |
| 3235 world.registerDynamicSetter(selector); |
| 3236 } |
| 3237 |
| 3238 for (Element element in impact.getterForSuperElements) { |
| 3239 world.registerGetterForSuperMethod(element); |
| 3240 } |
| 3241 |
| 3242 for (Element element in impact.fieldGetters) { |
| 3243 world.registerFieldGetter(element); |
| 3244 } |
| 3245 |
| 3246 for (Element element in impact.fieldSetters) { |
| 3247 world.registerFieldSetter(element); |
| 3248 } |
| 3249 |
| 3250 for (DartType type in impact.isChecks) { |
| 3251 world.registerIsCheck(type); |
| 3252 backend.registerIsCheckForCodegen(type, world, registry); |
| 3253 } |
| 3254 |
| 3255 for (ConstantValue constant in impact.compileTimeConstants) { |
| 3256 backend.registerCompileTimeConstant(constant, registry); |
| 3257 backend.addCompileTimeConstantForEmission(constant); |
| 3258 } |
| 3259 |
| 3260 for (Pair<DartType, DartType> check in |
| 3261 impact.typeVariableBoundsSubtypeChecks) { |
| 3262 backend.registerTypeVariableBoundsSubtypeCheck(check.a, check.b); |
| 3263 } |
| 3264 |
| 3265 for (LocalFunctionElement element in impact.closures) { |
| 3266 backend.registerInstantiatedClosure(element, registry); |
| 3267 } |
| 3268 |
| 3269 for (Element element in impact.closurizedFunctions) { |
| 3270 world.registerGetOfStaticFunction(element); |
| 3271 } |
| 3272 |
| 3273 for (String name in impact.constSymbols) { |
| 3274 backend.registerConstSymbol(name); |
| 3275 } |
| 3276 |
| 3277 for (Set<ClassElement> classes in impact.specializedGetInterceptors) { |
| 3278 backend.registerSpecializedGetInterceptor(classes); |
| 3279 } |
| 3280 |
| 3281 if (impact.usesInterceptor) { |
| 3282 backend.registerUseInterceptor(world); |
| 3283 } |
| 3284 |
| 3285 for (ClassElement element in impact.typeConstants) { |
| 3286 backend.customElementsAnalysis.registerTypeConstant(element, world); |
| 3287 backend.lookupMapAnalysis.registerTypeConstant(element); |
| 3288 } |
| 3289 |
| 3290 for (FunctionElement element in impact.asyncMarkers) { |
| 3291 backend.registerAsyncMarker(element, world, registry); |
| 3292 } |
| 3293 |
| 3294 // TODO(johnniwinther): Remove eager registration. |
| 3295 return const WorldImpact(); |
| 3296 } |
3214 } | 3297 } |
3215 | 3298 |
3216 /// Records that [constant] is used by the element behind [registry]. | 3299 /// Records that [constant] is used by the element behind [registry]. |
3217 class Dependency { | 3300 class Dependency { |
3218 final ConstantValue constant; | 3301 final ConstantValue constant; |
3219 final Element annotatedElement; | 3302 final Element annotatedElement; |
3220 | 3303 |
3221 const Dependency(this.constant, this.annotatedElement); | 3304 const Dependency(this.constant, this.annotatedElement); |
3222 } | 3305 } |
3223 | 3306 |
OLD | NEW |