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