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