| 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 1421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1432 Element element = find(isolateHelperLibrary, name); | 1432 Element element = find(isolateHelperLibrary, name); |
| 1433 enqueuer.addToWorkList(element); | 1433 enqueuer.addToWorkList(element); |
| 1434 compiler.globalDependencies.registerDependency(element); | 1434 compiler.globalDependencies.registerDependency(element); |
| 1435 helpersUsed.add(element.declaration); | 1435 helpersUsed.add(element.declaration); |
| 1436 } | 1436 } |
| 1437 } else { | 1437 } else { |
| 1438 enqueuer.addToWorkList(find(isolateHelperLibrary, START_ROOT_ISOLATE)); | 1438 enqueuer.addToWorkList(find(isolateHelperLibrary, START_ROOT_ISOLATE)); |
| 1439 } | 1439 } |
| 1440 } | 1440 } |
| 1441 | 1441 |
| 1442 void registerRequiredType(DartType type) { | |
| 1443 // If [argument] has type variables or is a type variable, this method | |
| 1444 // registers a RTI dependency between the class where the type variable is | |
| 1445 // defined (that is the enclosing class of the current element being | |
| 1446 // resolved) and the class of [type]. If the class of [type] requires RTI, | |
| 1447 // then the class of the type variable does too. | |
| 1448 ClassElement contextClass = Types.getClassContext(type); | |
| 1449 if (contextClass != null) { | |
| 1450 rti.registerRtiDependency(type.element, contextClass); | |
| 1451 } | |
| 1452 } | |
| 1453 | |
| 1454 bool classNeedsRti(ClassElement cls) { | 1442 bool classNeedsRti(ClassElement cls) { |
| 1455 return rti.classesNeedingRti.contains(cls.declaration) || | 1443 return rti.classesNeedingRti.contains(cls.declaration) || |
| 1456 compiler.enabledRuntimeType; | 1444 compiler.enabledRuntimeType; |
| 1457 } | 1445 } |
| 1458 | 1446 |
| 1459 bool isComplexNoSuchMethod(FunctionElement element) => | 1447 bool isComplexNoSuchMethod(FunctionElement element) => |
| 1460 noSuchMethodRegistry.isComplex(element); | 1448 noSuchMethodRegistry.isComplex(element); |
| 1461 | 1449 |
| 1462 bool isDefaultEqualityImplementation(Element element) { | 1450 bool isDefaultEqualityImplementation(Element element) { |
| 1463 assert(element.name == '=='); | 1451 assert(element.name == '=='); |
| (...skipping 1438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2902 registerBackendImpact(transformed, impacts.throwNoSuchMethod); | 2890 registerBackendImpact(transformed, impacts.throwNoSuchMethod); |
| 2903 break; | 2891 break; |
| 2904 case Feature.THROW_RUNTIME_ERROR: | 2892 case Feature.THROW_RUNTIME_ERROR: |
| 2905 registerBackendImpact(transformed, impacts.throwRuntimeError); | 2893 registerBackendImpact(transformed, impacts.throwRuntimeError); |
| 2906 break; | 2894 break; |
| 2907 case Feature.TYPE_VARIABLE_BOUNDS_CHECK: | 2895 case Feature.TYPE_VARIABLE_BOUNDS_CHECK: |
| 2908 registerBackendImpact(transformed, impacts.typeVariableBoundCheck); | 2896 registerBackendImpact(transformed, impacts.typeVariableBoundCheck); |
| 2909 break; | 2897 break; |
| 2910 } | 2898 } |
| 2911 } | 2899 } |
| 2900 |
| 2901 for (InterfaceType type in worldImpact.instantiatedTypes) { |
| 2902 registerRequiredType(type); |
| 2903 } |
| 2904 |
| 2912 for (DartType type in worldImpact.isChecks) { | 2905 for (DartType type in worldImpact.isChecks) { |
| 2913 onIsCheck(type, transformed); | 2906 onIsCheck(type, transformed); |
| 2914 } | 2907 } |
| 2915 | 2908 |
| 2916 if (worldImpact.asCasts.isNotEmpty) { | 2909 if (worldImpact.asCasts.isNotEmpty) { |
| 2917 for (DartType type in worldImpact.asCasts) { | 2910 for (DartType type in worldImpact.asCasts) { |
| 2918 onIsCheck(type, transformed); | 2911 onIsCheck(type, transformed); |
| 2919 } | 2912 } |
| 2920 registerBackendImpact(transformed, impacts.asCheck); | 2913 registerBackendImpact(transformed, impacts.asCheck); |
| 2921 } | 2914 } |
| 2922 | 2915 |
| 2923 if (backend.compiler.enableTypeAssertions) { | 2916 if (backend.compiler.enableTypeAssertions) { |
| 2924 for (DartType type in worldImpact.checkedModeChecks) { | 2917 for (DartType type in worldImpact.checkedModeChecks) { |
| 2925 onIsCheck(type, transformed); | 2918 onIsCheck(type, transformed); |
| 2926 } | 2919 } |
| 2927 } | 2920 } |
| 2928 | 2921 |
| 2929 for (DartType requiredType in worldImpact.requiredTypes) { | 2922 for (DartType type in worldImpact.onCatchTypes) { |
| 2930 backend.registerRequiredType(requiredType); | 2923 onIsCheck(type, transformed); |
| 2931 } | 2924 } |
| 2932 | 2925 |
| 2933 for (MapLiteralUse mapLiteralUse in worldImpact.mapLiterals) { | 2926 for (MapLiteralUse mapLiteralUse in worldImpact.mapLiterals) { |
| 2934 // TODO(johnniwinther): Use the [isEmpty] property when factory | 2927 // TODO(johnniwinther): Use the [isEmpty] property when factory |
| 2935 // constructors are registered directly. | 2928 // constructors are registered directly. |
| 2936 if (mapLiteralUse.isConstant) { | 2929 if (mapLiteralUse.isConstant) { |
| 2937 registerBackendImpact(transformed, impacts.constantMapLiteral); | 2930 registerBackendImpact(transformed, impacts.constantMapLiteral); |
| 2938 } else { | 2931 } else { |
| 2939 transformed.registerInstantiatedType(mapLiteralUse.type); | 2932 transformed.registerInstantiatedType(mapLiteralUse.type); |
| 2940 } | 2933 } |
| 2934 registerRequiredType(mapLiteralUse.type); |
| 2941 } | 2935 } |
| 2942 | 2936 |
| 2943 for (ListLiteralUse listLiteralUse in worldImpact.listLiterals) { | 2937 for (ListLiteralUse listLiteralUse in worldImpact.listLiterals) { |
| 2944 // TODO(johnniwinther): Use the [isConstant] and [isEmpty] property when | 2938 // TODO(johnniwinther): Use the [isConstant] and [isEmpty] property when |
| 2945 // factory constructors are registered directly. | 2939 // factory constructors are registered directly. |
| 2946 transformed.registerInstantiatedType(listLiteralUse.type); | 2940 transformed.registerInstantiatedType(listLiteralUse.type); |
| 2941 registerRequiredType(listLiteralUse.type); |
| 2947 } | 2942 } |
| 2948 | 2943 |
| 2949 if (worldImpact.typeLiterals.isNotEmpty) { | 2944 if (worldImpact.typeLiterals.isNotEmpty) { |
| 2950 transformed.registerInstantiatedType(backend.compiler.coreTypes.typeType); | 2945 transformed.registerInstantiatedType(backend.compiler.coreTypes.typeType); |
| 2951 registerBackendImpact(transformed, impacts.typeLiteral); | 2946 registerBackendImpact(transformed, impacts.typeLiteral); |
| 2952 for (DartType typeLiteral in worldImpact.typeLiterals) { | 2947 for (DartType typeLiteral in worldImpact.typeLiterals) { |
| 2953 backend.customElementsAnalysis.registerTypeLiteral(typeLiteral); | 2948 backend.customElementsAnalysis.registerTypeLiteral(typeLiteral); |
| 2954 if (typeLiteral.isTypedef) { | 2949 if (typeLiteral.isTypedef) { |
| 2955 backend.compiler.world.allTypedefs.add(typeLiteral.element); | 2950 backend.compiler.world.allTypedefs.add(typeLiteral.element); |
| 2956 } | 2951 } |
| 2957 if (typeLiteral.isTypeVariable) { | 2952 if (typeLiteral.isTypeVariable) { |
| 2958 ClassElement cls = typeLiteral.element.enclosingClass; | 2953 ClassElement cls = typeLiteral.element.enclosingClass; |
| 2959 backend.rti.registerClassUsingTypeVariableExpression(cls); | 2954 backend.rti.registerClassUsingTypeVariableExpression(cls); |
| 2960 registerBackendImpact(transformed, impacts.typeVariableExpression); | 2955 registerBackendImpact(transformed, impacts.typeVariableExpression); |
| 2961 } | 2956 } |
| 2962 } | 2957 } |
| 2963 } | 2958 } |
| 2964 | 2959 |
| 2965 for (String constSymbolName in worldImpact.constSymbolNames) { | 2960 if (worldImpact.constSymbolNames.isNotEmpty) { |
| 2966 backend.registerConstSymbol(constSymbolName); | 2961 registerBackendImpact(transformed, impacts.constSymbol); |
| 2962 for (String constSymbolName in worldImpact.constSymbolNames) { |
| 2963 backend.registerConstSymbol(constSymbolName); |
| 2964 } |
| 2967 } | 2965 } |
| 2968 | 2966 |
| 2969 for (LocalFunctionElement closure in worldImpact.closures) { | 2967 if (worldImpact.closures.isNotEmpty) { |
| 2970 if (closure.computeType(backend.resolution).containsTypeVariables) { | 2968 registerBackendImpact(transformed, impacts.closure); |
| 2971 backend.compiler.enqueuer.resolution.universe | 2969 for (LocalFunctionElement closure in worldImpact.closures) { |
| 2972 .closuresWithFreeTypeVariables.add(closure); | 2970 if (closure.computeType(backend.resolution).containsTypeVariables) { |
| 2973 registerBackendImpact(transformed, impacts.computeSignature); | 2971 backend.compiler.enqueuer.resolution.universe |
| 2972 .closuresWithFreeTypeVariables.add(closure); |
| 2973 registerBackendImpact(transformed, impacts.computeSignature); |
| 2974 } |
| 2974 } | 2975 } |
| 2975 } | 2976 } |
| 2977 |
| 2976 return transformed; | 2978 return transformed; |
| 2977 } | 2979 } |
| 2978 | 2980 |
| 2979 void registerBackendImpact(TransformedWorldImpact worldImpact, | 2981 void registerBackendImpact(TransformedWorldImpact worldImpact, |
| 2980 BackendImpact backendImpact) { | 2982 BackendImpact backendImpact) { |
| 2981 for (Element staticUse in backendImpact.staticUses) { | 2983 for (Element staticUse in backendImpact.staticUses) { |
| 2982 assert(staticUse != null); | 2984 assert(staticUse != null); |
| 2983 backend.registerBackendUse(staticUse); | 2985 backend.registerBackendUse(staticUse); |
| 2984 worldImpact.registerStaticUse(staticUse); | 2986 worldImpact.registerStaticUse(staticUse); |
| 2985 } | 2987 } |
| 2986 for (InterfaceType instantiatedType in backendImpact.instantiatedTypes) { | 2988 for (InterfaceType instantiatedType in backendImpact.instantiatedTypes) { |
| 2987 backend.registerBackendUse(instantiatedType.element); | 2989 backend.registerBackendUse(instantiatedType.element); |
| 2988 worldImpact.registerInstantiatedType(instantiatedType); | 2990 worldImpact.registerInstantiatedType(instantiatedType); |
| 2989 } | 2991 } |
| 2990 for (ClassElement cls in backendImpact.instantiatedClasses) { | 2992 for (ClassElement cls in backendImpact.instantiatedClasses) { |
| 2991 cls.ensureResolved(backend.resolution); | 2993 cls.ensureResolved(backend.resolution); |
| 2992 backend.registerBackendUse(cls); | 2994 backend.registerBackendUse(cls); |
| 2993 worldImpact.registerInstantiatedType(cls.rawType); | 2995 worldImpact.registerInstantiatedType(cls.rawType); |
| 2994 } | 2996 } |
| 2995 for (BackendImpact otherImpact in backendImpact.otherImpacts) { | 2997 for (BackendImpact otherImpact in backendImpact.otherImpacts) { |
| 2996 registerBackendImpact(worldImpact, otherImpact); | 2998 registerBackendImpact(worldImpact, otherImpact); |
| 2997 } | 2999 } |
| 2998 } | 3000 } |
| 2999 | 3001 |
| 3002 /// Register [type] as required for the runtime type information system. |
| 3003 void registerRequiredType(DartType type) { |
| 3004 // If [argument] has type variables or is a type variable, this method |
| 3005 // registers a RTI dependency between the class where the type variable is |
| 3006 // defined (that is the enclosing class of the current element being |
| 3007 // resolved) and the class of [type]. If the class of [type] requires RTI, |
| 3008 // then the class of the type variable does too. |
| 3009 ClassElement contextClass = Types.getClassContext(type); |
| 3010 if (contextClass != null) { |
| 3011 backend.rti.registerRtiDependency(type.element, contextClass); |
| 3012 } |
| 3013 } |
| 3014 |
| 3000 // TODO(johnniwinther): Maybe split this into [onAssertType] and [onTestType]. | 3015 // TODO(johnniwinther): Maybe split this into [onAssertType] and [onTestType]. |
| 3001 void onIsCheck(DartType type, TransformedWorldImpact transformed) { | 3016 void onIsCheck(DartType type, TransformedWorldImpact transformed) { |
| 3017 registerRequiredType(type); |
| 3002 type.computeUnaliased(backend.resolution); | 3018 type.computeUnaliased(backend.resolution); |
| 3003 type = type.unaliased; | 3019 type = type.unaliased; |
| 3004 registerBackendImpact(transformed, impacts.typeCheck); | 3020 registerBackendImpact(transformed, impacts.typeCheck); |
| 3005 | 3021 |
| 3006 bool inCheckedMode = backend.compiler.enableTypeAssertions; | 3022 bool inCheckedMode = backend.compiler.enableTypeAssertions; |
| 3007 if (inCheckedMode) { | 3023 if (inCheckedMode) { |
| 3008 registerBackendImpact(transformed, impacts.checkedModeTypeCheck); | 3024 registerBackendImpact(transformed, impacts.checkedModeTypeCheck); |
| 3009 } | 3025 } |
| 3010 if (type.isMalformed) { | 3026 if (type.isMalformed) { |
| 3011 registerBackendImpact(transformed, impacts.malformedTypeCheck); | 3027 registerBackendImpact(transformed, impacts.malformedTypeCheck); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3033 } | 3049 } |
| 3034 | 3050 |
| 3035 /// Records that [constant] is used by the element behind [registry]. | 3051 /// Records that [constant] is used by the element behind [registry]. |
| 3036 class Dependency { | 3052 class Dependency { |
| 3037 final ConstantValue constant; | 3053 final ConstantValue constant; |
| 3038 final Element annotatedElement; | 3054 final Element annotatedElement; |
| 3039 | 3055 |
| 3040 const Dependency(this.constant, this.annotatedElement); | 3056 const Dependency(this.constant, this.annotatedElement); |
| 3041 } | 3057 } |
| 3042 | 3058 |
| OLD | NEW |