OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 library js_backend.backend.impact_transformer; | 5 library js_backend.backend.impact_transformer; |
6 | 6 |
7 import '../common.dart'; | 7 import '../common.dart'; |
| 8 import '../common_elements.dart'; |
8 import '../common/backend_api.dart' show ImpactTransformer; | 9 import '../common/backend_api.dart' show ImpactTransformer; |
9 import '../common/codegen.dart' show CodegenImpact; | 10 import '../common/codegen.dart' show CodegenImpact; |
10 import '../common/resolution.dart' show ResolutionImpact; | 11 import '../common/resolution.dart' show Resolution, ResolutionImpact; |
11 import '../constants/expressions.dart'; | 12 import '../constants/expressions.dart'; |
12 import '../constants/values.dart'; | 13 import '../constants/values.dart'; |
13 import '../common_elements.dart' show ElementEnvironment; | 14 import '../common_elements.dart' show ElementEnvironment; |
14 import '../elements/elements.dart'; | 15 import '../elements/elements.dart'; |
15 import '../elements/resolution_types.dart'; | 16 import '../elements/resolution_types.dart'; |
16 import '../enqueue.dart' show ResolutionEnqueuer; | 17 import '../enqueue.dart' show ResolutionEnqueuer; |
| 18 import '../native/enqueue.dart'; |
17 import '../native/native.dart' as native; | 19 import '../native/native.dart' as native; |
| 20 import '../options.dart'; |
18 import '../universe/feature.dart'; | 21 import '../universe/feature.dart'; |
19 import '../universe/use.dart' | 22 import '../universe/use.dart' |
20 show StaticUse, StaticUseKind, TypeUse, TypeUseKind; | 23 show StaticUse, StaticUseKind, TypeUse, TypeUseKind; |
21 import '../universe/world_impact.dart' show TransformedWorldImpact, WorldImpact; | 24 import '../universe/world_impact.dart' show TransformedWorldImpact, WorldImpact; |
22 import '../util/util.dart'; | 25 import '../util/util.dart'; |
23 import 'backend.dart'; | 26 import 'backend.dart'; |
| 27 import 'backend_helpers.dart'; |
24 import 'backend_impact.dart'; | 28 import 'backend_impact.dart'; |
25 import 'backend_usage.dart'; | 29 import 'backend_usage.dart'; |
26 import 'checked_mode_helpers.dart'; | 30 import 'checked_mode_helpers.dart'; |
| 31 import 'custom_elements_analysis.dart'; |
| 32 import 'interceptor_data.dart'; |
| 33 import 'lookup_map_analysis.dart'; |
| 34 import 'mirrors_data.dart'; |
| 35 import 'namer.dart'; |
| 36 import 'native_data.dart'; |
27 | 37 |
28 class JavaScriptImpactTransformer extends ImpactTransformer { | 38 class JavaScriptImpactTransformer extends ImpactTransformer { |
29 final JavaScriptBackend backend; | 39 final CompilerOptions _options; |
| 40 final Resolution _resolution; |
| 41 final ElementEnvironment _elementEnvironment; |
| 42 final CommonElements _commonElements; |
| 43 final BackendImpacts _impacts; |
| 44 final NativeClassData _nativeClassData; |
| 45 final NativeResolutionEnqueuer _nativeResolutionEnqueuer; |
| 46 final BackendUsageBuilder _backendUsageBuider; |
| 47 final MirrorsData _mirrorsData; |
| 48 final CustomElementsResolutionAnalysis _customElementsResolutionAnalysis; |
| 49 final RuntimeTypesNeedBuilder _rtiNeedBuilder; |
30 | 50 |
31 JavaScriptImpactTransformer(this.backend); | 51 JavaScriptImpactTransformer( |
32 | 52 this._options, |
33 BackendImpacts get impacts => backend.impacts; | 53 this._resolution, |
34 | 54 this._elementEnvironment, |
35 ElementEnvironment get elementEnvironment => | 55 this._commonElements, |
36 backend.compiler.elementEnvironment; | 56 this._impacts, |
| 57 this._nativeClassData, |
| 58 this._nativeResolutionEnqueuer, |
| 59 this._backendUsageBuider, |
| 60 this._mirrorsData, |
| 61 this._customElementsResolutionAnalysis, |
| 62 this._rtiNeedBuilder); |
37 | 63 |
38 @override | 64 @override |
39 WorldImpact transformResolutionImpact( | 65 WorldImpact transformResolutionImpact( |
40 ResolutionEnqueuer enqueuer, ResolutionImpact worldImpact) { | 66 ResolutionEnqueuer enqueuer, ResolutionImpact worldImpact) { |
41 BackendUsageBuilder backendUsage = backend.backendUsageBuilder; | |
42 TransformedWorldImpact transformed = | 67 TransformedWorldImpact transformed = |
43 new TransformedWorldImpact(worldImpact); | 68 new TransformedWorldImpact(worldImpact); |
44 | 69 |
45 void registerImpact(BackendImpact impact) { | 70 void registerImpact(BackendImpact impact) { |
46 impact.registerImpact(transformed, elementEnvironment); | 71 impact.registerImpact(transformed, _elementEnvironment); |
47 backendUsage.processBackendImpact(impact); | 72 _backendUsageBuider.processBackendImpact(impact); |
48 } | 73 } |
49 | 74 |
50 for (Feature feature in worldImpact.features) { | 75 for (Feature feature in worldImpact.features) { |
51 switch (feature) { | 76 switch (feature) { |
52 case Feature.ABSTRACT_CLASS_INSTANTIATION: | 77 case Feature.ABSTRACT_CLASS_INSTANTIATION: |
53 registerImpact(impacts.abstractClassInstantiation); | 78 registerImpact(_impacts.abstractClassInstantiation); |
54 break; | 79 break; |
55 case Feature.ASSERT: | 80 case Feature.ASSERT: |
56 registerImpact(impacts.assertWithoutMessage); | 81 registerImpact(_impacts.assertWithoutMessage); |
57 break; | 82 break; |
58 case Feature.ASSERT_WITH_MESSAGE: | 83 case Feature.ASSERT_WITH_MESSAGE: |
59 registerImpact(impacts.assertWithMessage); | 84 registerImpact(_impacts.assertWithMessage); |
60 break; | 85 break; |
61 case Feature.ASYNC: | 86 case Feature.ASYNC: |
62 registerImpact(impacts.asyncBody); | 87 registerImpact(_impacts.asyncBody); |
63 break; | 88 break; |
64 case Feature.ASYNC_FOR_IN: | 89 case Feature.ASYNC_FOR_IN: |
65 registerImpact(impacts.asyncForIn); | 90 registerImpact(_impacts.asyncForIn); |
66 break; | 91 break; |
67 case Feature.ASYNC_STAR: | 92 case Feature.ASYNC_STAR: |
68 registerImpact(impacts.asyncStarBody); | 93 registerImpact(_impacts.asyncStarBody); |
69 break; | 94 break; |
70 case Feature.CATCH_STATEMENT: | 95 case Feature.CATCH_STATEMENT: |
71 registerImpact(impacts.catchStatement); | 96 registerImpact(_impacts.catchStatement); |
72 break; | 97 break; |
73 case Feature.COMPILE_TIME_ERROR: | 98 case Feature.COMPILE_TIME_ERROR: |
74 if (backend.compiler.options.generateCodeWithCompileTimeErrors) { | 99 if (_options.generateCodeWithCompileTimeErrors) { |
75 // TODO(johnniwinther): This should have its own uncatchable error. | 100 // TODO(johnniwinther): This should have its own uncatchable error. |
76 registerImpact(impacts.throwRuntimeError); | 101 registerImpact(_impacts.throwRuntimeError); |
77 } | 102 } |
78 break; | 103 break; |
79 case Feature.FALL_THROUGH_ERROR: | 104 case Feature.FALL_THROUGH_ERROR: |
80 registerImpact(impacts.fallThroughError); | 105 registerImpact(_impacts.fallThroughError); |
81 break; | 106 break; |
82 case Feature.FIELD_WITHOUT_INITIALIZER: | 107 case Feature.FIELD_WITHOUT_INITIALIZER: |
83 case Feature.LOCAL_WITHOUT_INITIALIZER: | 108 case Feature.LOCAL_WITHOUT_INITIALIZER: |
84 transformed.registerTypeUse( | 109 transformed.registerTypeUse( |
85 new TypeUse.instantiation(backend.commonElements.nullType)); | 110 new TypeUse.instantiation(_commonElements.nullType)); |
86 registerImpact(impacts.nullLiteral); | 111 registerImpact(_impacts.nullLiteral); |
87 break; | 112 break; |
88 case Feature.LAZY_FIELD: | 113 case Feature.LAZY_FIELD: |
89 registerImpact(impacts.lazyField); | 114 registerImpact(_impacts.lazyField); |
90 break; | 115 break; |
91 case Feature.STACK_TRACE_IN_CATCH: | 116 case Feature.STACK_TRACE_IN_CATCH: |
92 registerImpact(impacts.stackTraceInCatch); | 117 registerImpact(_impacts.stackTraceInCatch); |
93 break; | 118 break; |
94 case Feature.STRING_INTERPOLATION: | 119 case Feature.STRING_INTERPOLATION: |
95 registerImpact(impacts.stringInterpolation); | 120 registerImpact(_impacts.stringInterpolation); |
96 break; | 121 break; |
97 case Feature.STRING_JUXTAPOSITION: | 122 case Feature.STRING_JUXTAPOSITION: |
98 registerImpact(impacts.stringJuxtaposition); | 123 registerImpact(_impacts.stringJuxtaposition); |
99 break; | 124 break; |
100 case Feature.SUPER_NO_SUCH_METHOD: | 125 case Feature.SUPER_NO_SUCH_METHOD: |
101 registerImpact(impacts.superNoSuchMethod); | 126 registerImpact(_impacts.superNoSuchMethod); |
102 break; | 127 break; |
103 case Feature.SYMBOL_CONSTRUCTOR: | 128 case Feature.SYMBOL_CONSTRUCTOR: |
104 registerImpact(impacts.symbolConstructor); | 129 registerImpact(_impacts.symbolConstructor); |
105 break; | 130 break; |
106 case Feature.SYNC_FOR_IN: | 131 case Feature.SYNC_FOR_IN: |
107 registerImpact(impacts.syncForIn); | 132 registerImpact(_impacts.syncForIn); |
108 break; | 133 break; |
109 case Feature.SYNC_STAR: | 134 case Feature.SYNC_STAR: |
110 registerImpact(impacts.syncStarBody); | 135 registerImpact(_impacts.syncStarBody); |
111 break; | 136 break; |
112 case Feature.THROW_EXPRESSION: | 137 case Feature.THROW_EXPRESSION: |
113 registerImpact(impacts.throwExpression); | 138 registerImpact(_impacts.throwExpression); |
114 break; | 139 break; |
115 case Feature.THROW_NO_SUCH_METHOD: | 140 case Feature.THROW_NO_SUCH_METHOD: |
116 registerImpact(impacts.throwNoSuchMethod); | 141 registerImpact(_impacts.throwNoSuchMethod); |
117 break; | 142 break; |
118 case Feature.THROW_RUNTIME_ERROR: | 143 case Feature.THROW_RUNTIME_ERROR: |
119 registerImpact(impacts.throwRuntimeError); | 144 registerImpact(_impacts.throwRuntimeError); |
120 break; | 145 break; |
121 case Feature.TYPE_VARIABLE_BOUNDS_CHECK: | 146 case Feature.TYPE_VARIABLE_BOUNDS_CHECK: |
122 registerImpact(impacts.typeVariableBoundCheck); | 147 registerImpact(_impacts.typeVariableBoundCheck); |
123 break; | 148 break; |
124 } | 149 } |
125 } | 150 } |
126 | 151 |
127 bool hasAsCast = false; | 152 bool hasAsCast = false; |
128 bool hasTypeLiteral = false; | 153 bool hasTypeLiteral = false; |
129 for (TypeUse typeUse in worldImpact.typeUses) { | 154 for (TypeUse typeUse in worldImpact.typeUses) { |
130 ResolutionDartType type = typeUse.type; | 155 ResolutionDartType type = typeUse.type; |
131 switch (typeUse.kind) { | 156 switch (typeUse.kind) { |
132 case TypeUseKind.INSTANTIATION: | 157 case TypeUseKind.INSTANTIATION: |
133 case TypeUseKind.MIRROR_INSTANTIATION: | 158 case TypeUseKind.MIRROR_INSTANTIATION: |
134 case TypeUseKind.NATIVE_INSTANTIATION: | 159 case TypeUseKind.NATIVE_INSTANTIATION: |
135 registerRequiredType(type); | 160 registerRequiredType(type); |
136 break; | 161 break; |
137 case TypeUseKind.IS_CHECK: | 162 case TypeUseKind.IS_CHECK: |
138 onIsCheck(type, transformed); | 163 onIsCheck(type, transformed); |
139 break; | 164 break; |
140 case TypeUseKind.AS_CAST: | 165 case TypeUseKind.AS_CAST: |
141 onIsCheck(type, transformed); | 166 onIsCheck(type, transformed); |
142 hasAsCast = true; | 167 hasAsCast = true; |
143 break; | 168 break; |
144 case TypeUseKind.CHECKED_MODE_CHECK: | 169 case TypeUseKind.CHECKED_MODE_CHECK: |
145 if (backend.compiler.options.enableTypeAssertions) { | 170 if (_options.enableTypeAssertions) { |
146 onIsCheck(type, transformed); | 171 onIsCheck(type, transformed); |
147 } | 172 } |
148 break; | 173 break; |
149 case TypeUseKind.CATCH_TYPE: | 174 case TypeUseKind.CATCH_TYPE: |
150 onIsCheck(type, transformed); | 175 onIsCheck(type, transformed); |
151 break; | 176 break; |
152 case TypeUseKind.TYPE_LITERAL: | 177 case TypeUseKind.TYPE_LITERAL: |
153 backend.customElementsResolutionAnalysis.registerTypeLiteral(type); | 178 _customElementsResolutionAnalysis.registerTypeLiteral(type); |
154 if (type.isTypeVariable && type is! MethodTypeVariableType) { | 179 if (type.isTypeVariable && type is! MethodTypeVariableType) { |
155 // GENERIC_METHODS: The `is!` test above filters away method type | 180 // GENERIC_METHODS: The `is!` test above filters away method type |
156 // variables, because they have the value `dynamic` with the | 181 // variables, because they have the value `dynamic` with the |
157 // incomplete support for generic methods offered with | 182 // incomplete support for generic methods offered with |
158 // '--generic-method-syntax'. This must be revised in order to | 183 // '--generic-method-syntax'. This must be revised in order to |
159 // support generic methods fully. | 184 // support generic methods fully. |
160 ClassElement cls = type.element.enclosingClass; | 185 ClassElement cls = type.element.enclosingClass; |
161 backend.rtiNeedBuilder | 186 _rtiNeedBuilder.registerClassUsingTypeVariableExpression(cls); |
162 .registerClassUsingTypeVariableExpression(cls); | 187 registerImpact(_impacts.typeVariableExpression); |
163 registerImpact(impacts.typeVariableExpression); | |
164 } | 188 } |
165 hasTypeLiteral = true; | 189 hasTypeLiteral = true; |
166 break; | 190 break; |
167 } | 191 } |
168 } | 192 } |
169 | 193 |
170 if (hasAsCast) { | 194 if (hasAsCast) { |
171 registerImpact(impacts.asCheck); | 195 registerImpact(_impacts.asCheck); |
172 } | 196 } |
173 | 197 |
174 if (hasTypeLiteral) { | 198 if (hasTypeLiteral) { |
175 transformed.registerTypeUse( | 199 transformed |
176 new TypeUse.instantiation(backend.compiler.commonElements.typeType)); | 200 .registerTypeUse(new TypeUse.instantiation(_commonElements.typeType)); |
177 registerImpact(impacts.typeLiteral); | 201 registerImpact(_impacts.typeLiteral); |
178 } | 202 } |
179 | 203 |
180 for (MapLiteralUse mapLiteralUse in worldImpact.mapLiterals) { | 204 for (MapLiteralUse mapLiteralUse in worldImpact.mapLiterals) { |
181 // TODO(johnniwinther): Use the [isEmpty] property when factory | 205 // TODO(johnniwinther): Use the [isEmpty] property when factory |
182 // constructors are registered directly. | 206 // constructors are registered directly. |
183 if (mapLiteralUse.isConstant) { | 207 if (mapLiteralUse.isConstant) { |
184 registerImpact(impacts.constantMapLiteral); | 208 registerImpact(_impacts.constantMapLiteral); |
185 } else { | 209 } else { |
186 transformed | 210 transformed |
187 .registerTypeUse(new TypeUse.instantiation(mapLiteralUse.type)); | 211 .registerTypeUse(new TypeUse.instantiation(mapLiteralUse.type)); |
188 } | 212 } |
189 ResolutionInterfaceType type = mapLiteralUse.type; | 213 ResolutionInterfaceType type = mapLiteralUse.type; |
190 registerRequiredType(type); | 214 registerRequiredType(type); |
191 } | 215 } |
192 | 216 |
193 for (ListLiteralUse listLiteralUse in worldImpact.listLiterals) { | 217 for (ListLiteralUse listLiteralUse in worldImpact.listLiterals) { |
194 // TODO(johnniwinther): Use the [isConstant] and [isEmpty] property when | 218 // TODO(johnniwinther): Use the [isConstant] and [isEmpty] property when |
195 // factory constructors are registered directly. | 219 // factory constructors are registered directly. |
196 transformed | 220 transformed |
197 .registerTypeUse(new TypeUse.instantiation(listLiteralUse.type)); | 221 .registerTypeUse(new TypeUse.instantiation(listLiteralUse.type)); |
198 ResolutionInterfaceType type = listLiteralUse.type; | 222 ResolutionInterfaceType type = listLiteralUse.type; |
199 registerRequiredType(type); | 223 registerRequiredType(type); |
200 } | 224 } |
201 | 225 |
202 if (worldImpact.constSymbolNames.isNotEmpty) { | 226 if (worldImpact.constSymbolNames.isNotEmpty) { |
203 registerImpact(impacts.constSymbol); | 227 registerImpact(_impacts.constSymbol); |
204 for (String constSymbolName in worldImpact.constSymbolNames) { | 228 for (String constSymbolName in worldImpact.constSymbolNames) { |
205 backend.mirrorsData.registerConstSymbol(constSymbolName); | 229 _mirrorsData.registerConstSymbol(constSymbolName); |
206 } | 230 } |
207 } | 231 } |
208 | 232 |
209 for (StaticUse staticUse in worldImpact.staticUses) { | 233 for (StaticUse staticUse in worldImpact.staticUses) { |
210 switch (staticUse.kind) { | 234 switch (staticUse.kind) { |
211 case StaticUseKind.CLOSURE: | 235 case StaticUseKind.CLOSURE: |
212 registerImpact(impacts.closure); | 236 registerImpact(_impacts.closure); |
213 LocalFunctionElement closure = staticUse.element; | 237 LocalFunctionElement closure = staticUse.element; |
214 if (closure.type.containsTypeVariables) { | 238 if (closure.type.containsTypeVariables) { |
215 registerImpact(impacts.computeSignature); | 239 registerImpact(_impacts.computeSignature); |
216 } | 240 } |
217 break; | 241 break; |
218 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: | 242 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: |
219 case StaticUseKind.CONSTRUCTOR_INVOKE: | 243 case StaticUseKind.CONSTRUCTOR_INVOKE: |
220 registerRequiredType(staticUse.type); | 244 registerRequiredType(staticUse.type); |
221 break; | 245 break; |
222 default: | 246 default: |
223 } | 247 } |
224 } | 248 } |
225 | 249 |
226 for (ConstantExpression constant in worldImpact.constantLiterals) { | 250 for (ConstantExpression constant in worldImpact.constantLiterals) { |
227 switch (constant.kind) { | 251 switch (constant.kind) { |
228 case ConstantExpressionKind.NULL: | 252 case ConstantExpressionKind.NULL: |
229 registerImpact(impacts.nullLiteral); | 253 registerImpact(_impacts.nullLiteral); |
230 break; | 254 break; |
231 case ConstantExpressionKind.BOOL: | 255 case ConstantExpressionKind.BOOL: |
232 registerImpact(impacts.boolLiteral); | 256 registerImpact(_impacts.boolLiteral); |
233 break; | 257 break; |
234 case ConstantExpressionKind.INT: | 258 case ConstantExpressionKind.INT: |
235 registerImpact(impacts.intLiteral); | 259 registerImpact(_impacts.intLiteral); |
236 break; | 260 break; |
237 case ConstantExpressionKind.DOUBLE: | 261 case ConstantExpressionKind.DOUBLE: |
238 registerImpact(impacts.doubleLiteral); | 262 registerImpact(_impacts.doubleLiteral); |
239 break; | 263 break; |
240 case ConstantExpressionKind.STRING: | 264 case ConstantExpressionKind.STRING: |
241 registerImpact(impacts.stringLiteral); | 265 registerImpact(_impacts.stringLiteral); |
242 break; | 266 break; |
243 default: | 267 default: |
244 assert(invariant(NO_LOCATION_SPANNABLE, false, | 268 assert(invariant(NO_LOCATION_SPANNABLE, false, |
245 message: "Unexpected constant literal: ${constant.kind}.")); | 269 message: "Unexpected constant literal: ${constant.kind}.")); |
246 } | 270 } |
247 } | 271 } |
248 | 272 |
249 for (native.NativeBehavior behavior in worldImpact.nativeData) { | 273 for (native.NativeBehavior behavior in worldImpact.nativeData) { |
250 backend.nativeResolutionEnqueuer | 274 _nativeResolutionEnqueuer.registerNativeBehavior( |
251 .registerNativeBehavior(transformed, behavior, worldImpact); | 275 transformed, behavior, worldImpact); |
252 } | 276 } |
253 | 277 |
254 return transformed; | 278 return transformed; |
255 } | 279 } |
256 | 280 |
257 /// Register [type] as required for the runtime type information system. | 281 /// Register [type] as required for the runtime type information system. |
258 void registerRequiredType(ResolutionDartType type) { | 282 void registerRequiredType(ResolutionDartType type) { |
259 if (!type.isInterfaceType) return; | 283 if (!type.isInterfaceType) return; |
260 // If [argument] has type variables or is a type variable, this method | 284 // If [argument] has type variables or is a type variable, this method |
261 // registers a RTI dependency between the class where the type variable is | 285 // registers a RTI dependency between the class where the type variable is |
262 // defined (that is the enclosing class of the current element being | 286 // defined (that is the enclosing class of the current element being |
263 // resolved) and the class of [type]. If the class of [type] requires RTI, | 287 // resolved) and the class of [type]. If the class of [type] requires RTI, |
264 // then the class of the type variable does too. | 288 // then the class of the type variable does too. |
265 ClassElement contextClass = Types.getClassContext(type); | 289 ClassElement contextClass = Types.getClassContext(type); |
266 if (contextClass != null) { | 290 if (contextClass != null) { |
267 backend.rtiNeedBuilder.registerRtiDependency(type.element, contextClass); | 291 _rtiNeedBuilder.registerRtiDependency(type.element, contextClass); |
268 } | 292 } |
269 } | 293 } |
270 | 294 |
271 // TODO(johnniwinther): Maybe split this into [onAssertType] and [onTestType]. | 295 // TODO(johnniwinther): Maybe split this into [onAssertType] and [onTestType]. |
272 void onIsCheck(ResolutionDartType type, TransformedWorldImpact transformed) { | 296 void onIsCheck(ResolutionDartType type, TransformedWorldImpact transformed) { |
273 BackendUsageBuilder backendUsage = backend.backendUsageBuilder; | |
274 | |
275 void registerImpact(BackendImpact impact) { | 297 void registerImpact(BackendImpact impact) { |
276 impact.registerImpact(transformed, elementEnvironment); | 298 impact.registerImpact(transformed, _elementEnvironment); |
277 backendUsage.processBackendImpact(impact); | 299 _backendUsageBuider.processBackendImpact(impact); |
278 } | 300 } |
279 | 301 |
280 registerRequiredType(type); | 302 registerRequiredType(type); |
281 type.computeUnaliased(backend.resolution); | 303 type.computeUnaliased(_resolution); |
282 type = type.unaliased; | 304 type = type.unaliased; |
283 registerImpact(impacts.typeCheck); | 305 registerImpact(_impacts.typeCheck); |
284 | 306 |
285 bool inCheckedMode = backend.compiler.options.enableTypeAssertions; | 307 bool inCheckedMode = _options.enableTypeAssertions; |
286 if (inCheckedMode) { | 308 if (inCheckedMode) { |
287 registerImpact(impacts.checkedModeTypeCheck); | 309 registerImpact(_impacts.checkedModeTypeCheck); |
288 } | 310 } |
289 if (type.isMalformed) { | 311 if (type.isMalformed) { |
290 registerImpact(impacts.malformedTypeCheck); | 312 registerImpact(_impacts.malformedTypeCheck); |
291 } | 313 } |
292 if (!type.treatAsRaw || type.containsTypeVariables || type.isFunctionType) { | 314 if (!type.treatAsRaw || type.containsTypeVariables || type.isFunctionType) { |
293 registerImpact(impacts.genericTypeCheck); | 315 registerImpact(_impacts.genericTypeCheck); |
294 if (inCheckedMode) { | 316 if (inCheckedMode) { |
295 registerImpact(impacts.genericCheckedModeTypeCheck); | 317 registerImpact(_impacts.genericCheckedModeTypeCheck); |
296 } | 318 } |
297 if (type.isTypeVariable) { | 319 if (type.isTypeVariable) { |
298 registerImpact(impacts.typeVariableTypeCheck); | 320 registerImpact(_impacts.typeVariableTypeCheck); |
299 if (inCheckedMode) { | 321 if (inCheckedMode) { |
300 registerImpact(impacts.typeVariableCheckedModeTypeCheck); | 322 registerImpact(_impacts.typeVariableCheckedModeTypeCheck); |
301 } | 323 } |
302 } | 324 } |
303 } | 325 } |
304 if (type is ResolutionFunctionType) { | 326 if (type is ResolutionFunctionType) { |
305 registerImpact(impacts.functionTypeCheck); | 327 registerImpact(_impacts.functionTypeCheck); |
306 } | 328 } |
307 if (type is ResolutionInterfaceType && | 329 if (type is ResolutionInterfaceType && |
308 backend.nativeClassData.isNativeClass(type.element)) { | 330 _nativeClassData.isNativeClass(type.element)) { |
309 registerImpact(impacts.nativeTypeCheck); | 331 registerImpact(_impacts.nativeTypeCheck); |
310 } | 332 } |
311 } | 333 } |
| 334 } |
| 335 |
| 336 class CodegenImpactTransformer { |
| 337 // TODO(johnniwinther): Remove the need for this. |
| 338 final JavaScriptBackend _backend; |
| 339 |
| 340 final CompilerOptions _options; |
| 341 final ElementEnvironment _elementEnvironment; |
| 342 final BackendHelpers _helpers; |
| 343 final BackendImpacts _impacts; |
| 344 final CheckedModeHelpers _checkedModeHelpers; |
| 345 final NativeData _nativeData; |
| 346 final RuntimeTypesNeed _rtiNeed; |
| 347 final NativeCodegenEnqueuer _nativeCodegenEnqueuer; |
| 348 final Namer _namer; |
| 349 final MirrorsData _mirrorsData; |
| 350 final OneShotInterceptorData _oneShotInterceptorData; |
| 351 final LookupMapAnalysis _lookupMapAnalysis; |
| 352 final CustomElementsCodegenAnalysis _customElementsCodegenAnalysis; |
| 353 |
| 354 CodegenImpactTransformer( |
| 355 this._backend, |
| 356 this._options, |
| 357 this._elementEnvironment, |
| 358 this._helpers, |
| 359 this._impacts, |
| 360 this._checkedModeHelpers, |
| 361 this._nativeData, |
| 362 this._rtiNeed, |
| 363 this._nativeCodegenEnqueuer, |
| 364 this._namer, |
| 365 this._mirrorsData, |
| 366 this._oneShotInterceptorData, |
| 367 this._lookupMapAnalysis, |
| 368 this._customElementsCodegenAnalysis); |
312 | 369 |
313 void onIsCheckForCodegen( | 370 void onIsCheckForCodegen( |
314 ResolutionDartType type, TransformedWorldImpact transformed) { | 371 ResolutionDartType type, TransformedWorldImpact transformed) { |
315 if (type.isDynamic) return; | 372 if (type.isDynamic) return; |
316 type = type.unaliased; | 373 type = type.unaliased; |
317 impacts.typeCheck.registerImpact(transformed, elementEnvironment); | 374 _impacts.typeCheck.registerImpact(transformed, _elementEnvironment); |
318 | 375 |
319 bool inCheckedMode = backend.compiler.options.enableTypeAssertions; | 376 bool inCheckedMode = _options.enableTypeAssertions; |
320 // [registerIsCheck] is also called for checked mode checks, so we | 377 // [registerIsCheck] is also called for checked mode checks, so we |
321 // need to register checked mode helpers. | 378 // need to register checked mode helpers. |
322 if (inCheckedMode) { | 379 if (inCheckedMode) { |
323 // All helpers are added to resolution queue in enqueueHelpers. These | 380 // All helpers are added to resolution queue in enqueueHelpers. These |
324 // calls to [enqueue] with the resolution enqueuer serve as assertions | 381 // calls to [enqueue] with the resolution enqueuer serve as assertions |
325 // that the helper was in fact added. | 382 // that the helper was in fact added. |
326 // TODO(13155): Find a way to enqueue helpers lazily. | 383 // TODO(13155): Find a way to enqueue helpers lazily. |
327 CheckedModeHelper helper = backend.checkedModeHelpers | 384 CheckedModeHelper helper = |
328 .getCheckedModeHelper(type, typeCast: false); | 385 _checkedModeHelpers.getCheckedModeHelper(type, typeCast: false); |
329 if (helper != null) { | 386 if (helper != null) { |
330 StaticUse staticUse = helper.getStaticUse(backend.helpers); | 387 StaticUse staticUse = helper.getStaticUse(_helpers); |
331 transformed.registerStaticUse(staticUse); | 388 transformed.registerStaticUse(staticUse); |
332 } | 389 } |
333 // We also need the native variant of the check (for DOM types). | 390 // We also need the native variant of the check (for DOM types). |
334 helper = backend.checkedModeHelpers | 391 helper = |
335 .getNativeCheckedModeHelper(type, typeCast: false); | 392 _checkedModeHelpers.getNativeCheckedModeHelper(type, typeCast: false); |
336 if (helper != null) { | 393 if (helper != null) { |
337 StaticUse staticUse = helper.getStaticUse(backend.helpers); | 394 StaticUse staticUse = helper.getStaticUse(_helpers); |
338 transformed.registerStaticUse(staticUse); | 395 transformed.registerStaticUse(staticUse); |
339 } | 396 } |
340 } | 397 } |
341 if (!type.treatAsRaw || type.containsTypeVariables) { | 398 if (!type.treatAsRaw || type.containsTypeVariables) { |
342 impacts.genericIsCheck.registerImpact(transformed, elementEnvironment); | 399 _impacts.genericIsCheck.registerImpact(transformed, _elementEnvironment); |
343 } | 400 } |
344 if (type is ResolutionInterfaceType && | 401 if (type is ResolutionInterfaceType && |
345 backend.nativeData.isNativeClass(type.element)) { | 402 _nativeData.isNativeClass(type.element)) { |
346 // We will neeed to add the "$is" and "$as" properties on the | 403 // We will neeed to add the "$is" and "$as" properties on the |
347 // JavaScript object prototype, so we make sure | 404 // JavaScript object prototype, so we make sure |
348 // [:defineProperty:] is compiled. | 405 // [:defineProperty:] is compiled. |
349 impacts.nativeTypeCheck.registerImpact(transformed, elementEnvironment); | 406 _impacts.nativeTypeCheck.registerImpact(transformed, _elementEnvironment); |
350 } | 407 } |
351 } | 408 } |
352 | 409 |
353 @override | 410 @override |
354 WorldImpact transformCodegenImpact(CodegenImpact impact) { | 411 WorldImpact transformCodegenImpact(CodegenImpact impact) { |
355 TransformedWorldImpact transformed = new TransformedWorldImpact(impact); | 412 TransformedWorldImpact transformed = new TransformedWorldImpact(impact); |
356 | 413 |
357 for (TypeUse typeUse in impact.typeUses) { | 414 for (TypeUse typeUse in impact.typeUses) { |
358 ResolutionDartType type = typeUse.type; | 415 ResolutionDartType type = typeUse.type; |
359 switch (typeUse.kind) { | 416 switch (typeUse.kind) { |
360 case TypeUseKind.INSTANTIATION: | 417 case TypeUseKind.INSTANTIATION: |
361 backend.lookupMapAnalysis.registerInstantiatedType(type); | 418 _lookupMapAnalysis.registerInstantiatedType(type); |
362 break; | 419 break; |
363 case TypeUseKind.IS_CHECK: | 420 case TypeUseKind.IS_CHECK: |
364 onIsCheckForCodegen(type, transformed); | 421 onIsCheckForCodegen(type, transformed); |
365 break; | 422 break; |
366 default: | 423 default: |
367 } | 424 } |
368 } | 425 } |
369 | 426 |
370 for (ConstantValue constant in impact.compileTimeConstants) { | 427 for (ConstantValue constant in impact.compileTimeConstants) { |
371 backend.computeImpactForCompileTimeConstant(constant, transformed, | 428 _backend.computeImpactForCompileTimeConstant(constant, transformed, |
372 forResolution: false); | 429 forResolution: false); |
373 backend.addCompileTimeConstantForEmission(constant); | 430 _backend.addCompileTimeConstantForEmission(constant); |
374 } | 431 } |
375 | 432 |
376 for (Pair<ResolutionDartType, ResolutionDartType> check | 433 for (Pair<ResolutionDartType, ResolutionDartType> check |
377 in impact.typeVariableBoundsSubtypeChecks) { | 434 in impact.typeVariableBoundsSubtypeChecks) { |
378 backend.registerTypeVariableBoundsSubtypeCheck(check.a, check.b); | 435 _backend.registerTypeVariableBoundsSubtypeCheck(check.a, check.b); |
379 } | 436 } |
380 | 437 |
381 for (StaticUse staticUse in impact.staticUses) { | 438 for (StaticUse staticUse in impact.staticUses) { |
382 switch (staticUse.kind) { | 439 switch (staticUse.kind) { |
383 case StaticUseKind.CLOSURE: | 440 case StaticUseKind.CLOSURE: |
384 LocalFunctionElement closure = staticUse.element; | 441 LocalFunctionElement closure = staticUse.element; |
385 if (backend.rtiNeed.localFunctionNeedsRti(closure)) { | 442 if (_rtiNeed.localFunctionNeedsRti(closure)) { |
386 impacts.computeSignature | 443 _impacts.computeSignature |
387 .registerImpact(transformed, elementEnvironment); | 444 .registerImpact(transformed, _elementEnvironment); |
388 } | 445 } |
389 break; | 446 break; |
390 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: | 447 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: |
391 case StaticUseKind.CONSTRUCTOR_INVOKE: | 448 case StaticUseKind.CONSTRUCTOR_INVOKE: |
392 backend.lookupMapAnalysis.registerInstantiatedType(staticUse.type); | 449 _lookupMapAnalysis.registerInstantiatedType(staticUse.type); |
393 break; | 450 break; |
394 default: | 451 default: |
395 } | 452 } |
396 } | 453 } |
397 | 454 |
398 for (String name in impact.constSymbols) { | 455 for (String name in impact.constSymbols) { |
399 backend.mirrorsData.registerConstSymbol(name); | 456 _mirrorsData.registerConstSymbol(name); |
400 } | 457 } |
401 | 458 |
402 for (Set<ClassElement> classes in impact.specializedGetInterceptors) { | 459 for (Set<ClassElement> classes in impact.specializedGetInterceptors) { |
403 backend.oneShotInterceptorData | 460 _oneShotInterceptorData.registerSpecializedGetInterceptor( |
404 .registerSpecializedGetInterceptor(classes, backend.namer); | 461 classes, _namer); |
405 } | 462 } |
406 | 463 |
407 if (impact.usesInterceptor) { | 464 if (impact.usesInterceptor) { |
408 if (backend.nativeCodegenEnqueuer.hasInstantiatedNativeClasses) { | 465 if (_nativeCodegenEnqueuer.hasInstantiatedNativeClasses) { |
409 impacts.interceptorUse.registerImpact(transformed, elementEnvironment); | 466 _impacts.interceptorUse |
| 467 .registerImpact(transformed, _elementEnvironment); |
410 } | 468 } |
411 } | 469 } |
412 | 470 |
413 for (ClassElement element in impact.typeConstants) { | 471 for (ClassElement element in impact.typeConstants) { |
414 backend.customElementsCodegenAnalysis.registerTypeConstant(element); | 472 _customElementsCodegenAnalysis.registerTypeConstant(element); |
415 backend.lookupMapAnalysis.registerTypeConstant(element); | 473 _lookupMapAnalysis.registerTypeConstant(element); |
416 } | 474 } |
417 | 475 |
418 for (FunctionElement element in impact.asyncMarkers) { | 476 for (FunctionElement element in impact.asyncMarkers) { |
419 switch (element.asyncMarker) { | 477 switch (element.asyncMarker) { |
420 case AsyncMarker.ASYNC: | 478 case AsyncMarker.ASYNC: |
421 impacts.asyncBody.registerImpact(transformed, elementEnvironment); | 479 _impacts.asyncBody.registerImpact(transformed, _elementEnvironment); |
422 break; | 480 break; |
423 case AsyncMarker.SYNC_STAR: | 481 case AsyncMarker.SYNC_STAR: |
424 impacts.syncStarBody.registerImpact(transformed, elementEnvironment); | 482 _impacts.syncStarBody |
| 483 .registerImpact(transformed, _elementEnvironment); |
425 break; | 484 break; |
426 case AsyncMarker.ASYNC_STAR: | 485 case AsyncMarker.ASYNC_STAR: |
427 impacts.asyncStarBody.registerImpact(transformed, elementEnvironment); | 486 _impacts.asyncStarBody |
| 487 .registerImpact(transformed, _elementEnvironment); |
428 break; | 488 break; |
429 } | 489 } |
430 } | 490 } |
431 | 491 |
432 // TODO(johnniwinther): Remove eager registration. | 492 // TODO(johnniwinther): Remove eager registration. |
433 return transformed; | 493 return transformed; |
434 } | 494 } |
435 } | 495 } |
OLD | NEW |