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 1439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1450 void registerClosureWithFreeTypeVariables( | 1450 void registerClosureWithFreeTypeVariables( |
1451 Element closure, | 1451 Element closure, |
1452 Enqueuer enqueuer, | 1452 Enqueuer enqueuer, |
1453 Registry registry) { | 1453 Registry registry) { |
1454 if (enqueuer.isResolutionQueue || methodNeedsRti(closure)) { | 1454 if (enqueuer.isResolutionQueue || methodNeedsRti(closure)) { |
1455 registerComputeSignature(enqueuer, registry); | 1455 registerComputeSignature(enqueuer, registry); |
1456 } | 1456 } |
1457 super.registerClosureWithFreeTypeVariables(closure, enqueuer, registry); | 1457 super.registerClosureWithFreeTypeVariables(closure, enqueuer, registry); |
1458 } | 1458 } |
1459 | 1459 |
1460 /// Call during codegen if an instance of [closure] is being created. | |
1461 void registerInstantiatedClosure(LocalFunctionElement closure, | |
1462 Registry registry) { | |
1463 if (methodNeedsRti(closure)) { | |
1464 registerComputeSignature(compiler.enqueuer.codegen, registry); | |
1465 } | |
1466 } | |
1467 | |
1468 void registerBoundClosure(Enqueuer enqueuer) { | 1460 void registerBoundClosure(Enqueuer enqueuer) { |
1469 boundClosureClass.ensureResolved(resolution); | 1461 boundClosureClass.ensureResolved(resolution); |
1470 registerInstantiatedType( | 1462 registerInstantiatedType( |
1471 boundClosureClass.rawType, | 1463 boundClosureClass.rawType, |
1472 enqueuer, | 1464 enqueuer, |
1473 // Precise dependency is not important here. | 1465 // Precise dependency is not important here. |
1474 compiler.globalDependencies); | 1466 compiler.globalDependencies); |
1475 } | 1467 } |
1476 | 1468 |
1477 void registerGetOfStaticFunction(Enqueuer enqueuer) { | 1469 void registerGetOfStaticFunction(Enqueuer enqueuer) { |
(...skipping 12 matching lines...) Expand all Loading... |
1490 } | 1482 } |
1491 | 1483 |
1492 void registerRuntimeType(Enqueuer enqueuer, Registry registry) { | 1484 void registerRuntimeType(Enqueuer enqueuer, Registry registry) { |
1493 registerComputeSignature(enqueuer, registry); | 1485 registerComputeSignature(enqueuer, registry); |
1494 enqueueInResolution(helpers.setRuntimeTypeInfo, registry); | 1486 enqueueInResolution(helpers.setRuntimeTypeInfo, registry); |
1495 registerGetRuntimeTypeArgument(registry); | 1487 registerGetRuntimeTypeArgument(registry); |
1496 enqueueInResolution(helpers.getRuntimeTypeInfo, registry); | 1488 enqueueInResolution(helpers.getRuntimeTypeInfo, registry); |
1497 enqueueClass(enqueuer, coreClasses.listClass, registry); | 1489 enqueueClass(enqueuer, coreClasses.listClass, registry); |
1498 } | 1490 } |
1499 | 1491 |
1500 void registerIsCheckForCodegen(DartType type, | |
1501 Enqueuer world, | |
1502 Registry registry) { | |
1503 assert(!registry.isForResolution); | |
1504 type = type.unaliased; | |
1505 enqueueClass(world, coreClasses.boolClass, registry); | |
1506 bool inCheckedMode = compiler.enableTypeAssertions; | |
1507 // [registerIsCheck] is also called for checked mode checks, so we | |
1508 // need to register checked mode helpers. | |
1509 if (inCheckedMode) { | |
1510 // All helpers are added to resolution queue in enqueueHelpers. These | |
1511 // calls to enqueueInResolution serve as assertions that the helper was | |
1512 // in fact added. | |
1513 // TODO(13155): Find a way to enqueue helpers lazily. | |
1514 CheckedModeHelper helper = getCheckedModeHelper(type, typeCast: false); | |
1515 if (helper != null) { | |
1516 enqueue(world, helper.getElement(compiler), registry); | |
1517 } | |
1518 // We also need the native variant of the check (for DOM types). | |
1519 helper = getNativeCheckedModeHelper(type, typeCast: false); | |
1520 if (helper != null) { | |
1521 enqueue(world, helper.getElement(compiler), registry); | |
1522 } | |
1523 } | |
1524 if (!type.treatAsRaw || type.containsTypeVariables) { | |
1525 enqueueClass(world, coreClasses.listClass, registry); | |
1526 } | |
1527 if (type.element != null && isNative(type.element)) { | |
1528 // We will neeed to add the "$is" and "$as" properties on the | |
1529 // JavaScript object prototype, so we make sure | |
1530 // [:defineProperty:] is compiled. | |
1531 enqueue(world, findHelper('defineProperty'), registry); | |
1532 } | |
1533 } | |
1534 | |
1535 void registerTypeVariableBoundsSubtypeCheck(DartType typeArgument, | 1492 void registerTypeVariableBoundsSubtypeCheck(DartType typeArgument, |
1536 DartType bound) { | 1493 DartType bound) { |
1537 rti.registerTypeVariableBoundsSubtypeCheck(typeArgument, bound); | 1494 rti.registerTypeVariableBoundsSubtypeCheck(typeArgument, bound); |
1538 } | 1495 } |
1539 | 1496 |
1540 void registerCheckDeferredIsLoaded(Registry registry) { | 1497 void registerCheckDeferredIsLoaded(Registry registry) { |
1541 enqueueInResolution(helpers.checkDeferredIsLoaded, registry); | 1498 enqueueInResolution(helpers.checkDeferredIsLoaded, registry); |
1542 // Also register the types of the arguments passed to this method. | 1499 // Also register the types of the arguments passed to this method. |
1543 enqueueClass( | 1500 enqueueClass( |
1544 compiler.enqueuer.resolution, coreClasses.stringClass, registry); | 1501 compiler.enqueuer.resolution, coreClasses.stringClass, registry); |
(...skipping 1260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2805 String deferredPartFileName(String name, {bool addExtension: true}) { | 2762 String deferredPartFileName(String name, {bool addExtension: true}) { |
2806 assert(name != ""); | 2763 assert(name != ""); |
2807 String outPath = compiler.outputUri != null | 2764 String outPath = compiler.outputUri != null |
2808 ? compiler.outputUri.path | 2765 ? compiler.outputUri.path |
2809 : "out"; | 2766 : "out"; |
2810 String outName = outPath.substring(outPath.lastIndexOf('/') + 1); | 2767 String outName = outPath.substring(outPath.lastIndexOf('/') + 1); |
2811 String extension = addExtension ? ".part.js" : ""; | 2768 String extension = addExtension ? ".part.js" : ""; |
2812 return "${outName}_$name$extension"; | 2769 return "${outName}_$name$extension"; |
2813 } | 2770 } |
2814 | 2771 |
2815 void registerAsyncMarker(FunctionElement element, | |
2816 Enqueuer enqueuer, | |
2817 Registry registry) { | |
2818 if (element.asyncMarker == AsyncMarker.ASYNC) { | |
2819 _registerAsync(enqueuer, registry); | |
2820 } else if (element.asyncMarker == AsyncMarker.SYNC_STAR) { | |
2821 _registerSyncStar(enqueuer, registry); | |
2822 } else if (element.asyncMarker == AsyncMarker.ASYNC_STAR) { | |
2823 _registerAsyncStar(enqueuer, registry); | |
2824 } | |
2825 } | |
2826 | |
2827 void _registerAsync(Enqueuer enqueuer, | |
2828 Registry registry) { | |
2829 enqueueImpact(enqueuer, impacts.asyncBody, registry); | |
2830 } | |
2831 | |
2832 void _registerSyncStar(Enqueuer enqueuer, | |
2833 Registry registry) { | |
2834 enqueueImpact(enqueuer, impacts.syncStarBody, registry); | |
2835 } | |
2836 | |
2837 void _registerAsyncStar(Enqueuer enqueuer, | |
2838 Registry registry) { | |
2839 enqueueImpact(enqueuer, impacts.asyncStarBody, registry); | |
2840 } | |
2841 | |
2842 @override | 2772 @override |
2843 bool enableDeferredLoadingIfSupported(Spannable node, Registry registry) { | 2773 bool enableDeferredLoadingIfSupported(Spannable node, Registry registry) { |
2844 registerCheckDeferredIsLoaded(registry); | 2774 registerCheckDeferredIsLoaded(registry); |
2845 return true; | 2775 return true; |
2846 } | 2776 } |
2847 | 2777 |
2848 @override | 2778 @override |
2849 bool enableCodegenWithErrorsIfSupported(Spannable node) { | 2779 bool enableCodegenWithErrorsIfSupported(Spannable node) { |
2850 if (compiler.useCpsIr) { | 2780 if (compiler.useCpsIr) { |
2851 reporter.reportHintMessage( | 2781 reporter.reportHintMessage( |
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3217 } | 3147 } |
3218 } | 3148 } |
3219 if (type is FunctionType) { | 3149 if (type is FunctionType) { |
3220 registerBackendImpact(transformed, impacts.functionTypeCheck); | 3150 registerBackendImpact(transformed, impacts.functionTypeCheck); |
3221 } | 3151 } |
3222 if (type.element != null && backend.isNative(type.element)) { | 3152 if (type.element != null && backend.isNative(type.element)) { |
3223 registerBackendImpact(transformed, impacts.nativeTypeCheck); | 3153 registerBackendImpact(transformed, impacts.nativeTypeCheck); |
3224 } | 3154 } |
3225 } | 3155 } |
3226 | 3156 |
| 3157 void onIsCheckForCodegen(DartType type, TransformedWorldImpact transformed) { |
| 3158 type = type.unaliased; |
| 3159 registerBackendImpact(transformed, impacts.typeCheck); |
| 3160 |
| 3161 bool inCheckedMode = backend.compiler.enableTypeAssertions; |
| 3162 // [registerIsCheck] is also called for checked mode checks, so we |
| 3163 // need to register checked mode helpers. |
| 3164 if (inCheckedMode) { |
| 3165 // All helpers are added to resolution queue in enqueueHelpers. These |
| 3166 // calls to enqueueInResolution serve as assertions that the helper was |
| 3167 // in fact added. |
| 3168 // TODO(13155): Find a way to enqueue helpers lazily. |
| 3169 CheckedModeHelper helper = |
| 3170 backend.getCheckedModeHelper(type, typeCast: false); |
| 3171 if (helper != null) { |
| 3172 Element helperElement = helper.getElement(backend.compiler); |
| 3173 transformed.registerStaticUse(helperElement); |
| 3174 backend.registerBackendUse(helperElement); |
| 3175 } |
| 3176 // We also need the native variant of the check (for DOM types). |
| 3177 helper = backend.getNativeCheckedModeHelper(type, typeCast: false); |
| 3178 if (helper != null) { |
| 3179 Element helperElement = helper.getElement(backend.compiler); |
| 3180 transformed.registerStaticUse(helperElement); |
| 3181 backend.registerBackendUse(helperElement); |
| 3182 } |
| 3183 } |
| 3184 if (!type.treatAsRaw || type.containsTypeVariables) { |
| 3185 registerBackendImpact(transformed, impacts.genericIsCheck); |
| 3186 } |
| 3187 if (type.element != null && backend.isNative(type.element)) { |
| 3188 // We will neeed to add the "$is" and "$as" properties on the |
| 3189 // JavaScript object prototype, so we make sure |
| 3190 // [:defineProperty:] is compiled. |
| 3191 registerBackendImpact(transformed, impacts.nativeTypeCheck); |
| 3192 } |
| 3193 } |
| 3194 |
3227 @override | 3195 @override |
3228 WorldImpact transformCodegenImpact(CodegenImpact impact) { | 3196 WorldImpact transformCodegenImpact(CodegenImpact impact) { |
| 3197 TransformedWorldImpact transformed = new TransformedWorldImpact(impact); |
3229 EagerRegistry registry = impact.registry; | 3198 EagerRegistry registry = impact.registry; |
3230 Enqueuer world = registry.world; | 3199 Enqueuer world = registry.world; |
3231 | 3200 |
3232 for (InterfaceType type in impact.instantiatedTypes) { | 3201 for (InterfaceType type in impact.instantiatedTypes) { |
3233 backend.registerInstantiatedType(type, world, registry); | 3202 backend.lookupMapAnalysis.registerInstantiatedType(type, registry); |
3234 } | |
3235 | |
3236 for (Element element in impact.staticUses) { | |
3237 world.registerStaticUse(element); | |
3238 } | |
3239 | |
3240 for (UniverseSelector selector in impact.dynamicInvocations) { | |
3241 world.registerDynamicInvocation(selector); | |
3242 } | |
3243 | |
3244 for (UniverseSelector selector in impact.dynamicGetters) { | |
3245 world.registerDynamicGetter(selector); | |
3246 } | |
3247 | |
3248 for (UniverseSelector selector in impact.dynamicSetters) { | |
3249 world.registerDynamicSetter(selector); | |
3250 } | |
3251 | |
3252 for (UniverseSelector selector in impact.dynamicSetters) { | |
3253 world.registerDynamicSetter(selector); | |
3254 } | 3203 } |
3255 | 3204 |
3256 for (Element element in impact.getterForSuperElements) { | 3205 for (Element element in impact.getterForSuperElements) { |
3257 world.registerGetterForSuperMethod(element); | 3206 world.registerGetterForSuperMethod(element); |
3258 } | 3207 } |
3259 | 3208 |
3260 for (Element element in impact.fieldGetters) { | 3209 for (Element element in impact.fieldGetters) { |
3261 world.registerFieldGetter(element); | 3210 world.registerFieldGetter(element); |
3262 } | 3211 } |
3263 | 3212 |
3264 for (Element element in impact.fieldSetters) { | 3213 for (Element element in impact.fieldSetters) { |
3265 world.registerFieldSetter(element); | 3214 world.registerFieldSetter(element); |
3266 } | 3215 } |
3267 | 3216 |
3268 for (DartType type in impact.isChecks) { | 3217 for (DartType type in impact.isChecks) { |
3269 world.registerIsCheck(type); | 3218 onIsCheckForCodegen(type, transformed); |
3270 backend.registerIsCheckForCodegen(type, world, registry); | |
3271 } | 3219 } |
3272 | 3220 |
3273 for (ConstantValue constant in impact.compileTimeConstants) { | 3221 for (ConstantValue constant in impact.compileTimeConstants) { |
3274 backend.registerCompileTimeConstant(constant, registry); | 3222 backend.registerCompileTimeConstant(constant, registry); |
3275 backend.addCompileTimeConstantForEmission(constant); | 3223 backend.addCompileTimeConstantForEmission(constant); |
3276 } | 3224 } |
3277 | 3225 |
3278 for (Pair<DartType, DartType> check in | 3226 for (Pair<DartType, DartType> check in |
3279 impact.typeVariableBoundsSubtypeChecks) { | 3227 impact.typeVariableBoundsSubtypeChecks) { |
3280 backend.registerTypeVariableBoundsSubtypeCheck(check.a, check.b); | 3228 backend.registerTypeVariableBoundsSubtypeCheck(check.a, check.b); |
3281 } | 3229 } |
3282 | 3230 |
3283 for (LocalFunctionElement element in impact.closures) { | 3231 for (LocalFunctionElement element in impact.closures) { |
3284 backend.registerInstantiatedClosure(element, registry); | 3232 if (backend.methodNeedsRti(element)) { |
3285 } | 3233 registerBackendImpact(transformed, impacts.computeSignature); |
3286 | 3234 } |
3287 for (Element element in impact.closurizedFunctions) { | |
3288 world.registerGetOfStaticFunction(element); | |
3289 } | 3235 } |
3290 | 3236 |
3291 for (String name in impact.constSymbols) { | 3237 for (String name in impact.constSymbols) { |
3292 backend.registerConstSymbol(name); | 3238 backend.registerConstSymbol(name); |
3293 } | 3239 } |
3294 | 3240 |
3295 for (Set<ClassElement> classes in impact.specializedGetInterceptors) { | 3241 for (Set<ClassElement> classes in impact.specializedGetInterceptors) { |
3296 backend.registerSpecializedGetInterceptor(classes); | 3242 backend.registerSpecializedGetInterceptor(classes); |
3297 } | 3243 } |
3298 | 3244 |
3299 if (impact.usesInterceptor) { | 3245 if (impact.usesInterceptor) { |
3300 backend.registerUseInterceptor(world); | 3246 backend.registerUseInterceptor(world); |
3301 } | 3247 } |
3302 | 3248 |
3303 for (ClassElement element in impact.typeConstants) { | 3249 for (ClassElement element in impact.typeConstants) { |
3304 backend.customElementsAnalysis.registerTypeConstant(element, world); | 3250 backend.customElementsAnalysis.registerTypeConstant(element); |
3305 backend.lookupMapAnalysis.registerTypeConstant(element); | 3251 backend.lookupMapAnalysis.registerTypeConstant(element); |
3306 } | 3252 } |
3307 | 3253 |
3308 for (FunctionElement element in impact.asyncMarkers) { | 3254 for (FunctionElement element in impact.asyncMarkers) { |
3309 backend.registerAsyncMarker(element, world, registry); | 3255 switch (element.asyncMarker) { |
| 3256 case AsyncMarker.ASYNC: |
| 3257 registerBackendImpact(transformed, impacts.asyncBody); |
| 3258 break; |
| 3259 case AsyncMarker.SYNC_STAR: |
| 3260 registerBackendImpact(transformed, impacts.syncStarBody); |
| 3261 break; |
| 3262 case AsyncMarker.ASYNC_STAR: |
| 3263 registerBackendImpact(transformed, impacts.asyncStarBody); |
| 3264 break; |
| 3265 } |
3310 } | 3266 } |
3311 | 3267 |
3312 // TODO(johnniwinther): Remove eager registration. | 3268 // TODO(johnniwinther): Remove eager registration. |
3313 return const WorldImpact(); | 3269 return transformed; |
3314 } | 3270 } |
3315 } | 3271 } |
3316 | 3272 |
3317 /// Records that [constant] is used by the element behind [registry]. | 3273 /// Records that [constant] is used by the element behind [registry]. |
3318 class Dependency { | 3274 class Dependency { |
3319 final ConstantValue constant; | 3275 final ConstantValue constant; |
3320 final Element annotatedElement; | 3276 final Element annotatedElement; |
3321 | 3277 |
3322 const Dependency(this.constant, this.annotatedElement); | 3278 const Dependency(this.constant, this.annotatedElement); |
3323 } | 3279 } |
3324 | 3280 |
OLD | NEW |