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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 void markAsInlinable(FunctionElement element, {bool insideLoop}) { | 100 void markAsInlinable(FunctionElement element, {bool insideLoop}) { |
101 int oldDecision = _cachedDecisions[element]; | 101 int oldDecision = _cachedDecisions[element]; |
102 | 102 |
103 if (oldDecision == null) { | 103 if (oldDecision == null) { |
104 oldDecision = _unknown; | 104 oldDecision = _unknown; |
105 } | 105 } |
106 | 106 |
107 if (insideLoop) { | 107 if (insideLoop) { |
108 switch (oldDecision) { | 108 switch (oldDecision) { |
109 case _mustNotInline: | 109 case _mustNotInline: |
110 throw new SpannableAssertionFailure(element, | 110 throw new SpannableAssertionFailure( |
| 111 element, |
111 "Can't mark a function as non-inlinable and inlinable at the " | 112 "Can't mark a function as non-inlinable and inlinable at the " |
112 "same time."); | 113 "same time."); |
113 | 114 |
114 case _unknown: | 115 case _unknown: |
115 // We know that it can be inlined in a loop, but don't know about the | 116 // We know that it can be inlined in a loop, but don't know about the |
116 // non-loop case yet. | 117 // non-loop case yet. |
117 _cachedDecisions[element] = _canInlineInLoopMayInlineOutside; | 118 _cachedDecisions[element] = _canInlineInLoopMayInlineOutside; |
118 break; | 119 break; |
119 | 120 |
120 case _mayInlineInLoopMustNotOutside: | 121 case _mayInlineInLoopMustNotOutside: |
121 _cachedDecisions[element] = _canInlineInLoopMustNotOutside; | 122 _cachedDecisions[element] = _canInlineInLoopMustNotOutside; |
122 break; | 123 break; |
123 | 124 |
124 case _canInlineInLoopMustNotOutside: | 125 case _canInlineInLoopMustNotOutside: |
125 case _canInlineInLoopMayInlineOutside: | 126 case _canInlineInLoopMayInlineOutside: |
126 case _canInline: | 127 case _canInline: |
127 case _mustInline: | 128 case _mustInline: |
128 // Do nothing. | 129 // Do nothing. |
129 break; | 130 break; |
130 } | 131 } |
131 } else { | 132 } else { |
132 switch (oldDecision) { | 133 switch (oldDecision) { |
133 case _mustNotInline: | 134 case _mustNotInline: |
134 case _mayInlineInLoopMustNotOutside: | 135 case _mayInlineInLoopMustNotOutside: |
135 case _canInlineInLoopMustNotOutside: | 136 case _canInlineInLoopMustNotOutside: |
136 throw new SpannableAssertionFailure(element, | 137 throw new SpannableAssertionFailure( |
| 138 element, |
137 "Can't mark a function as non-inlinable and inlinable at the " | 139 "Can't mark a function as non-inlinable and inlinable at the " |
138 "same time."); | 140 "same time."); |
139 | 141 |
140 case _unknown: | 142 case _unknown: |
141 case _canInlineInLoopMayInlineOutside: | 143 case _canInlineInLoopMayInlineOutside: |
142 _cachedDecisions[element] = _canInline; | 144 _cachedDecisions[element] = _canInline; |
143 break; | 145 break; |
144 | 146 |
145 case _canInline: | 147 case _canInline: |
146 case _mustInline: | 148 case _mustInline: |
147 // Do nothing. | 149 // Do nothing. |
148 break; | 150 break; |
149 | |
150 } | 151 } |
151 } | 152 } |
152 } | 153 } |
153 | 154 |
154 void markAsNonInlinable(FunctionElement element, {bool insideLoop: true}) { | 155 void markAsNonInlinable(FunctionElement element, {bool insideLoop: true}) { |
155 int oldDecision = _cachedDecisions[element]; | 156 int oldDecision = _cachedDecisions[element]; |
156 | 157 |
157 if (oldDecision == null) { | 158 if (oldDecision == null) { |
158 oldDecision = _unknown; | 159 oldDecision = _unknown; |
159 } | 160 } |
160 | 161 |
161 if (insideLoop) { | 162 if (insideLoop) { |
162 switch (oldDecision) { | 163 switch (oldDecision) { |
163 case _canInlineInLoopMustNotOutside: | 164 case _canInlineInLoopMustNotOutside: |
164 case _canInlineInLoopMayInlineOutside: | 165 case _canInlineInLoopMayInlineOutside: |
165 case _canInline: | 166 case _canInline: |
166 case _mustInline: | 167 case _mustInline: |
167 throw new SpannableAssertionFailure(element, | 168 throw new SpannableAssertionFailure( |
| 169 element, |
168 "Can't mark a function as non-inlinable and inlinable at the " | 170 "Can't mark a function as non-inlinable and inlinable at the " |
169 "same time."); | 171 "same time."); |
170 | 172 |
171 case _mayInlineInLoopMustNotOutside: | 173 case _mayInlineInLoopMustNotOutside: |
172 case _unknown: | 174 case _unknown: |
173 _cachedDecisions[element] = _mustNotInline; | 175 _cachedDecisions[element] = _mustNotInline; |
174 break; | 176 break; |
175 | 177 |
176 case _mustNotInline: | 178 case _mustNotInline: |
177 // Do nothing. | 179 // Do nothing. |
178 break; | 180 break; |
179 } | 181 } |
180 } else { | 182 } else { |
181 switch (oldDecision) { | 183 switch (oldDecision) { |
182 case _canInline: | 184 case _canInline: |
183 case _mustInline: | 185 case _mustInline: |
184 throw new SpannableAssertionFailure(element, | 186 throw new SpannableAssertionFailure( |
| 187 element, |
185 "Can't mark a function as non-inlinable and inlinable at the " | 188 "Can't mark a function as non-inlinable and inlinable at the " |
186 "same time."); | 189 "same time."); |
187 | 190 |
188 case _unknown: | 191 case _unknown: |
189 // We can't inline outside a loop, but we might still be allowed to do | 192 // We can't inline outside a loop, but we might still be allowed to do |
190 // so outside. | 193 // so outside. |
191 _cachedDecisions[element] = _mayInlineInLoopMustNotOutside; | 194 _cachedDecisions[element] = _mayInlineInLoopMustNotOutside; |
192 break; | 195 break; |
193 | 196 |
194 case _canInlineInLoopMayInlineOutside: | 197 case _canInlineInLoopMayInlineOutside: |
(...skipping 13 matching lines...) Expand all Loading... |
208 } | 211 } |
209 | 212 |
210 void markAsMustInline(FunctionElement element) { | 213 void markAsMustInline(FunctionElement element) { |
211 _cachedDecisions[element] = _mustInline; | 214 _cachedDecisions[element] = _mustInline; |
212 } | 215 } |
213 } | 216 } |
214 | 217 |
215 enum SyntheticConstantKind { | 218 enum SyntheticConstantKind { |
216 DUMMY_INTERCEPTOR, | 219 DUMMY_INTERCEPTOR, |
217 EMPTY_VALUE, | 220 EMPTY_VALUE, |
218 TYPEVARIABLE_REFERENCE, // Reference to a type in reflection data. | 221 TYPEVARIABLE_REFERENCE, // Reference to a type in reflection data. |
219 NAME | 222 NAME |
220 } | 223 } |
221 | 224 |
222 class JavaScriptBackend extends Backend { | 225 class JavaScriptBackend extends Backend { |
223 String get patchVersion => emitter.patchVersion; | 226 String get patchVersion => emitter.patchVersion; |
224 | 227 |
225 bool get supportsReflection => emitter.emitter.supportsReflection; | 228 bool get supportsReflection => emitter.emitter.supportsReflection; |
226 | 229 |
227 final Annotations annotations; | 230 final Annotations annotations; |
228 | 231 |
229 | |
230 /// Set of classes that need to be considered for reflection although not | 232 /// Set of classes that need to be considered for reflection although not |
231 /// otherwise visible during resolution. | 233 /// otherwise visible during resolution. |
232 Iterable<ClassElement> get classesRequiredForReflection { | 234 Iterable<ClassElement> get classesRequiredForReflection { |
233 // TODO(herhut): Clean this up when classes needed for rti are tracked. | 235 // TODO(herhut): Clean this up when classes needed for rti are tracked. |
234 return [helpers.closureClass, helpers.jsIndexableClass]; | 236 return [helpers.closureClass, helpers.jsIndexableClass]; |
235 } | 237 } |
236 | 238 |
237 FunctionCompiler functionCompiler; | 239 FunctionCompiler functionCompiler; |
238 | 240 |
239 CodeEmitterTask emitter; | 241 CodeEmitterTask emitter; |
240 | 242 |
241 /** | 243 /** |
242 * The generated code as a js AST for compiled methods. | 244 * The generated code as a js AST for compiled methods. |
243 */ | 245 */ |
244 Map<Element, jsAst.Expression> get generatedCode { | 246 Map<Element, jsAst.Expression> get generatedCode { |
245 return compiler.enqueuer.codegen.generatedCode; | 247 return compiler.enqueuer.codegen.generatedCode; |
246 } | 248 } |
247 | 249 |
248 FunctionInlineCache inlineCache = new FunctionInlineCache(); | 250 FunctionInlineCache inlineCache = new FunctionInlineCache(); |
249 | 251 |
250 /// If [true], the compiler will emit code that logs whenever a method is | 252 /// If [true], the compiler will emit code that logs whenever a method is |
251 /// called. When TRACE_METHOD is 'console' this will be logged | 253 /// called. When TRACE_METHOD is 'console' this will be logged |
252 /// directly in the JavaScript console. When TRACE_METHOD is 'post' the | 254 /// directly in the JavaScript console. When TRACE_METHOD is 'post' the |
253 /// information will be sent to a server via a POST request. | 255 /// information will be sent to a server via a POST request. |
254 static const String TRACE_METHOD = const String.fromEnvironment('traceCalls'); | 256 static const String TRACE_METHOD = const String.fromEnvironment('traceCalls'); |
255 static const bool TRACE_CALLS = | 257 static const bool TRACE_CALLS = |
256 TRACE_METHOD == 'post' || TRACE_METHOD == 'console'; | 258 TRACE_METHOD == 'post' || TRACE_METHOD == 'console'; |
257 Element traceHelper; | 259 Element traceHelper; |
258 | 260 |
259 TypeMask get stringType => compiler.typesTask.stringType; | 261 TypeMask get stringType => compiler.typesTask.stringType; |
260 TypeMask get doubleType => compiler.typesTask.doubleType; | 262 TypeMask get doubleType => compiler.typesTask.doubleType; |
261 TypeMask get intType => compiler.typesTask.intType; | 263 TypeMask get intType => compiler.typesTask.intType; |
262 TypeMask get uint32Type => compiler.typesTask.uint32Type; | 264 TypeMask get uint32Type => compiler.typesTask.uint32Type; |
263 TypeMask get uint31Type => compiler.typesTask.uint31Type; | 265 TypeMask get uint31Type => compiler.typesTask.uint31Type; |
264 TypeMask get positiveIntType => compiler.typesTask.positiveIntType; | 266 TypeMask get positiveIntType => compiler.typesTask.positiveIntType; |
265 TypeMask get numType => compiler.typesTask.numType; | 267 TypeMask get numType => compiler.typesTask.numType; |
266 TypeMask get boolType => compiler.typesTask.boolType; | 268 TypeMask get boolType => compiler.typesTask.boolType; |
267 TypeMask get dynamicType => compiler.typesTask.dynamicType; | 269 TypeMask get dynamicType => compiler.typesTask.dynamicType; |
268 TypeMask get nullType => compiler.typesTask.nullType; | 270 TypeMask get nullType => compiler.typesTask.nullType; |
269 TypeMask get emptyType => const TypeMask.nonNullEmpty(); | 271 TypeMask get emptyType => const TypeMask.nonNullEmpty(); |
270 | 272 |
271 TypeMask _indexablePrimitiveTypeCache; | 273 TypeMask _indexablePrimitiveTypeCache; |
272 TypeMask get indexablePrimitiveType { | 274 TypeMask get indexablePrimitiveType { |
273 if (_indexablePrimitiveTypeCache == null) { | 275 if (_indexablePrimitiveTypeCache == null) { |
274 _indexablePrimitiveTypeCache = new TypeMask.nonNullSubtype( | 276 _indexablePrimitiveTypeCache = |
275 helpers.jsIndexableClass, compiler.world); | 277 new TypeMask.nonNullSubtype(helpers.jsIndexableClass, compiler.world); |
276 } | 278 } |
277 return _indexablePrimitiveTypeCache; | 279 return _indexablePrimitiveTypeCache; |
278 } | 280 } |
279 | 281 |
280 TypeMask _readableArrayTypeCache; | 282 TypeMask _readableArrayTypeCache; |
281 TypeMask get readableArrayType { | 283 TypeMask get readableArrayType { |
282 if (_readableArrayTypeCache == null) { | 284 if (_readableArrayTypeCache == null) { |
283 _readableArrayTypeCache = new TypeMask.nonNullSubclass( | 285 _readableArrayTypeCache = |
284 helpers.jsArrayClass, compiler.world); | 286 new TypeMask.nonNullSubclass(helpers.jsArrayClass, compiler.world); |
285 } | 287 } |
286 return _readableArrayTypeCache; | 288 return _readableArrayTypeCache; |
287 } | 289 } |
288 | 290 |
289 TypeMask _mutableArrayTypeCache; | 291 TypeMask _mutableArrayTypeCache; |
290 TypeMask get mutableArrayType { | 292 TypeMask get mutableArrayType { |
291 if (_mutableArrayTypeCache == null) { | 293 if (_mutableArrayTypeCache == null) { |
292 _mutableArrayTypeCache = new TypeMask.nonNullSubclass( | 294 _mutableArrayTypeCache = new TypeMask.nonNullSubclass( |
293 helpers.jsMutableArrayClass, compiler.world); | 295 helpers.jsMutableArrayClass, compiler.world); |
294 } | 296 } |
295 return _mutableArrayTypeCache; | 297 return _mutableArrayTypeCache; |
296 } | 298 } |
297 | 299 |
298 TypeMask _fixedArrayTypeCache; | 300 TypeMask _fixedArrayTypeCache; |
299 TypeMask get fixedArrayType { | 301 TypeMask get fixedArrayType { |
300 if (_fixedArrayTypeCache == null) { | 302 if (_fixedArrayTypeCache == null) { |
301 _fixedArrayTypeCache = new TypeMask.nonNullExact( | 303 _fixedArrayTypeCache = |
302 helpers.jsFixedArrayClass, compiler.world); | 304 new TypeMask.nonNullExact(helpers.jsFixedArrayClass, compiler.world); |
303 } | 305 } |
304 return _fixedArrayTypeCache; | 306 return _fixedArrayTypeCache; |
305 } | 307 } |
306 | 308 |
307 TypeMask _extendableArrayTypeCache; | 309 TypeMask _extendableArrayTypeCache; |
308 TypeMask get extendableArrayType { | 310 TypeMask get extendableArrayType { |
309 if (_extendableArrayTypeCache == null) { | 311 if (_extendableArrayTypeCache == null) { |
310 _extendableArrayTypeCache = new TypeMask.nonNullExact( | 312 _extendableArrayTypeCache = new TypeMask.nonNullExact( |
311 helpers.jsExtendableArrayClass, compiler.world); | 313 helpers.jsExtendableArrayClass, compiler.world); |
312 } | 314 } |
313 return _extendableArrayTypeCache; | 315 return _extendableArrayTypeCache; |
314 } | 316 } |
315 | 317 |
316 TypeMask _unmodifiableArrayTypeCache; | 318 TypeMask _unmodifiableArrayTypeCache; |
317 TypeMask get unmodifiableArrayType { | 319 TypeMask get unmodifiableArrayType { |
318 if (_unmodifiableArrayTypeCache == null) { | 320 if (_unmodifiableArrayTypeCache == null) { |
319 _unmodifiableArrayTypeCache = new TypeMask.nonNullExact( | 321 _unmodifiableArrayTypeCache = new TypeMask.nonNullExact( |
320 helpers.jsUnmodifiableArrayClass, compiler.world); | 322 helpers.jsUnmodifiableArrayClass, compiler.world); |
321 } | 323 } |
322 return _fixedArrayTypeCache; | 324 return _fixedArrayTypeCache; |
323 } | 325 } |
324 | 326 |
325 TypeMask _nonNullTypeCache; | 327 TypeMask _nonNullTypeCache; |
326 TypeMask get nonNullType { | 328 TypeMask get nonNullType { |
327 if (_nonNullTypeCache == null) { | 329 if (_nonNullTypeCache == null) { |
328 _nonNullTypeCache = | 330 _nonNullTypeCache = compiler.typesTask.dynamicType.nonNullable(); |
329 compiler.typesTask.dynamicType.nonNullable(); | |
330 } | 331 } |
331 return _nonNullTypeCache; | 332 return _nonNullTypeCache; |
332 } | 333 } |
333 | 334 |
334 /// Maps special classes to their implementation (JSXxx) class. | 335 /// Maps special classes to their implementation (JSXxx) class. |
335 Map<ClassElement, ClassElement> implementationClasses; | 336 Map<ClassElement, ClassElement> implementationClasses; |
336 | 337 |
337 bool needToInitializeIsolateAffinityTag = false; | 338 bool needToInitializeIsolateAffinityTag = false; |
338 bool needToInitializeDispatchProperty = false; | 339 bool needToInitializeDispatchProperty = false; |
339 | 340 |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 final Set<String> symbolsUsed = new Set<String>(); | 466 final Set<String> symbolsUsed = new Set<String>(); |
466 | 467 |
467 /// List of elements that the backend may use. | 468 /// List of elements that the backend may use. |
468 final Set<Element> helpersUsed = new Set<Element>(); | 469 final Set<Element> helpersUsed = new Set<Element>(); |
469 | 470 |
470 /// All the checked mode helpers. | 471 /// All the checked mode helpers. |
471 static const checkedModeHelpers = CheckedModeHelper.helpers; | 472 static const checkedModeHelpers = CheckedModeHelper.helpers; |
472 | 473 |
473 // Checked mode helpers indexed by name. | 474 // Checked mode helpers indexed by name. |
474 Map<String, CheckedModeHelper> checkedModeHelperByName = | 475 Map<String, CheckedModeHelper> checkedModeHelperByName = |
475 new Map<String, CheckedModeHelper>.fromIterable( | 476 new Map<String, CheckedModeHelper>.fromIterable(checkedModeHelpers, |
476 checkedModeHelpers, | |
477 key: (helper) => helper.name); | 477 key: (helper) => helper.name); |
478 | 478 |
479 TypeVariableHandler typeVariableHandler; | 479 TypeVariableHandler typeVariableHandler; |
480 | 480 |
481 /// Number of methods compiled before considering reflection. | 481 /// Number of methods compiled before considering reflection. |
482 int preMirrorsMethodCount = 0; | 482 int preMirrorsMethodCount = 0; |
483 | 483 |
484 /// Resolution and codegen support for generating table of interceptors and | 484 /// Resolution and codegen support for generating table of interceptors and |
485 /// constructors for custom elements. | 485 /// constructors for custom elements. |
486 CustomElementsAnalysis customElementsAnalysis; | 486 CustomElementsAnalysis customElementsAnalysis; |
(...skipping 18 matching lines...) Expand all Loading... |
505 SourceInformationStrategy sourceInformationStrategy; | 505 SourceInformationStrategy sourceInformationStrategy; |
506 | 506 |
507 JavaScriptBackendSerialization serialization; | 507 JavaScriptBackendSerialization serialization; |
508 | 508 |
509 final NativeData nativeData = new NativeData(); | 509 final NativeData nativeData = new NativeData(); |
510 | 510 |
511 final BackendHelpers helpers; | 511 final BackendHelpers helpers; |
512 final BackendImpacts impacts; | 512 final BackendImpacts impacts; |
513 | 513 |
514 JavaScriptBackend(Compiler compiler, | 514 JavaScriptBackend(Compiler compiler, |
515 {bool generateSourceMap: true, | 515 {bool generateSourceMap: true, |
516 bool useStartupEmitter: false, | 516 bool useStartupEmitter: false, |
517 bool useNewSourceInfo: false}) | 517 bool useNewSourceInfo: false}) |
518 : namer = determineNamer(compiler), | 518 : namer = determineNamer(compiler), |
519 oneShotInterceptors = new Map<jsAst.Name, Selector>(), | 519 oneShotInterceptors = new Map<jsAst.Name, Selector>(), |
520 interceptedElements = new Map<String, Set<Element>>(), | 520 interceptedElements = new Map<String, Set<Element>>(), |
521 rti = new _RuntimeTypes(compiler), | 521 rti = new _RuntimeTypes(compiler), |
522 rtiEncoder = new _RuntimeTypesEncoder(compiler), | 522 rtiEncoder = new _RuntimeTypesEncoder(compiler), |
523 specializedGetInterceptors = new Map<jsAst.Name, Set<ClassElement>>(), | 523 specializedGetInterceptors = new Map<jsAst.Name, Set<ClassElement>>(), |
524 annotations = new Annotations(compiler), | 524 annotations = new Annotations(compiler), |
525 this.sourceInformationStrategy = | 525 this.sourceInformationStrategy = generateSourceMap |
526 generateSourceMap | 526 ? (useNewSourceInfo |
527 ? (useNewSourceInfo | 527 ? new PositionSourceInformationStrategy() |
528 ? new PositionSourceInformationStrategy() | 528 : const StartEndSourceInformationStrategy()) |
529 : const StartEndSourceInformationStrategy()) | 529 : const JavaScriptSourceInformationStrategy(), |
530 : const JavaScriptSourceInformationStrategy(), | |
531 helpers = new BackendHelpers(compiler), | 530 helpers = new BackendHelpers(compiler), |
532 impacts = new BackendImpacts(compiler), | 531 impacts = new BackendImpacts(compiler), |
533 super(compiler) { | 532 super(compiler) { |
534 emitter = new CodeEmitterTask( | 533 emitter = new CodeEmitterTask( |
535 compiler, namer, generateSourceMap, useStartupEmitter); | 534 compiler, namer, generateSourceMap, useStartupEmitter); |
536 typeVariableHandler = new TypeVariableHandler(compiler); | 535 typeVariableHandler = new TypeVariableHandler(compiler); |
537 customElementsAnalysis = new CustomElementsAnalysis(this); | 536 customElementsAnalysis = new CustomElementsAnalysis(this); |
538 lookupMapAnalysis = new LookupMapAnalysis(this, reporter); | 537 lookupMapAnalysis = new LookupMapAnalysis(this, reporter); |
539 jsInteropAnalysis = new JsInteropAnalysis(this); | 538 jsInteropAnalysis = new JsInteropAnalysis(this); |
540 | 539 |
541 noSuchMethodRegistry = new NoSuchMethodRegistry(this); | 540 noSuchMethodRegistry = new NoSuchMethodRegistry(this); |
542 constantCompilerTask = new JavaScriptConstantTask(compiler); | 541 constantCompilerTask = new JavaScriptConstantTask(compiler); |
543 impactTransformer = new JavaScriptImpactTransformer(this); | 542 impactTransformer = new JavaScriptImpactTransformer(this); |
544 patchResolverTask = new PatchResolverTask(compiler); | 543 patchResolverTask = new PatchResolverTask(compiler); |
545 functionCompiler = compiler.options.useCpsIr | 544 functionCompiler = compiler.options.useCpsIr |
546 ? new CpsFunctionCompiler( | 545 ? new CpsFunctionCompiler(compiler, this, sourceInformationStrategy) |
547 compiler, this, sourceInformationStrategy) | 546 : new SsaFunctionCompiler(this, sourceInformationStrategy); |
548 : new SsaFunctionCompiler(this, sourceInformationStrategy); | |
549 serialization = new JavaScriptBackendSerialization(this); | 547 serialization = new JavaScriptBackendSerialization(this); |
550 } | 548 } |
551 | 549 |
552 ConstantSystem get constantSystem => constants.constantSystem; | 550 ConstantSystem get constantSystem => constants.constantSystem; |
553 | 551 |
554 DiagnosticReporter get reporter => compiler.reporter; | 552 DiagnosticReporter get reporter => compiler.reporter; |
555 | 553 |
556 CoreClasses get coreClasses => compiler.coreClasses; | 554 CoreClasses get coreClasses => compiler.coreClasses; |
557 | 555 |
558 CoreTypes get coreTypes => compiler.coreTypes; | 556 CoreTypes get coreTypes => compiler.coreTypes; |
559 | 557 |
560 Resolution get resolution => compiler.resolution; | 558 Resolution get resolution => compiler.resolution; |
561 | 559 |
562 /// Returns constant environment for the JavaScript interpretation of the | 560 /// Returns constant environment for the JavaScript interpretation of the |
563 /// constants. | 561 /// constants. |
564 JavaScriptConstantCompiler get constants { | 562 JavaScriptConstantCompiler get constants { |
565 return constantCompilerTask.jsConstantCompiler; | 563 return constantCompilerTask.jsConstantCompiler; |
566 } | 564 } |
567 | 565 |
568 MethodElement resolveExternalFunction(MethodElement element) { | 566 MethodElement resolveExternalFunction(MethodElement element) { |
569 if (isForeign(element)) { | 567 if (isForeign(element)) { |
570 return element; | 568 return element; |
571 } | 569 } |
572 if (isJsInterop(element)) { | 570 if (isJsInterop(element)) { |
573 if (element.memberName == const PublicName('[]') || | 571 if (element.memberName == const PublicName('[]') || |
574 element.memberName == const PublicName('[]=')) { | 572 element.memberName == const PublicName('[]=')) { |
575 reporter.reportErrorMessage(element, | 573 reporter.reportErrorMessage( |
576 MessageKind.JS_INTEROP_INDEX_NOT_SUPPORTED); | 574 element, MessageKind.JS_INTEROP_INDEX_NOT_SUPPORTED); |
577 } | 575 } |
578 return element; | 576 return element; |
579 } | 577 } |
580 return patchResolverTask.measure(() { | 578 return patchResolverTask.measure(() { |
581 return patchResolverTask.resolveExternalFunction(element); | 579 return patchResolverTask.resolveExternalFunction(element); |
582 }); | 580 }); |
583 } | 581 } |
584 | 582 |
585 bool isForeign(Element element) => element.library == helpers.foreignLibrary; | 583 bool isForeign(Element element) => element.library == helpers.foreignLibrary; |
586 | 584 |
587 bool isBackendLibrary(LibraryElement library) { | 585 bool isBackendLibrary(LibraryElement library) { |
588 return library == helpers.interceptorsLibrary || | 586 return library == helpers.interceptorsLibrary || |
589 library == helpers.jsHelperLibrary; | 587 library == helpers.jsHelperLibrary; |
590 } | 588 } |
591 | 589 |
592 static Namer determineNamer(Compiler compiler) { | 590 static Namer determineNamer(Compiler compiler) { |
593 return compiler.options.enableMinification ? | 591 return compiler.options.enableMinification |
594 compiler.options.useFrequencyNamer ? | 592 ? compiler.options.useFrequencyNamer |
595 new FrequencyBasedNamer(compiler) : | 593 ? new FrequencyBasedNamer(compiler) |
596 new MinifyNamer(compiler) : | 594 : new MinifyNamer(compiler) |
597 new Namer(compiler); | 595 : new Namer(compiler); |
598 } | 596 } |
599 | 597 |
600 /// The backend must *always* call this method when enqueuing an | 598 /// The backend must *always* call this method when enqueuing an |
601 /// element. Calls done by the backend are not seen by global | 599 /// element. Calls done by the backend are not seen by global |
602 /// optimizations, so they would make these optimizations unsound. | 600 /// optimizations, so they would make these optimizations unsound. |
603 /// Therefore we need to collect the list of helpers the backend may | 601 /// Therefore we need to collect the list of helpers the backend may |
604 /// use. | 602 /// use. |
605 // TODO(johnniwinther): Replace this with a more precise modelling; type | 603 // TODO(johnniwinther): Replace this with a more precise modelling; type |
606 // inference of these elements is disabled. | 604 // inference of these elements is disabled. |
607 Element registerBackendUse(Element element) { | 605 Element registerBackendUse(Element element) { |
608 if (element == null) return null; | 606 if (element == null) return null; |
609 assert(invariant(element, _isValidBackendUse(element), | 607 assert(invariant(element, _isValidBackendUse(element), |
610 message: "Backend use of $element is not allowed.")); | 608 message: "Backend use of $element is not allowed.")); |
611 helpersUsed.add(element.declaration); | 609 helpersUsed.add(element.declaration); |
612 if (element.isClass && element.isPatched) { | 610 if (element.isClass && element.isPatched) { |
613 // Both declaration and implementation may declare fields, so we | 611 // Both declaration and implementation may declare fields, so we |
614 // add both to the list of helpers. | 612 // add both to the list of helpers. |
615 helpersUsed.add(element.implementation); | 613 helpersUsed.add(element.implementation); |
616 } | 614 } |
617 return element; | 615 return element; |
618 } | 616 } |
619 | 617 |
620 bool _isValidBackendUse(Element element) { | 618 bool _isValidBackendUse(Element element) { |
621 assert(invariant(element, element.isDeclaration, | 619 assert(invariant(element, element.isDeclaration, message: "")); |
622 message: "")); | |
623 if (element == helpers.streamIteratorConstructor || | 620 if (element == helpers.streamIteratorConstructor || |
624 element == helpers.compiler.symbolConstructor || | 621 element == helpers.compiler.symbolConstructor || |
625 element == helpers.compiler.symbolValidatedConstructor || | 622 element == helpers.compiler.symbolValidatedConstructor || |
626 element == helpers.syncCompleterConstructor || | 623 element == helpers.syncCompleterConstructor || |
627 element == coreClasses.symbolClass || | 624 element == coreClasses.symbolClass || |
628 element == helpers.objectNoSuchMethod) { | 625 element == helpers.objectNoSuchMethod) { |
629 // TODO(johnniwinther): These are valid but we could be more precise. | 626 // TODO(johnniwinther): These are valid but we could be more precise. |
630 return true; | 627 return true; |
631 } else if (element.implementationLibrary.isPatch || | 628 } else if (element.implementationLibrary.isPatch || |
632 // Needed to detect deserialized injected elements, that is | 629 // Needed to detect deserialized injected elements, that is |
633 // element declared in patch files. | 630 // element declared in patch files. |
634 (element.library.isPlatformLibrary && | 631 (element.library.isPlatformLibrary && |
635 element.sourcePosition.uri.path.contains( | 632 element.sourcePosition.uri.path |
636 '_internal/js_runtime/lib/')) || | 633 .contains('_internal/js_runtime/lib/')) || |
637 element.library == helpers.jsHelperLibrary || | 634 element.library == helpers.jsHelperLibrary || |
638 element.library == helpers.interceptorsLibrary || | 635 element.library == helpers.interceptorsLibrary || |
639 element.library == helpers.isolateHelperLibrary) { | 636 element.library == helpers.isolateHelperLibrary) { |
640 // TODO(johnniwinther): We should be more precise about these. | 637 // TODO(johnniwinther): We should be more precise about these. |
641 return true; | 638 return true; |
642 } else if (element == coreClasses.listClass || | 639 } else if (element == coreClasses.listClass || |
643 element == helpers.mapLiteralClass || | 640 element == helpers.mapLiteralClass || |
644 element == coreClasses.functionClass || | 641 element == coreClasses.functionClass || |
645 element == coreClasses.stringClass) { | 642 element == coreClasses.stringClass) { |
646 // TODO(johnniwinther): Avoid these. | 643 // TODO(johnniwinther): Avoid these. |
647 return true; | 644 return true; |
648 } | 645 } |
649 return false; | 646 return false; |
650 } | 647 } |
651 | 648 |
652 bool usedByBackend(Element element) { | 649 bool usedByBackend(Element element) { |
653 if (element.isParameter | 650 if (element.isParameter || |
654 || element.isInitializingFormal | 651 element.isInitializingFormal || |
655 || element.isField) { | 652 element.isField) { |
656 if (usedByBackend(element.enclosingElement)) return true; | 653 if (usedByBackend(element.enclosingElement)) return true; |
657 } | 654 } |
658 return helpersUsed.contains(element.declaration); | 655 return helpersUsed.contains(element.declaration); |
659 } | 656 } |
660 | 657 |
661 bool invokedReflectively(Element element) { | 658 bool invokedReflectively(Element element) { |
662 if (element.isParameter || element.isInitializingFormal) { | 659 if (element.isParameter || element.isInitializingFormal) { |
663 ParameterElement parameter = element; | 660 ParameterElement parameter = element; |
664 if (invokedReflectively(parameter.functionDeclaration)) return true; | 661 if (invokedReflectively(parameter.functionDeclaration)) return true; |
665 } | 662 } |
666 | 663 |
667 if (element.isField) { | 664 if (element.isField) { |
668 if (Elements.isStaticOrTopLevel(element) | 665 if (Elements.isStaticOrTopLevel(element) && |
669 && (element.isFinal || element.isConst)) { | 666 (element.isFinal || element.isConst)) { |
670 return false; | 667 return false; |
671 } | 668 } |
672 } | 669 } |
673 | 670 |
674 return isAccessibleByReflection(element.declaration); | 671 return isAccessibleByReflection(element.declaration); |
675 } | 672 } |
676 | 673 |
677 bool canBeUsedForGlobalOptimizations(Element element) { | 674 bool canBeUsedForGlobalOptimizations(Element element) { |
678 return !usedByBackend(element) && !invokedReflectively(element); | 675 return !usedByBackend(element) && !invokedReflectively(element); |
679 } | 676 } |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
768 bool isInterceptedSelector(Selector selector) { | 765 bool isInterceptedSelector(Selector selector) { |
769 return interceptedElements[selector.name] != null; | 766 return interceptedElements[selector.name] != null; |
770 } | 767 } |
771 | 768 |
772 /** | 769 /** |
773 * Returns `true` iff [selector] matches an element defined in a class mixed | 770 * Returns `true` iff [selector] matches an element defined in a class mixed |
774 * into an intercepted class. These selectors are not eligible for the 'dummy | 771 * into an intercepted class. These selectors are not eligible for the 'dummy |
775 * explicit receiver' optimization. | 772 * explicit receiver' optimization. |
776 */ | 773 */ |
777 bool isInterceptedMixinSelector(Selector selector, TypeMask mask) { | 774 bool isInterceptedMixinSelector(Selector selector, TypeMask mask) { |
778 Set<Element> elements = interceptedMixinElements.putIfAbsent( | 775 Set<Element> elements = |
779 selector.name, | 776 interceptedMixinElements.putIfAbsent(selector.name, () { |
780 () { | 777 Set<Element> elements = interceptedElements[selector.name]; |
781 Set<Element> elements = interceptedElements[selector.name]; | 778 if (elements == null) return null; |
782 if (elements == null) return null; | 779 return elements |
783 return elements | 780 .where((element) => classesMixedIntoInterceptedClasses |
784 .where((element) => | 781 .contains(element.enclosingClass)) |
785 classesMixedIntoInterceptedClasses.contains( | 782 .toSet(); |
786 element.enclosingClass)) | 783 }); |
787 .toSet(); | |
788 }); | |
789 | 784 |
790 if (elements == null) return false; | 785 if (elements == null) return false; |
791 if (elements.isEmpty) return false; | 786 if (elements.isEmpty) return false; |
792 return elements.any((element) { | 787 return elements.any((element) { |
793 return selector.applies(element, compiler.world) && | 788 return selector.applies(element, compiler.world) && |
794 (mask == null || mask.canHit(element, selector, compiler.world)); | 789 (mask == null || mask.canHit(element, selector, compiler.world)); |
795 }); | 790 }); |
796 } | 791 } |
797 | 792 |
798 /// True if the given class is an internal class used for type inference | 793 /// True if the given class is an internal class used for type inference |
799 /// and never exists at runtime. | 794 /// and never exists at runtime. |
800 bool isCompileTimeOnlyClass(ClassElement class_) { | 795 bool isCompileTimeOnlyClass(ClassElement class_) { |
801 return class_ == helpers.jsPositiveIntClass || | 796 return class_ == helpers.jsPositiveIntClass || |
802 class_ == helpers.jsUInt32Class || | 797 class_ == helpers.jsUInt32Class || |
803 class_ == helpers.jsUInt31Class || | 798 class_ == helpers.jsUInt31Class || |
804 class_ == helpers.jsFixedArrayClass || | 799 class_ == helpers.jsFixedArrayClass || |
805 class_ == helpers.jsUnmodifiableArrayClass || | 800 class_ == helpers.jsUnmodifiableArrayClass || |
806 class_ == helpers.jsMutableArrayClass || | 801 class_ == helpers.jsMutableArrayClass || |
807 class_ == helpers.jsExtendableArrayClass; | 802 class_ == helpers.jsExtendableArrayClass; |
808 } | 803 } |
809 | 804 |
810 /// Maps compile-time classes to their runtime class. The runtime class is | 805 /// Maps compile-time classes to their runtime class. The runtime class is |
811 /// always a superclass or the class itself. | 806 /// always a superclass or the class itself. |
812 ClassElement getRuntimeClass(ClassElement class_) { | 807 ClassElement getRuntimeClass(ClassElement class_) { |
813 if (class_.isSubclassOf(helpers.jsIntClass)) return helpers.jsIntClass; | 808 if (class_.isSubclassOf(helpers.jsIntClass)) return helpers.jsIntClass; |
814 if (class_.isSubclassOf(helpers.jsArrayClass)) return helpers.jsArrayClass; | 809 if (class_.isSubclassOf(helpers.jsArrayClass)) return helpers.jsArrayClass; |
815 return class_; | 810 return class_; |
816 } | 811 } |
817 | 812 |
818 final Map<String, Set<ClassElement>> interceptedClassesCache = | 813 final Map<String, Set<ClassElement>> interceptedClassesCache = |
819 new Map<String, Set<ClassElement>>(); | 814 new Map<String, Set<ClassElement>>(); |
820 final Set<ClassElement> _noClasses = new Set<ClassElement>(); | 815 final Set<ClassElement> _noClasses = new Set<ClassElement>(); |
821 | 816 |
822 /// Returns a set of interceptor classes that contain a member named [name] | 817 /// Returns a set of interceptor classes that contain a member named [name] |
823 /// | 818 /// |
824 /// Returns an empty set if there is no class. Do not modify the returned set. | 819 /// Returns an empty set if there is no class. Do not modify the returned set. |
825 Set<ClassElement> getInterceptedClassesOn(String name) { | 820 Set<ClassElement> getInterceptedClassesOn(String name) { |
826 Set<Element> intercepted = interceptedElements[name]; | 821 Set<Element> intercepted = interceptedElements[name]; |
827 if (intercepted == null) return _noClasses; | 822 if (intercepted == null) return _noClasses; |
828 return interceptedClassesCache.putIfAbsent(name, () { | 823 return interceptedClassesCache.putIfAbsent(name, () { |
829 // Populate the cache by running through all the elements and | 824 // Populate the cache by running through all the elements and |
830 // determine if the given selector applies to them. | 825 // determine if the given selector applies to them. |
831 Set<ClassElement> result = new Set<ClassElement>(); | 826 Set<ClassElement> result = new Set<ClassElement>(); |
832 for (Element element in intercepted) { | 827 for (Element element in intercepted) { |
833 ClassElement classElement = element.enclosingClass; | 828 ClassElement classElement = element.enclosingClass; |
834 if (isCompileTimeOnlyClass(classElement)) continue; | 829 if (isCompileTimeOnlyClass(classElement)) continue; |
835 if (isNativeOrExtendsNative(classElement) | 830 if (isNativeOrExtendsNative(classElement) || |
836 || interceptedClasses.contains(classElement)) { | 831 interceptedClasses.contains(classElement)) { |
837 result.add(classElement); | 832 result.add(classElement); |
838 } | 833 } |
839 if (classesMixedIntoInterceptedClasses.contains(classElement)) { | 834 if (classesMixedIntoInterceptedClasses.contains(classElement)) { |
840 Set<ClassElement> nativeSubclasses = | 835 Set<ClassElement> nativeSubclasses = |
841 nativeSubclassesOfMixin(classElement); | 836 nativeSubclassesOfMixin(classElement); |
842 if (nativeSubclasses != null) result.addAll(nativeSubclasses); | 837 if (nativeSubclasses != null) result.addAll(nativeSubclasses); |
843 } | 838 } |
844 } | 839 } |
845 return result; | 840 return result; |
846 }); | 841 }); |
847 } | 842 } |
848 | 843 |
849 Set<ClassElement> nativeSubclassesOfMixin(ClassElement mixin) { | 844 Set<ClassElement> nativeSubclassesOfMixin(ClassElement mixin) { |
850 ClassWorld classWorld = compiler.world; | 845 ClassWorld classWorld = compiler.world; |
851 Iterable<MixinApplicationElement> uses = classWorld.mixinUsesOf(mixin); | 846 Iterable<MixinApplicationElement> uses = classWorld.mixinUsesOf(mixin); |
852 Set<ClassElement> result = null; | 847 Set<ClassElement> result = null; |
853 for (MixinApplicationElement use in uses) { | 848 for (MixinApplicationElement use in uses) { |
854 classWorld.forEachStrictSubclassOf(use, (ClassElement subclass) { | 849 classWorld.forEachStrictSubclassOf(use, (ClassElement subclass) { |
855 if (isNativeOrExtendsNative(subclass)) { | 850 if (isNativeOrExtendsNative(subclass)) { |
856 if (result == null) result = new Set<ClassElement>(); | 851 if (result == null) result = new Set<ClassElement>(); |
857 result.add(subclass); | 852 result.add(subclass); |
858 } | 853 } |
859 }); | 854 }); |
860 } | 855 } |
861 return result; | 856 return result; |
862 } | 857 } |
863 | 858 |
864 bool operatorEqHandlesNullArgument(FunctionElement operatorEqfunction) { | 859 bool operatorEqHandlesNullArgument(FunctionElement operatorEqfunction) { |
865 return specialOperatorEqClasses.contains( | 860 return specialOperatorEqClasses.contains(operatorEqfunction.enclosingClass); |
866 operatorEqfunction.enclosingClass); | |
867 } | 861 } |
868 | 862 |
869 void validateInterceptorImplementsAllObjectMethods( | 863 void validateInterceptorImplementsAllObjectMethods( |
870 ClassElement interceptorClass) { | 864 ClassElement interceptorClass) { |
871 if (interceptorClass == null) return; | 865 if (interceptorClass == null) return; |
872 interceptorClass.ensureResolved(resolution); | 866 interceptorClass.ensureResolved(resolution); |
873 coreClasses.objectClass.forEachMember((_, Element member) { | 867 coreClasses.objectClass.forEachMember((_, Element member) { |
874 if (member.isGenerativeConstructor) return; | 868 if (member.isGenerativeConstructor) return; |
875 Element interceptorMember = interceptorClass.lookupMember(member.name); | 869 Element interceptorMember = interceptorClass.lookupMember(member.name); |
876 // Interceptors must override all Object methods due to calling convention | 870 // Interceptors must override all Object methods due to calling convention |
877 // differences. | 871 // differences. |
878 assert(invariant( | 872 assert(invariant(interceptorMember, |
879 interceptorMember, | |
880 interceptorMember.enclosingClass == interceptorClass, | 873 interceptorMember.enclosingClass == interceptorClass, |
881 message: | 874 message: |
882 "Member ${member.name} not overridden in ${interceptorClass}. " | 875 "Member ${member.name} not overridden in ${interceptorClass}. " |
883 "Found $interceptorMember from " | 876 "Found $interceptorMember from " |
884 "${interceptorMember.enclosingClass}.")); | 877 "${interceptorMember.enclosingClass}.")); |
885 }); | 878 }); |
886 } | 879 } |
887 | 880 |
888 void addInterceptorsForNativeClassMembers( | 881 void addInterceptorsForNativeClassMembers( |
889 ClassElement cls, Enqueuer enqueuer) { | 882 ClassElement cls, Enqueuer enqueuer) { |
890 if (enqueuer.isResolutionQueue) { | 883 if (enqueuer.isResolutionQueue) { |
891 cls.ensureResolved(resolution); | 884 cls.ensureResolved(resolution); |
892 cls.forEachMember((ClassElement classElement, Element member) { | 885 cls.forEachMember((ClassElement classElement, Element member) { |
893 if (member.name == Identifiers.call) { | 886 if (member.name == Identifiers.call) { |
894 reporter.reportErrorMessage( | 887 reporter.reportErrorMessage( |
895 member, | 888 member, MessageKind.CALL_NOT_SUPPORTED_ON_NATIVE_CLASS); |
896 MessageKind.CALL_NOT_SUPPORTED_ON_NATIVE_CLASS); | |
897 return; | 889 return; |
898 } | 890 } |
899 if (member.isSynthesized) return; | 891 if (member.isSynthesized) return; |
900 // All methods on [Object] are shadowed by [Interceptor]. | 892 // All methods on [Object] are shadowed by [Interceptor]. |
901 if (classElement == coreClasses.objectClass) return; | 893 if (classElement == coreClasses.objectClass) return; |
902 Set<Element> set = interceptedElements.putIfAbsent( | 894 Set<Element> set = interceptedElements.putIfAbsent( |
903 member.name, () => new Set<Element>()); | 895 member.name, () => new Set<Element>()); |
904 set.add(member); | 896 set.add(member); |
905 }, | 897 }, includeSuperAndInjectedMembers: true); |
906 includeSuperAndInjectedMembers: true); | |
907 | 898 |
908 // Walk superclass chain to find mixins. | 899 // Walk superclass chain to find mixins. |
909 for (; cls != null; cls = cls.superclass) { | 900 for (; cls != null; cls = cls.superclass) { |
910 if (cls.isMixinApplication) { | 901 if (cls.isMixinApplication) { |
911 MixinApplicationElement mixinApplication = cls; | 902 MixinApplicationElement mixinApplication = cls; |
912 classesMixedIntoInterceptedClasses.add(mixinApplication.mixin); | 903 classesMixedIntoInterceptedClasses.add(mixinApplication.mixin); |
913 } | 904 } |
914 } | 905 } |
915 } | 906 } |
916 } | 907 } |
917 | 908 |
918 void addInterceptors(ClassElement cls, | 909 void addInterceptors(ClassElement cls, Enqueuer enqueuer, Registry registry) { |
919 Enqueuer enqueuer, | |
920 Registry registry) { | |
921 if (enqueuer.isResolutionQueue) { | 910 if (enqueuer.isResolutionQueue) { |
922 _interceptedClasses.add(helpers.jsInterceptorClass); | 911 _interceptedClasses.add(helpers.jsInterceptorClass); |
923 _interceptedClasses.add(cls); | 912 _interceptedClasses.add(cls); |
924 cls.ensureResolved(resolution); | 913 cls.ensureResolved(resolution); |
925 cls.forEachMember((ClassElement classElement, Element member) { | 914 cls.forEachMember((ClassElement classElement, Element member) { |
926 // All methods on [Object] are shadowed by [Interceptor]. | 915 // All methods on [Object] are shadowed by [Interceptor]. |
927 if (classElement == coreClasses.objectClass) return; | 916 if (classElement == coreClasses.objectClass) return; |
928 Set<Element> set = interceptedElements.putIfAbsent( | 917 Set<Element> set = interceptedElements.putIfAbsent( |
929 member.name, () => new Set<Element>()); | 918 member.name, () => new Set<Element>()); |
930 set.add(member); | 919 set.add(member); |
931 }, | 920 }, includeSuperAndInjectedMembers: true); |
932 includeSuperAndInjectedMembers: true); | |
933 } | 921 } |
934 enqueueClass(enqueuer, cls, registry); | 922 enqueueClass(enqueuer, cls, registry); |
935 } | 923 } |
936 | 924 |
937 Set<ClassElement> get interceptedClasses { | 925 Set<ClassElement> get interceptedClasses { |
938 assert(compiler.enqueuer.resolution.queueIsClosed); | 926 assert(compiler.enqueuer.resolution.queueIsClosed); |
939 return _interceptedClasses; | 927 return _interceptedClasses; |
940 } | 928 } |
941 | 929 |
942 void registerSpecializedGetInterceptor(Set<ClassElement> classes) { | 930 void registerSpecializedGetInterceptor(Set<ClassElement> classes) { |
943 jsAst.Name name = namer.nameForGetInterceptor(classes); | 931 jsAst.Name name = namer.nameForGetInterceptor(classes); |
944 if (classes.contains(helpers.jsInterceptorClass)) { | 932 if (classes.contains(helpers.jsInterceptorClass)) { |
945 // We can't use a specialized [getInterceptorMethod], so we make | 933 // We can't use a specialized [getInterceptorMethod], so we make |
946 // sure we emit the one with all checks. | 934 // sure we emit the one with all checks. |
947 specializedGetInterceptors[name] = interceptedClasses; | 935 specializedGetInterceptors[name] = interceptedClasses; |
948 } else { | 936 } else { |
949 specializedGetInterceptors[name] = classes; | 937 specializedGetInterceptors[name] = classes; |
950 } | 938 } |
951 } | 939 } |
952 | 940 |
953 void registerCompileTimeConstant(ConstantValue constant, Registry registry) { | 941 void registerCompileTimeConstant(ConstantValue constant, Registry registry) { |
954 registerCompileTimeConstantInternal(constant, registry); | 942 registerCompileTimeConstantInternal(constant, registry); |
955 | 943 |
956 if (!registry.isForResolution && | 944 if (!registry.isForResolution && lookupMapAnalysis.isLookupMap(constant)) { |
957 lookupMapAnalysis.isLookupMap(constant)) { | |
958 // Note: internally, this registration will temporarily remove the | 945 // Note: internally, this registration will temporarily remove the |
959 // constant dependencies and add them later on-demand. | 946 // constant dependencies and add them later on-demand. |
960 lookupMapAnalysis.registerLookupMapReference(constant); | 947 lookupMapAnalysis.registerLookupMapReference(constant); |
961 } | 948 } |
962 | 949 |
963 for (ConstantValue dependency in constant.getDependencies()) { | 950 for (ConstantValue dependency in constant.getDependencies()) { |
964 registerCompileTimeConstant(dependency, registry); | 951 registerCompileTimeConstant(dependency, registry); |
965 } | 952 } |
966 } | 953 } |
967 | 954 |
968 void addCompileTimeConstantForEmission(ConstantValue constant) { | 955 void addCompileTimeConstantForEmission(ConstantValue constant) { |
969 constants.addCompileTimeConstantForEmission(constant); | 956 constants.addCompileTimeConstantForEmission(constant); |
970 } | 957 } |
971 | 958 |
972 void registerCompileTimeConstantInternal(ConstantValue constant, | 959 void registerCompileTimeConstantInternal( |
973 Registry registry) { | 960 ConstantValue constant, Registry registry) { |
974 DartType type = constant.getType(compiler.coreTypes); | 961 DartType type = constant.getType(compiler.coreTypes); |
975 registerInstantiatedConstantType(type, registry); | 962 registerInstantiatedConstantType(type, registry); |
976 | 963 |
977 if (constant.isFunction) { | 964 if (constant.isFunction) { |
978 FunctionConstantValue function = constant; | 965 FunctionConstantValue function = constant; |
979 registry.registerStaticUse(new StaticUse.staticTearOff(function.element)); | 966 registry.registerStaticUse(new StaticUse.staticTearOff(function.element)); |
980 } else if (constant.isInterceptor) { | 967 } else if (constant.isInterceptor) { |
981 // An interceptor constant references the class's prototype chain. | 968 // An interceptor constant references the class's prototype chain. |
982 InterceptorConstantValue interceptor = constant; | 969 InterceptorConstantValue interceptor = constant; |
983 registerInstantiatedConstantType(interceptor.dispatchedType, registry); | 970 registerInstantiatedConstantType(interceptor.dispatchedType, registry); |
984 } else if (constant.isType) { | 971 } else if (constant.isType) { |
985 enqueueInResolution(helpers.createRuntimeType, registry); | 972 enqueueInResolution(helpers.createRuntimeType, registry); |
986 registry.registerInstantiation(typeImplementation.rawType); | 973 registry.registerInstantiation(typeImplementation.rawType); |
987 } | 974 } |
988 lookupMapAnalysis.registerConstantKey(constant); | 975 lookupMapAnalysis.registerConstantKey(constant); |
989 } | 976 } |
990 | 977 |
991 void registerInstantiatedConstantType(DartType type, Registry registry) { | 978 void registerInstantiatedConstantType(DartType type, Registry registry) { |
992 DartType instantiatedType = | 979 DartType instantiatedType = |
993 type.isFunctionType ? coreTypes.functionType : type; | 980 type.isFunctionType ? coreTypes.functionType : type; |
994 if (type is InterfaceType) { | 981 if (type is InterfaceType) { |
995 registry.registerInstantiation(instantiatedType); | 982 registry.registerInstantiation(instantiatedType); |
996 if (!type.treatAsRaw && classNeedsRti(type.element)) { | 983 if (!type.treatAsRaw && classNeedsRti(type.element)) { |
997 registry.registerStaticUse( | 984 registry.registerStaticUse(new StaticUse.staticInvoke( |
998 new StaticUse.staticInvoke( | 985 // TODO(johnniwinther): Find the right [CallStructure]. |
999 // TODO(johnniwinther): Find the right [CallStructure]. | 986 helpers.setRuntimeTypeInfo, |
1000 helpers.setRuntimeTypeInfo, null)); | 987 null)); |
1001 } | 988 } |
1002 if (type.element == typeImplementation) { | 989 if (type.element == typeImplementation) { |
1003 // If we use a type literal in a constant, the compile time | 990 // If we use a type literal in a constant, the compile time |
1004 // constant emitter will generate a call to the createRuntimeType | 991 // constant emitter will generate a call to the createRuntimeType |
1005 // helper so we register a use of that. | 992 // helper so we register a use of that. |
1006 registry.registerStaticUse( | 993 registry.registerStaticUse(new StaticUse.staticInvoke( |
1007 new StaticUse.staticInvoke( | 994 // TODO(johnniwinther): Find the right [CallStructure]. |
1008 // TODO(johnniwinther): Find the right [CallStructure]. | |
1009 | 995 |
1010 helpers.createRuntimeType, null)); | 996 helpers.createRuntimeType, |
| 997 null)); |
1011 } | 998 } |
1012 } | 999 } |
1013 } | 1000 } |
1014 | 1001 |
1015 void registerMetadataConstant(MetadataAnnotation metadata, | 1002 void registerMetadataConstant(MetadataAnnotation metadata, |
1016 Element annotatedElement, | 1003 Element annotatedElement, Registry registry) { |
1017 Registry registry) { | |
1018 assert(registry.isForResolution); | 1004 assert(registry.isForResolution); |
1019 ConstantValue constant = constants.getConstantValueForMetadata(metadata); | 1005 ConstantValue constant = constants.getConstantValueForMetadata(metadata); |
1020 registerCompileTimeConstant(constant, registry); | 1006 registerCompileTimeConstant(constant, registry); |
1021 metadataConstants.add(new Dependency(constant, annotatedElement)); | 1007 metadataConstants.add(new Dependency(constant, annotatedElement)); |
1022 } | 1008 } |
1023 | 1009 |
1024 void registerInstantiatedClass(ClassElement cls, | 1010 void registerInstantiatedClass( |
1025 Enqueuer enqueuer, | 1011 ClassElement cls, Enqueuer enqueuer, Registry registry) { |
1026 Registry registry) { | |
1027 _processClass(cls, enqueuer, registry); | 1012 _processClass(cls, enqueuer, registry); |
1028 } | 1013 } |
1029 | 1014 |
1030 void registerImplementedClass(ClassElement cls, | 1015 void registerImplementedClass( |
1031 Enqueuer enqueuer, | 1016 ClassElement cls, Enqueuer enqueuer, Registry registry) { |
1032 Registry registry) { | |
1033 _processClass(cls, enqueuer, registry); | 1017 _processClass(cls, enqueuer, registry); |
1034 } | 1018 } |
1035 | 1019 |
1036 void _processClass(ClassElement cls, | 1020 void _processClass(ClassElement cls, Enqueuer enqueuer, Registry registry) { |
1037 Enqueuer enqueuer, | |
1038 Registry registry) { | |
1039 if (!cls.typeVariables.isEmpty) { | 1021 if (!cls.typeVariables.isEmpty) { |
1040 typeVariableHandler.registerClassWithTypeVariables(cls, enqueuer, | 1022 typeVariableHandler.registerClassWithTypeVariables( |
1041 registry); | 1023 cls, enqueuer, registry); |
1042 } | 1024 } |
1043 | 1025 |
1044 // Register any helper that will be needed by the backend. | 1026 // Register any helper that will be needed by the backend. |
1045 if (enqueuer.isResolutionQueue) { | 1027 if (enqueuer.isResolutionQueue) { |
1046 if (cls == coreClasses.intClass || | 1028 if (cls == coreClasses.intClass || |
1047 cls == coreClasses.doubleClass || | 1029 cls == coreClasses.doubleClass || |
1048 cls == coreClasses.numClass) { | 1030 cls == coreClasses.numClass) { |
1049 // The backend will try to optimize number operations and use the | 1031 // The backend will try to optimize number operations and use the |
1050 // `iae` helper directly. | 1032 // `iae` helper directly. |
1051 enqueue(enqueuer, helpers.throwIllegalArgumentException, registry); | 1033 enqueue(enqueuer, helpers.throwIllegalArgumentException, registry); |
1052 } else if (cls == coreClasses.listClass || | 1034 } else if (cls == coreClasses.listClass || |
1053 cls == coreClasses.stringClass) { | 1035 cls == coreClasses.stringClass) { |
1054 // The backend will try to optimize array and string access and use the | 1036 // The backend will try to optimize array and string access and use the |
1055 // `ioore` and `iae` helpers directly. | 1037 // `ioore` and `iae` helpers directly. |
1056 enqueue(enqueuer, helpers.throwIndexOutOfRangeException, registry); | 1038 enqueue(enqueuer, helpers.throwIndexOutOfRangeException, registry); |
1057 enqueue(enqueuer, helpers.throwIllegalArgumentException, registry); | 1039 enqueue(enqueuer, helpers.throwIllegalArgumentException, registry); |
1058 } else if (cls == coreClasses.functionClass) { | 1040 } else if (cls == coreClasses.functionClass) { |
1059 enqueueClass(enqueuer, helpers.closureClass, registry); | 1041 enqueueClass(enqueuer, helpers.closureClass, registry); |
1060 } else if (cls == coreClasses.mapClass) { | 1042 } else if (cls == coreClasses.mapClass) { |
1061 // The backend will use a literal list to initialize the entries | 1043 // The backend will use a literal list to initialize the entries |
1062 // of the map. | 1044 // of the map. |
1063 enqueueClass(enqueuer, coreClasses.listClass, registry); | 1045 enqueueClass(enqueuer, coreClasses.listClass, registry); |
1064 enqueueClass(enqueuer, helpers.mapLiteralClass, registry); | 1046 enqueueClass(enqueuer, helpers.mapLiteralClass, registry); |
1065 // For map literals, the dependency between the implementation class | 1047 // For map literals, the dependency between the implementation class |
1066 // and [Map] is not visible, so we have to add it manually. | 1048 // and [Map] is not visible, so we have to add it manually. |
1067 rti.registerRtiDependency(helpers.mapLiteralClass, cls); | 1049 rti.registerRtiDependency(helpers.mapLiteralClass, cls); |
1068 } else if (cls == helpers.boundClosureClass) { | 1050 } else if (cls == helpers.boundClosureClass) { |
1069 // TODO(johnniwinther): Is this a noop? | 1051 // TODO(johnniwinther): Is this a noop? |
1070 enqueueClass(enqueuer, helpers.boundClosureClass, registry); | 1052 enqueueClass(enqueuer, helpers.boundClosureClass, registry); |
1071 } else if (isNativeOrExtendsNative(cls)) { | 1053 } else if (isNativeOrExtendsNative(cls)) { |
1072 enqueue(enqueuer, helpers.getNativeInterceptorMethod, registry); | 1054 enqueue(enqueuer, helpers.getNativeInterceptorMethod, registry); |
1073 enqueueClass(enqueuer, helpers.jsInterceptorClass, | 1055 enqueueClass( |
1074 compiler.globalDependencies); | 1056 enqueuer, helpers.jsInterceptorClass, compiler.globalDependencies); |
1075 enqueueClass(enqueuer, helpers.jsJavaScriptObjectClass, registry); | 1057 enqueueClass(enqueuer, helpers.jsJavaScriptObjectClass, registry); |
1076 enqueueClass(enqueuer, helpers.jsPlainJavaScriptObjectClass, registry); | 1058 enqueueClass(enqueuer, helpers.jsPlainJavaScriptObjectClass, registry); |
1077 enqueueClass(enqueuer, helpers.jsJavaScriptFunctionClass, registry); | 1059 enqueueClass(enqueuer, helpers.jsJavaScriptFunctionClass, registry); |
1078 } else if (cls == helpers.mapLiteralClass) { | 1060 } else if (cls == helpers.mapLiteralClass) { |
1079 // For map literals, the dependency between the implementation class | 1061 // For map literals, the dependency between the implementation class |
1080 // and [Map] is not visible, so we have to add it manually. | 1062 // and [Map] is not visible, so we have to add it manually. |
1081 Element getFactory(String name, int arity) { | 1063 Element getFactory(String name, int arity) { |
1082 // The constructor is on the patch class, but dart2js unit tests don't | 1064 // The constructor is on the patch class, but dart2js unit tests don't |
1083 // have a patch class. | 1065 // have a patch class. |
1084 ClassElement implementation = cls.implementation; | 1066 ClassElement implementation = cls.implementation; |
1085 ConstructorElement ctor = implementation.lookupConstructor(name); | 1067 ConstructorElement ctor = implementation.lookupConstructor(name); |
1086 if (ctor == null || | 1068 if (ctor == null || |
1087 (Name.isPrivateName(name) && | 1069 (Name.isPrivateName(name) && |
1088 ctor.library != helpers.mapLiteralClass.library)) { | 1070 ctor.library != helpers.mapLiteralClass.library)) { |
1089 reporter.internalError( | 1071 reporter.internalError( |
1090 helpers.mapLiteralClass, | 1072 helpers.mapLiteralClass, |
1091 "Map literal class ${helpers.mapLiteralClass} missing " | 1073 "Map literal class ${helpers.mapLiteralClass} missing " |
1092 "'$name' constructor" | 1074 "'$name' constructor" |
1093 " ${helpers.mapLiteralClass.constructors}"); | 1075 " ${helpers.mapLiteralClass.constructors}"); |
1094 } | 1076 } |
1095 return ctor; | 1077 return ctor; |
1096 } | 1078 } |
1097 Element getMember(String name) { | 1079 Element getMember(String name) { |
1098 // The constructor is on the patch class, but dart2js unit tests don't | 1080 // The constructor is on the patch class, but dart2js unit tests don't |
1099 // have a patch class. | 1081 // have a patch class. |
1100 ClassElement implementation = cls.implementation; | 1082 ClassElement implementation = cls.implementation; |
1101 Element element = implementation.lookupLocalMember(name); | 1083 Element element = implementation.lookupLocalMember(name); |
1102 if (element == null || !element.isFunction || !element.isStatic) { | 1084 if (element == null || !element.isFunction || !element.isStatic) { |
1103 reporter.internalError(helpers.mapLiteralClass, | 1085 reporter.internalError( |
| 1086 helpers.mapLiteralClass, |
1104 "Map literal class ${helpers.mapLiteralClass} missing " | 1087 "Map literal class ${helpers.mapLiteralClass} missing " |
1105 "'$name' static member function"); | 1088 "'$name' static member function"); |
1106 } | 1089 } |
1107 return element; | 1090 return element; |
1108 } | 1091 } |
1109 helpers.mapLiteralConstructor = getFactory('_literal', 1); | 1092 helpers.mapLiteralConstructor = getFactory('_literal', 1); |
1110 helpers.mapLiteralConstructorEmpty = getFactory('_empty', 0); | 1093 helpers.mapLiteralConstructorEmpty = getFactory('_empty', 0); |
1111 enqueueInResolution(helpers.mapLiteralConstructor, registry); | 1094 enqueueInResolution(helpers.mapLiteralConstructor, registry); |
1112 enqueueInResolution(helpers.mapLiteralConstructorEmpty, registry); | 1095 enqueueInResolution(helpers.mapLiteralConstructorEmpty, registry); |
1113 | 1096 |
1114 helpers.mapLiteralUntypedMaker = getMember('_makeLiteral'); | 1097 helpers.mapLiteralUntypedMaker = getMember('_makeLiteral'); |
1115 helpers.mapLiteralUntypedEmptyMaker = getMember('_makeEmpty'); | 1098 helpers.mapLiteralUntypedEmptyMaker = getMember('_makeEmpty'); |
1116 enqueueInResolution(helpers.mapLiteralUntypedMaker, registry); | 1099 enqueueInResolution(helpers.mapLiteralUntypedMaker, registry); |
1117 enqueueInResolution(helpers.mapLiteralUntypedEmptyMaker, registry); | 1100 enqueueInResolution(helpers.mapLiteralUntypedEmptyMaker, registry); |
1118 } | 1101 } |
1119 } | 1102 } |
1120 if (cls == helpers.closureClass) { | 1103 if (cls == helpers.closureClass) { |
1121 enqueue(enqueuer, helpers.closureFromTearOff, registry); | 1104 enqueue(enqueuer, helpers.closureFromTearOff, registry); |
1122 } | 1105 } |
1123 if (cls == coreClasses.stringClass || | 1106 if (cls == coreClasses.stringClass || cls == helpers.jsStringClass) { |
1124 cls == helpers.jsStringClass) { | |
1125 addInterceptors(helpers.jsStringClass, enqueuer, registry); | 1107 addInterceptors(helpers.jsStringClass, enqueuer, registry); |
1126 } else if (cls == coreClasses.listClass || | 1108 } else if (cls == coreClasses.listClass || |
1127 cls == helpers.jsArrayClass || | 1109 cls == helpers.jsArrayClass || |
1128 cls == helpers.jsFixedArrayClass || | 1110 cls == helpers.jsFixedArrayClass || |
1129 cls == helpers.jsExtendableArrayClass || | 1111 cls == helpers.jsExtendableArrayClass || |
1130 cls == helpers.jsUnmodifiableArrayClass) { | 1112 cls == helpers.jsUnmodifiableArrayClass) { |
1131 addInterceptors(helpers.jsArrayClass, enqueuer, registry); | 1113 addInterceptors(helpers.jsArrayClass, enqueuer, registry); |
1132 addInterceptors(helpers.jsMutableArrayClass, enqueuer, registry); | 1114 addInterceptors(helpers.jsMutableArrayClass, enqueuer, registry); |
1133 addInterceptors(helpers.jsFixedArrayClass, enqueuer, registry); | 1115 addInterceptors(helpers.jsFixedArrayClass, enqueuer, registry); |
1134 addInterceptors(helpers.jsExtendableArrayClass, enqueuer, registry); | 1116 addInterceptors(helpers.jsExtendableArrayClass, enqueuer, registry); |
1135 addInterceptors(helpers.jsUnmodifiableArrayClass, enqueuer, registry); | 1117 addInterceptors(helpers.jsUnmodifiableArrayClass, enqueuer, registry); |
1136 // Literal lists can be translated into calls to these functions: | 1118 // Literal lists can be translated into calls to these functions: |
1137 enqueueInResolution(helpers.jsArrayTypedConstructor, registry); | 1119 enqueueInResolution(helpers.jsArrayTypedConstructor, registry); |
1138 enqueueInResolution(helpers.setRuntimeTypeInfo, registry); | 1120 enqueueInResolution(helpers.setRuntimeTypeInfo, registry); |
1139 enqueueInResolution(helpers.getTypeArgumentByIndex, registry); | 1121 enqueueInResolution(helpers.getTypeArgumentByIndex, registry); |
1140 } else if (cls == coreClasses.intClass || | 1122 } else if (cls == coreClasses.intClass || cls == helpers.jsIntClass) { |
1141 cls == helpers.jsIntClass) { | |
1142 addInterceptors(helpers.jsIntClass, enqueuer, registry); | 1123 addInterceptors(helpers.jsIntClass, enqueuer, registry); |
1143 addInterceptors(helpers.jsPositiveIntClass, enqueuer, registry); | 1124 addInterceptors(helpers.jsPositiveIntClass, enqueuer, registry); |
1144 addInterceptors(helpers.jsUInt32Class, enqueuer, registry); | 1125 addInterceptors(helpers.jsUInt32Class, enqueuer, registry); |
1145 addInterceptors(helpers.jsUInt31Class, enqueuer, registry); | 1126 addInterceptors(helpers.jsUInt31Class, enqueuer, registry); |
1146 addInterceptors(helpers.jsNumberClass, enqueuer, registry); | 1127 addInterceptors(helpers.jsNumberClass, enqueuer, registry); |
1147 } else if (cls == coreClasses.doubleClass || | 1128 } else if (cls == coreClasses.doubleClass || cls == helpers.jsDoubleClass) { |
1148 cls == helpers.jsDoubleClass) { | |
1149 addInterceptors(helpers.jsDoubleClass, enqueuer, registry); | 1129 addInterceptors(helpers.jsDoubleClass, enqueuer, registry); |
1150 addInterceptors(helpers.jsNumberClass, enqueuer, registry); | 1130 addInterceptors(helpers.jsNumberClass, enqueuer, registry); |
1151 } else if (cls == coreClasses.boolClass || | 1131 } else if (cls == coreClasses.boolClass || cls == helpers.jsBoolClass) { |
1152 cls == helpers.jsBoolClass) { | |
1153 addInterceptors(helpers.jsBoolClass, enqueuer, registry); | 1132 addInterceptors(helpers.jsBoolClass, enqueuer, registry); |
1154 } else if (cls == coreClasses.nullClass || | 1133 } else if (cls == coreClasses.nullClass || cls == helpers.jsNullClass) { |
1155 cls == helpers.jsNullClass) { | |
1156 addInterceptors(helpers.jsNullClass, enqueuer, registry); | 1134 addInterceptors(helpers.jsNullClass, enqueuer, registry); |
1157 } else if (cls == coreClasses.numClass || | 1135 } else if (cls == coreClasses.numClass || cls == helpers.jsNumberClass) { |
1158 cls == helpers.jsNumberClass) { | |
1159 addInterceptors(helpers.jsIntClass, enqueuer, registry); | 1136 addInterceptors(helpers.jsIntClass, enqueuer, registry); |
1160 addInterceptors(helpers.jsPositiveIntClass, enqueuer, registry); | 1137 addInterceptors(helpers.jsPositiveIntClass, enqueuer, registry); |
1161 addInterceptors(helpers.jsUInt32Class, enqueuer, registry); | 1138 addInterceptors(helpers.jsUInt32Class, enqueuer, registry); |
1162 addInterceptors(helpers.jsUInt31Class, enqueuer, registry); | 1139 addInterceptors(helpers.jsUInt31Class, enqueuer, registry); |
1163 addInterceptors(helpers.jsDoubleClass, enqueuer, registry); | 1140 addInterceptors(helpers.jsDoubleClass, enqueuer, registry); |
1164 addInterceptors(helpers.jsNumberClass, enqueuer, registry); | 1141 addInterceptors(helpers.jsNumberClass, enqueuer, registry); |
1165 } else if (cls == helpers.jsJavaScriptObjectClass) { | 1142 } else if (cls == helpers.jsJavaScriptObjectClass) { |
1166 addInterceptors(helpers.jsJavaScriptObjectClass, enqueuer, registry); | 1143 addInterceptors(helpers.jsJavaScriptObjectClass, enqueuer, registry); |
1167 } else if (cls == helpers.jsPlainJavaScriptObjectClass) { | 1144 } else if (cls == helpers.jsPlainJavaScriptObjectClass) { |
1168 addInterceptors(helpers.jsPlainJavaScriptObjectClass, enqueuer, registry); | 1145 addInterceptors(helpers.jsPlainJavaScriptObjectClass, enqueuer, registry); |
1169 } else if (cls == helpers.jsUnknownJavaScriptObjectClass) { | 1146 } else if (cls == helpers.jsUnknownJavaScriptObjectClass) { |
1170 addInterceptors(helpers.jsUnknownJavaScriptObjectClass, enqueuer, registry
); | 1147 addInterceptors( |
| 1148 helpers.jsUnknownJavaScriptObjectClass, enqueuer, registry); |
1171 } else if (cls == helpers.jsJavaScriptFunctionClass) { | 1149 } else if (cls == helpers.jsJavaScriptFunctionClass) { |
1172 addInterceptors(helpers.jsJavaScriptFunctionClass, enqueuer, registry); | 1150 addInterceptors(helpers.jsJavaScriptFunctionClass, enqueuer, registry); |
1173 } else if (isNativeOrExtendsNative(cls)) { | 1151 } else if (isNativeOrExtendsNative(cls)) { |
1174 addInterceptorsForNativeClassMembers(cls, enqueuer); | 1152 addInterceptorsForNativeClassMembers(cls, enqueuer); |
1175 } else if (cls == helpers.jsIndexingBehaviorInterface) { | 1153 } else if (cls == helpers.jsIndexingBehaviorInterface) { |
1176 // These two helpers are used by the emitter and the codegen. | 1154 // These two helpers are used by the emitter and the codegen. |
1177 // Because we cannot enqueue elements at the time of emission, | 1155 // Because we cannot enqueue elements at the time of emission, |
1178 // we make sure they are always generated. | 1156 // we make sure they are always generated. |
1179 enqueue(enqueuer, helpers.isJsIndexable, registry); | 1157 enqueue(enqueuer, helpers.isJsIndexable, registry); |
1180 } | 1158 } |
1181 | 1159 |
1182 customElementsAnalysis.registerInstantiatedClass(cls, enqueuer); | 1160 customElementsAnalysis.registerInstantiatedClass(cls, enqueuer); |
1183 if (!enqueuer.isResolutionQueue) { | 1161 if (!enqueuer.isResolutionQueue) { |
1184 lookupMapAnalysis.registerInstantiatedClass(cls); | 1162 lookupMapAnalysis.registerInstantiatedClass(cls); |
1185 } | 1163 } |
1186 } | 1164 } |
1187 | 1165 |
1188 void registerInstantiatedType(InterfaceType type, | 1166 void registerInstantiatedType( |
1189 Enqueuer enqueuer, | 1167 InterfaceType type, Enqueuer enqueuer, Registry registry, |
1190 Registry registry, | 1168 {bool mirrorUsage: false}) { |
1191 {bool mirrorUsage: false}) { | |
1192 lookupMapAnalysis.registerInstantiatedType(type, registry); | 1169 lookupMapAnalysis.registerInstantiatedType(type, registry); |
1193 super.registerInstantiatedType( | 1170 super.registerInstantiatedType(type, enqueuer, registry, |
1194 type, enqueuer, registry, mirrorUsage: mirrorUsage); | 1171 mirrorUsage: mirrorUsage); |
1195 } | 1172 } |
1196 | 1173 |
1197 void registerUseInterceptor(Enqueuer enqueuer) { | 1174 void registerUseInterceptor(Enqueuer enqueuer) { |
1198 assert(!enqueuer.isResolutionQueue); | 1175 assert(!enqueuer.isResolutionQueue); |
1199 if (!enqueuer.nativeEnqueuer.hasInstantiatedNativeClasses()) return; | 1176 if (!enqueuer.nativeEnqueuer.hasInstantiatedNativeClasses()) return; |
1200 Registry registry = compiler.globalDependencies; | 1177 Registry registry = compiler.globalDependencies; |
1201 enqueue(enqueuer, helpers.getNativeInterceptorMethod, registry); | 1178 enqueue(enqueuer, helpers.getNativeInterceptorMethod, registry); |
1202 enqueueClass(enqueuer, helpers.jsJavaScriptObjectClass, registry); | 1179 enqueueClass(enqueuer, helpers.jsJavaScriptObjectClass, registry); |
1203 enqueueClass(enqueuer, helpers.jsPlainJavaScriptObjectClass, registry); | 1180 enqueueClass(enqueuer, helpers.jsPlainJavaScriptObjectClass, registry); |
1204 enqueueClass(enqueuer, helpers.jsJavaScriptFunctionClass, registry); | 1181 enqueueClass(enqueuer, helpers.jsJavaScriptFunctionClass, registry); |
(...skipping 15 matching lines...) Expand all Loading... |
1220 if (compiler.options.enableTypeAssertions) { | 1197 if (compiler.options.enableTypeAssertions) { |
1221 // Unconditionally register the helper that checks if the | 1198 // Unconditionally register the helper that checks if the |
1222 // expression in an if/while/for is a boolean. | 1199 // expression in an if/while/for is a boolean. |
1223 // TODO(ngeoffray): Should we have the resolver register those instead? | 1200 // TODO(ngeoffray): Should we have the resolver register those instead? |
1224 Element e = helpers.boolConversionCheck; | 1201 Element e = helpers.boolConversionCheck; |
1225 if (e != null) enqueue(world, e, registry); | 1202 if (e != null) enqueue(world, e, registry); |
1226 } | 1203 } |
1227 | 1204 |
1228 if (TRACE_CALLS) { | 1205 if (TRACE_CALLS) { |
1229 traceHelper = TRACE_METHOD == 'console' | 1206 traceHelper = TRACE_METHOD == 'console' |
1230 ? helpers.consoleTraceHelper : helpers.postTraceHelper; | 1207 ? helpers.consoleTraceHelper |
| 1208 : helpers.postTraceHelper; |
1231 assert(traceHelper != null); | 1209 assert(traceHelper != null); |
1232 enqueueInResolution(traceHelper, registry); | 1210 enqueueInResolution(traceHelper, registry); |
1233 } | 1211 } |
1234 enqueueInResolution(helpers.assertUnreachableMethod, registry); | 1212 enqueueInResolution(helpers.assertUnreachableMethod, registry); |
1235 registerCheckedModeHelpers(registry); | 1213 registerCheckedModeHelpers(registry); |
1236 } | 1214 } |
1237 | 1215 |
1238 onResolutionComplete() { | 1216 onResolutionComplete() { |
1239 super.onResolutionComplete(); | 1217 super.onResolutionComplete(); |
1240 computeMembersNeededForReflection(); | 1218 computeMembersNeededForReflection(); |
1241 rti.computeClassesNeedingRti(); | 1219 rti.computeClassesNeedingRti(); |
1242 } | 1220 } |
1243 | 1221 |
1244 onTypeInferenceComplete() { | 1222 onTypeInferenceComplete() { |
1245 super.onTypeInferenceComplete(); | 1223 super.onTypeInferenceComplete(); |
1246 noSuchMethodRegistry.onTypeInferenceComplete(); | 1224 noSuchMethodRegistry.onTypeInferenceComplete(); |
1247 } | 1225 } |
1248 | 1226 |
1249 void registerGetRuntimeTypeArgument(Registry registry) { | 1227 void registerGetRuntimeTypeArgument(Registry registry) { |
1250 enqueueImpact( | 1228 enqueueImpact( |
1251 compiler.enqueuer.resolution, | 1229 compiler.enqueuer.resolution, impacts.getRuntimeTypeArgument, registry); |
1252 impacts.getRuntimeTypeArgument, | |
1253 registry); | |
1254 } | 1230 } |
1255 | 1231 |
1256 void registerCallMethodWithFreeTypeVariables( | 1232 void registerCallMethodWithFreeTypeVariables( |
1257 Element callMethod, | 1233 Element callMethod, Enqueuer enqueuer, Registry registry) { |
1258 Enqueuer enqueuer, | |
1259 Registry registry) { | |
1260 if (enqueuer.isResolutionQueue || methodNeedsRti(callMethod)) { | 1234 if (enqueuer.isResolutionQueue || methodNeedsRti(callMethod)) { |
1261 registerComputeSignature(enqueuer, registry); | 1235 registerComputeSignature(enqueuer, registry); |
1262 } | 1236 } |
1263 } | 1237 } |
1264 | 1238 |
1265 void registerClosureWithFreeTypeVariables( | 1239 void registerClosureWithFreeTypeVariables( |
1266 Element closure, | 1240 Element closure, Enqueuer enqueuer, Registry registry) { |
1267 Enqueuer enqueuer, | |
1268 Registry registry) { | |
1269 if (enqueuer.isResolutionQueue || methodNeedsRti(closure)) { | 1241 if (enqueuer.isResolutionQueue || methodNeedsRti(closure)) { |
1270 registerComputeSignature(enqueuer, registry); | 1242 registerComputeSignature(enqueuer, registry); |
1271 } | 1243 } |
1272 super.registerClosureWithFreeTypeVariables(closure, enqueuer, registry); | 1244 super.registerClosureWithFreeTypeVariables(closure, enqueuer, registry); |
1273 } | 1245 } |
1274 | 1246 |
1275 void registerBoundClosure(Enqueuer enqueuer) { | 1247 void registerBoundClosure(Enqueuer enqueuer) { |
1276 helpers.boundClosureClass.ensureResolved(resolution); | 1248 helpers.boundClosureClass.ensureResolved(resolution); |
1277 registerInstantiatedType( | 1249 registerInstantiatedType( |
1278 helpers.boundClosureClass.rawType, | 1250 helpers.boundClosureClass.rawType, |
1279 enqueuer, | 1251 enqueuer, |
1280 // Precise dependency is not important here. | 1252 // Precise dependency is not important here. |
1281 compiler.globalDependencies); | 1253 compiler.globalDependencies); |
1282 } | 1254 } |
1283 | 1255 |
1284 void registerGetOfStaticFunction(Enqueuer enqueuer) { | 1256 void registerGetOfStaticFunction(Enqueuer enqueuer) { |
1285 helpers.closureClass.ensureResolved(resolution); | 1257 helpers.closureClass.ensureResolved(resolution); |
1286 registerInstantiatedType( | 1258 registerInstantiatedType( |
1287 helpers.closureClass.rawType, | 1259 helpers.closureClass.rawType, enqueuer, compiler.globalDependencies); |
1288 enqueuer, | |
1289 compiler.globalDependencies); | |
1290 } | 1260 } |
1291 | 1261 |
1292 void registerComputeSignature(Enqueuer enqueuer, Registry registry) { | 1262 void registerComputeSignature(Enqueuer enqueuer, Registry registry) { |
1293 // Calls to [:computeSignature:] are generated by the emitter and we | 1263 // Calls to [:computeSignature:] are generated by the emitter and we |
1294 // therefore need to enqueue the used elements in the codegen enqueuer as | 1264 // therefore need to enqueue the used elements in the codegen enqueuer as |
1295 // well as in the resolution enqueuer. | 1265 // well as in the resolution enqueuer. |
1296 enqueueImpact(enqueuer, impacts.computeSignature, registry); | 1266 enqueueImpact(enqueuer, impacts.computeSignature, registry); |
1297 } | 1267 } |
1298 | 1268 |
1299 void registerRuntimeType(Enqueuer enqueuer, Registry registry) { | 1269 void registerRuntimeType(Enqueuer enqueuer, Registry registry) { |
1300 registerComputeSignature(enqueuer, registry); | 1270 registerComputeSignature(enqueuer, registry); |
1301 enqueueInResolution(helpers.setRuntimeTypeInfo, registry); | 1271 enqueueInResolution(helpers.setRuntimeTypeInfo, registry); |
1302 registerGetRuntimeTypeArgument(registry); | 1272 registerGetRuntimeTypeArgument(registry); |
1303 enqueueInResolution(helpers.getRuntimeTypeInfo, registry); | 1273 enqueueInResolution(helpers.getRuntimeTypeInfo, registry); |
1304 enqueueClass(enqueuer, coreClasses.listClass, registry); | 1274 enqueueClass(enqueuer, coreClasses.listClass, registry); |
1305 } | 1275 } |
1306 | 1276 |
1307 void registerTypeVariableBoundsSubtypeCheck(DartType typeArgument, | 1277 void registerTypeVariableBoundsSubtypeCheck( |
1308 DartType bound) { | 1278 DartType typeArgument, DartType bound) { |
1309 rti.registerTypeVariableBoundsSubtypeCheck(typeArgument, bound); | 1279 rti.registerTypeVariableBoundsSubtypeCheck(typeArgument, bound); |
1310 } | 1280 } |
1311 | 1281 |
1312 void registerCheckDeferredIsLoaded(Registry registry) { | 1282 void registerCheckDeferredIsLoaded(Registry registry) { |
1313 enqueueInResolution(helpers.checkDeferredIsLoaded, registry); | 1283 enqueueInResolution(helpers.checkDeferredIsLoaded, registry); |
1314 // Also register the types of the arguments passed to this method. | 1284 // Also register the types of the arguments passed to this method. |
1315 enqueueClass( | 1285 enqueueClass( |
1316 compiler.enqueuer.resolution, coreClasses.stringClass, registry); | 1286 compiler.enqueuer.resolution, coreClasses.stringClass, registry); |
1317 } | 1287 } |
1318 | 1288 |
1319 void registerNoSuchMethod(FunctionElement noSuchMethod) { | 1289 void registerNoSuchMethod(FunctionElement noSuchMethod) { |
1320 noSuchMethodRegistry.registerNoSuchMethod(noSuchMethod); | 1290 noSuchMethodRegistry.registerNoSuchMethod(noSuchMethod); |
1321 } | 1291 } |
1322 | 1292 |
1323 /// Called when resolving a call to a foreign function. | 1293 /// Called when resolving a call to a foreign function. |
1324 void registerForeignCall(Send node, | 1294 void registerForeignCall(Send node, Element element, |
1325 Element element, | 1295 CallStructure callStructure, ForeignResolver resolver) { |
1326 CallStructure callStructure, | |
1327 ForeignResolver resolver) { | |
1328 native.NativeResolutionEnqueuer nativeEnqueuer = | 1296 native.NativeResolutionEnqueuer nativeEnqueuer = |
1329 compiler.enqueuer.resolution.nativeEnqueuer; | 1297 compiler.enqueuer.resolution.nativeEnqueuer; |
1330 if (element.name == 'JS') { | 1298 if (element.name == 'JS') { |
1331 nativeEnqueuer.registerJsCall(node, resolver); | 1299 nativeEnqueuer.registerJsCall(node, resolver); |
1332 } else if (element.name == 'JS_EMBEDDED_GLOBAL') { | 1300 } else if (element.name == 'JS_EMBEDDED_GLOBAL') { |
1333 nativeEnqueuer.registerJsEmbeddedGlobalCall(node, resolver); | 1301 nativeEnqueuer.registerJsEmbeddedGlobalCall(node, resolver); |
1334 } else if (element.name == 'JS_BUILTIN') { | 1302 } else if (element.name == 'JS_BUILTIN') { |
1335 nativeEnqueuer.registerJsBuiltinCall(node, resolver); | 1303 nativeEnqueuer.registerJsBuiltinCall(node, resolver); |
1336 } else if (element.name == 'JS_INTERCEPTOR_CONSTANT') { | 1304 } else if (element.name == 'JS_INTERCEPTOR_CONSTANT') { |
1337 // The type constant that is an argument to JS_INTERCEPTOR_CONSTANT names | 1305 // The type constant that is an argument to JS_INTERCEPTOR_CONSTANT names |
1338 // a class that will be instantiated outside the program by attaching a | 1306 // a class that will be instantiated outside the program by attaching a |
1339 // native class dispatch record referencing the interceptor. | 1307 // native class dispatch record referencing the interceptor. |
1340 if (!node.argumentsNode.isEmpty) { | 1308 if (!node.argumentsNode.isEmpty) { |
1341 Node argument = node.argumentsNode.nodes.head; | 1309 Node argument = node.argumentsNode.nodes.head; |
1342 ConstantExpression constant = resolver.getConstant(argument); | 1310 ConstantExpression constant = resolver.getConstant(argument); |
1343 if (constant != null && constant.kind == ConstantExpressionKind.TYPE) { | 1311 if (constant != null && constant.kind == ConstantExpressionKind.TYPE) { |
1344 TypeConstantExpression typeConstant = constant; | 1312 TypeConstantExpression typeConstant = constant; |
1345 if (typeConstant.type is InterfaceType) { | 1313 if (typeConstant.type is InterfaceType) { |
1346 resolver.registerInstantiatedType(typeConstant.type); | 1314 resolver.registerInstantiatedType(typeConstant.type); |
1347 return; | 1315 return; |
1348 } | 1316 } |
1349 } | 1317 } |
1350 } | 1318 } |
1351 reporter.reportErrorMessage( | 1319 reporter.reportErrorMessage( |
1352 node, | 1320 node, MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); |
1353 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); | |
1354 } | 1321 } |
1355 } | 1322 } |
1356 | 1323 |
1357 void enableNoSuchMethod(Enqueuer world) { | 1324 void enableNoSuchMethod(Enqueuer world) { |
1358 enqueue(world, helpers.createInvocationMirror, compiler.globalDependencies); | 1325 enqueue(world, helpers.createInvocationMirror, compiler.globalDependencies); |
1359 world.registerDynamicUse( | 1326 world.registerDynamicUse(new DynamicUse(Selectors.noSuchMethod_, null)); |
1360 new DynamicUse(Selectors.noSuchMethod_, null)); | |
1361 } | 1327 } |
1362 | 1328 |
1363 void enableIsolateSupport(Enqueuer enqueuer) { | 1329 void enableIsolateSupport(Enqueuer enqueuer) { |
1364 // TODO(floitsch): We should also ensure that the class IsolateMessage is | 1330 // TODO(floitsch): We should also ensure that the class IsolateMessage is |
1365 // instantiated. Currently, just enabling isolate support works. | 1331 // instantiated. Currently, just enabling isolate support works. |
1366 if (compiler.mainFunction != null) { | 1332 if (compiler.mainFunction != null) { |
1367 // The JavaScript backend implements [Isolate.spawn] by looking up | 1333 // The JavaScript backend implements [Isolate.spawn] by looking up |
1368 // top-level functions by name. So all top-level function tear-off | 1334 // top-level functions by name. So all top-level function tear-off |
1369 // closures have a private name field. | 1335 // closures have a private name field. |
1370 // | 1336 // |
1371 // The JavaScript backend of [Isolate.spawnUri] uses the same internal | 1337 // The JavaScript backend of [Isolate.spawnUri] uses the same internal |
1372 // implementation as [Isolate.spawn], and fails if it cannot look main up | 1338 // implementation as [Isolate.spawn], and fails if it cannot look main up |
1373 // by name. | 1339 // by name. |
1374 enqueuer.registerStaticUse( | 1340 enqueuer.registerStaticUse( |
1375 new StaticUse.staticTearOff(compiler.mainFunction)); | 1341 new StaticUse.staticTearOff(compiler.mainFunction)); |
1376 } | 1342 } |
1377 if (enqueuer.isResolutionQueue) { | 1343 if (enqueuer.isResolutionQueue) { |
1378 | |
1379 void enqueue(Element element) { | 1344 void enqueue(Element element) { |
1380 enqueuer.addToWorkList(element); | 1345 enqueuer.addToWorkList(element); |
1381 compiler.globalDependencies.registerDependency(element); | 1346 compiler.globalDependencies.registerDependency(element); |
1382 helpersUsed.add(element.declaration); | 1347 helpersUsed.add(element.declaration); |
1383 } | 1348 } |
1384 | 1349 |
1385 enqueue(helpers.startRootIsolate); | 1350 enqueue(helpers.startRootIsolate); |
1386 enqueue(helpers.currentIsolate); | 1351 enqueue(helpers.currentIsolate); |
1387 enqueue(helpers.callInIsolate); | 1352 enqueue(helpers.callInIsolate); |
1388 } else { | 1353 } else { |
1389 enqueuer.addToWorkList(helpers.startRootIsolate); | 1354 enqueuer.addToWorkList(helpers.startRootIsolate); |
1390 } | 1355 } |
1391 } | 1356 } |
1392 | 1357 |
1393 bool classNeedsRti(ClassElement cls) { | 1358 bool classNeedsRti(ClassElement cls) { |
1394 return rti.classesNeedingRti.contains(cls.declaration) || | 1359 return rti.classesNeedingRti.contains(cls.declaration) || |
1395 compiler.enabledRuntimeType; | 1360 compiler.enabledRuntimeType; |
1396 } | 1361 } |
1397 | 1362 |
1398 bool isComplexNoSuchMethod(FunctionElement element) => | 1363 bool isComplexNoSuchMethod(FunctionElement element) => |
1399 noSuchMethodRegistry.isComplex(element); | 1364 noSuchMethodRegistry.isComplex(element); |
1400 | 1365 |
1401 bool isDefaultEqualityImplementation(Element element) { | 1366 bool isDefaultEqualityImplementation(Element element) { |
1402 assert(element.name == '=='); | 1367 assert(element.name == '=='); |
1403 ClassElement classElement = element.enclosingClass; | 1368 ClassElement classElement = element.enclosingClass; |
1404 return classElement == coreClasses.objectClass | 1369 return classElement == coreClasses.objectClass || |
1405 || classElement == helpers.jsInterceptorClass | 1370 classElement == helpers.jsInterceptorClass || |
1406 || classElement == helpers.jsNullClass; | 1371 classElement == helpers.jsNullClass; |
1407 } | 1372 } |
1408 | 1373 |
1409 bool methodNeedsRti(FunctionElement function) { | 1374 bool methodNeedsRti(FunctionElement function) { |
1410 return rti.methodsNeedingRti.contains(function) || | 1375 return rti.methodsNeedingRti.contains(function) || |
1411 compiler.enabledRuntimeType; | 1376 compiler.enabledRuntimeType; |
1412 } | 1377 } |
1413 | 1378 |
1414 /// Enqueue [e] in [enqueuer]. | 1379 /// Enqueue [e] in [enqueuer]. |
1415 /// | 1380 /// |
1416 /// This method calls [registerBackendUse]. | 1381 /// This method calls [registerBackendUse]. |
1417 void enqueue(Enqueuer enqueuer, Element e, Registry registry) { | 1382 void enqueue(Enqueuer enqueuer, Element e, Registry registry) { |
1418 if (e == null) return; | 1383 if (e == null) return; |
1419 registerBackendUse(e); | 1384 registerBackendUse(e); |
1420 enqueuer.addToWorkList(e); | 1385 enqueuer.addToWorkList(e); |
1421 registry.registerDependency(e); | 1386 registry.registerDependency(e); |
(...skipping 30 matching lines...) Expand all Loading... |
1452 ClassElement cls = type.element; | 1417 ClassElement cls = type.element; |
1453 registerBackendUse(cls); | 1418 registerBackendUse(cls); |
1454 helpersUsed.add(cls.declaration); | 1419 helpersUsed.add(cls.declaration); |
1455 if (cls.declaration != cls.implementation) { | 1420 if (cls.declaration != cls.implementation) { |
1456 helpersUsed.add(cls.implementation); | 1421 helpersUsed.add(cls.implementation); |
1457 } | 1422 } |
1458 cls.ensureResolved(resolution); | 1423 cls.ensureResolved(resolution); |
1459 registerInstantiatedType(type, enqueuer, registry); | 1424 registerInstantiatedType(type, enqueuer, registry); |
1460 } | 1425 } |
1461 | 1426 |
1462 void enqueueImpact(Enqueuer enqueuer, | 1427 void enqueueImpact( |
1463 BackendImpact impact, | 1428 Enqueuer enqueuer, BackendImpact impact, Registry registry) { |
1464 Registry registry) { | |
1465 for (Element staticUse in impact.staticUses) { | 1429 for (Element staticUse in impact.staticUses) { |
1466 enqueue(enqueuer, staticUse, registry); | 1430 enqueue(enqueuer, staticUse, registry); |
1467 } | 1431 } |
1468 for (InterfaceType type in impact.instantiatedTypes) { | 1432 for (InterfaceType type in impact.instantiatedTypes) { |
1469 enqueueType(enqueuer, type, registry); | 1433 enqueueType(enqueuer, type, registry); |
1470 } | 1434 } |
1471 for (ClassElement cls in impact.instantiatedClasses) { | 1435 for (ClassElement cls in impact.instantiatedClasses) { |
1472 enqueueClass(enqueuer, cls, registry); | 1436 enqueueClass(enqueuer, cls, registry); |
1473 } | 1437 } |
1474 for (BackendImpact otherImpact in impact.otherImpacts) { | 1438 for (BackendImpact otherImpact in impact.otherImpacts) { |
(...skipping 20 matching lines...) Expand all Loading... |
1495 if (kind.category == ElementCategory.VARIABLE) { | 1459 if (kind.category == ElementCategory.VARIABLE) { |
1496 ConstantValue initialValue = | 1460 ConstantValue initialValue = |
1497 constants.getConstantValueForVariable(element); | 1461 constants.getConstantValueForVariable(element); |
1498 if (initialValue != null) { | 1462 if (initialValue != null) { |
1499 registerCompileTimeConstant(initialValue, work.registry); | 1463 registerCompileTimeConstant(initialValue, work.registry); |
1500 addCompileTimeConstantForEmission(initialValue); | 1464 addCompileTimeConstantForEmission(initialValue); |
1501 // We don't need to generate code for static or top-level | 1465 // We don't need to generate code for static or top-level |
1502 // variables. For instance variables, we may need to generate | 1466 // variables. For instance variables, we may need to generate |
1503 // the checked setter. | 1467 // the checked setter. |
1504 if (Elements.isStaticOrTopLevel(element)) { | 1468 if (Elements.isStaticOrTopLevel(element)) { |
1505 return impactTransformer.transformCodegenImpact( | 1469 return impactTransformer |
1506 work.registry.worldImpact); | 1470 .transformCodegenImpact(work.registry.worldImpact); |
1507 } | 1471 } |
1508 } else { | 1472 } else { |
1509 // If the constant-handler was not able to produce a result we have to | 1473 // If the constant-handler was not able to produce a result we have to |
1510 // go through the builder (below) to generate the lazy initializer for | 1474 // go through the builder (below) to generate the lazy initializer for |
1511 // the static variable. | 1475 // the static variable. |
1512 // We also need to register the use of the cyclic-error helper. | 1476 // We also need to register the use of the cyclic-error helper. |
1513 compiler.enqueuer.codegen.registerStaticUse( | 1477 compiler.enqueuer.codegen.registerStaticUse(new StaticUse.staticInvoke( |
1514 new StaticUse.staticInvoke( | 1478 helpers.cyclicThrowHelper, CallStructure.ONE_ARG)); |
1515 helpers.cyclicThrowHelper, CallStructure.ONE_ARG)); | |
1516 } | 1479 } |
1517 } | 1480 } |
1518 | 1481 |
1519 jsAst.Fun function = functionCompiler.compile(work); | 1482 jsAst.Fun function = functionCompiler.compile(work); |
1520 if (function.sourceInformation == null) { | 1483 if (function.sourceInformation == null) { |
1521 function = function.withSourceInformation( | 1484 function = function.withSourceInformation( |
1522 sourceInformationStrategy.buildSourceMappedMarker()); | 1485 sourceInformationStrategy.buildSourceMappedMarker()); |
1523 } | 1486 } |
1524 generatedCode[element] = function; | 1487 generatedCode[element] = function; |
1525 WorldImpact worldImpact = | 1488 WorldImpact worldImpact = |
1526 impactTransformer.transformCodegenImpact(work.registry.worldImpact); | 1489 impactTransformer.transformCodegenImpact(work.registry.worldImpact); |
1527 compiler.dumpInfoTask.registerImpact(element, worldImpact); | 1490 compiler.dumpInfoTask.registerImpact(element, worldImpact); |
1528 return worldImpact; | 1491 return worldImpact; |
1529 } | 1492 } |
1530 | 1493 |
1531 native.NativeEnqueuer nativeResolutionEnqueuer(Enqueuer world) { | 1494 native.NativeEnqueuer nativeResolutionEnqueuer(Enqueuer world) { |
1532 return new native.NativeResolutionEnqueuer(world, compiler); | 1495 return new native.NativeResolutionEnqueuer(world, compiler); |
1533 } | 1496 } |
1534 | 1497 |
1535 native.NativeEnqueuer nativeCodegenEnqueuer(Enqueuer world) { | 1498 native.NativeEnqueuer nativeCodegenEnqueuer(Enqueuer world) { |
1536 return new native.NativeCodegenEnqueuer(world, compiler, emitter); | 1499 return new native.NativeCodegenEnqueuer(world, compiler, emitter); |
1537 } | 1500 } |
1538 | 1501 |
1539 ClassElement defaultSuperclass(ClassElement element) { | 1502 ClassElement defaultSuperclass(ClassElement element) { |
1540 if (isJsInterop(element)) { | 1503 if (isJsInterop(element)) { |
1541 return helpers.jsJavaScriptObjectClass; | 1504 return helpers.jsJavaScriptObjectClass; |
1542 } | 1505 } |
1543 // Native classes inherit from Interceptor. | 1506 // Native classes inherit from Interceptor. |
1544 return isNative(element) | 1507 return isNative(element) |
1545 ? helpers.jsInterceptorClass : coreClasses.objectClass; | 1508 ? helpers.jsInterceptorClass |
| 1509 : coreClasses.objectClass; |
1546 } | 1510 } |
1547 | 1511 |
1548 /** | 1512 /** |
1549 * Unit test hook that returns code of an element as a String. | 1513 * Unit test hook that returns code of an element as a String. |
1550 * | 1514 * |
1551 * Invariant: [element] must be a declaration element. | 1515 * Invariant: [element] must be a declaration element. |
1552 */ | 1516 */ |
1553 String getGeneratedCode(Element element) { | 1517 String getGeneratedCode(Element element) { |
1554 assert(invariant(element, element.isDeclaration)); | 1518 assert(invariant(element, element.isDeclaration)); |
1555 return jsAst.prettyPrint(generatedCode[element], compiler); | 1519 return jsAst.prettyPrint(generatedCode[element], compiler); |
1556 } | 1520 } |
1557 | 1521 |
1558 int assembleProgram() { | 1522 int assembleProgram() { |
1559 int programSize = emitter.assembleProgram(); | 1523 int programSize = emitter.assembleProgram(); |
1560 noSuchMethodRegistry.emitDiagnostic(); | 1524 noSuchMethodRegistry.emitDiagnostic(); |
1561 int totalMethodCount = generatedCode.length; | 1525 int totalMethodCount = generatedCode.length; |
1562 if (totalMethodCount != preMirrorsMethodCount) { | 1526 if (totalMethodCount != preMirrorsMethodCount) { |
1563 int mirrorCount = totalMethodCount - preMirrorsMethodCount; | 1527 int mirrorCount = totalMethodCount - preMirrorsMethodCount; |
1564 double percentage = (mirrorCount / totalMethodCount) * 100; | 1528 double percentage = (mirrorCount / totalMethodCount) * 100; |
1565 DiagnosticMessage hint = reporter.createMessage( | 1529 DiagnosticMessage hint = |
1566 compiler.mainApp, MessageKind.MIRROR_BLOAT, | 1530 reporter.createMessage(compiler.mainApp, MessageKind.MIRROR_BLOAT, { |
1567 {'count': mirrorCount, | 1531 'count': mirrorCount, |
1568 'total': totalMethodCount, | 1532 'total': totalMethodCount, |
1569 'percentage': percentage.round()}); | 1533 'percentage': percentage.round() |
| 1534 }); |
1570 | 1535 |
1571 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 1536 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; |
1572 for (LibraryElement library in compiler.libraryLoader.libraries) { | 1537 for (LibraryElement library in compiler.libraryLoader.libraries) { |
1573 if (library.isInternalLibrary) continue; | 1538 if (library.isInternalLibrary) continue; |
1574 for (ImportElement import in library.imports) { | 1539 for (ImportElement import in library.imports) { |
1575 LibraryElement importedLibrary = import.importedLibrary; | 1540 LibraryElement importedLibrary = import.importedLibrary; |
1576 if (importedLibrary != compiler.mirrorsLibrary) continue; | 1541 if (importedLibrary != compiler.mirrorsLibrary) continue; |
1577 MessageKind kind = | 1542 MessageKind kind = |
1578 compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(library) | 1543 compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(library) |
1579 ? MessageKind.MIRROR_IMPORT | 1544 ? MessageKind.MIRROR_IMPORT |
1580 : MessageKind.MIRROR_IMPORT_NO_USAGE; | 1545 : MessageKind.MIRROR_IMPORT_NO_USAGE; |
1581 reporter.withCurrentElement(library, () { | 1546 reporter.withCurrentElement(library, () { |
1582 infos.add(reporter.createMessage(import, kind)); | 1547 infos.add(reporter.createMessage(import, kind)); |
1583 }); | 1548 }); |
1584 } | 1549 } |
1585 } | 1550 } |
1586 reporter.reportHint(hint, infos); | 1551 reporter.reportHint(hint, infos); |
1587 } | 1552 } |
1588 return programSize; | 1553 return programSize; |
1589 } | 1554 } |
1590 | 1555 |
1591 Element getDartClass(Element element) { | 1556 Element getDartClass(Element element) { |
1592 for (ClassElement dartClass in implementationClasses.keys) { | 1557 for (ClassElement dartClass in implementationClasses.keys) { |
1593 if (element == implementationClasses[dartClass]) { | 1558 if (element == implementationClasses[dartClass]) { |
1594 return dartClass; | 1559 return dartClass; |
1595 } | 1560 } |
1596 } | 1561 } |
1597 return element; | 1562 return element; |
1598 } | 1563 } |
1599 | 1564 |
1600 /** | 1565 /** |
1601 * Returns the checked mode helper that will be needed to do a type check/type | 1566 * Returns the checked mode helper that will be needed to do a type check/type |
1602 * cast on [type] at runtime. Note that this method is being called both by | 1567 * cast on [type] at runtime. Note that this method is being called both by |
1603 * the resolver with interface types (int, String, ...), and by the SSA | 1568 * the resolver with interface types (int, String, ...), and by the SSA |
1604 * backend with implementation types (JSInt, JSString, ...). | 1569 * backend with implementation types (JSInt, JSString, ...). |
1605 */ | 1570 */ |
1606 CheckedModeHelper getCheckedModeHelper(DartType type, {bool typeCast}) { | 1571 CheckedModeHelper getCheckedModeHelper(DartType type, {bool typeCast}) { |
1607 return getCheckedModeHelperInternal( | 1572 return getCheckedModeHelperInternal(type, |
1608 type, typeCast: typeCast, nativeCheckOnly: false); | 1573 typeCast: typeCast, nativeCheckOnly: false); |
1609 } | 1574 } |
1610 | 1575 |
1611 /** | 1576 /** |
1612 * Returns the native checked mode helper that will be needed to do a type | 1577 * Returns the native checked mode helper that will be needed to do a type |
1613 * check/type cast on [type] at runtime. If no native helper exists for | 1578 * check/type cast on [type] at runtime. If no native helper exists for |
1614 * [type], [:null:] is returned. | 1579 * [type], [:null:] is returned. |
1615 */ | 1580 */ |
1616 CheckedModeHelper getNativeCheckedModeHelper(DartType type, {bool typeCast}) { | 1581 CheckedModeHelper getNativeCheckedModeHelper(DartType type, {bool typeCast}) { |
1617 return getCheckedModeHelperInternal( | 1582 return getCheckedModeHelperInternal(type, |
1618 type, typeCast: typeCast, nativeCheckOnly: true); | 1583 typeCast: typeCast, nativeCheckOnly: true); |
1619 } | 1584 } |
1620 | 1585 |
1621 /** | 1586 /** |
1622 * Returns the checked mode helper for the type check/type cast for [type]. If | 1587 * Returns the checked mode helper for the type check/type cast for [type]. If |
1623 * [nativeCheckOnly] is [:true:], only names for native helpers are returned. | 1588 * [nativeCheckOnly] is [:true:], only names for native helpers are returned. |
1624 */ | 1589 */ |
1625 CheckedModeHelper getCheckedModeHelperInternal(DartType type, | 1590 CheckedModeHelper getCheckedModeHelperInternal(DartType type, |
1626 {bool typeCast, | 1591 {bool typeCast, bool nativeCheckOnly}) { |
1627 bool nativeCheckOnly}) { | |
1628 String name = getCheckedModeHelperNameInternal(type, | 1592 String name = getCheckedModeHelperNameInternal(type, |
1629 typeCast: typeCast, nativeCheckOnly: nativeCheckOnly); | 1593 typeCast: typeCast, nativeCheckOnly: nativeCheckOnly); |
1630 if (name == null) return null; | 1594 if (name == null) return null; |
1631 CheckedModeHelper helper = checkedModeHelperByName[name]; | 1595 CheckedModeHelper helper = checkedModeHelperByName[name]; |
1632 assert(helper != null); | 1596 assert(helper != null); |
1633 return helper; | 1597 return helper; |
1634 } | 1598 } |
1635 | 1599 |
1636 String getCheckedModeHelperNameInternal(DartType type, | 1600 String getCheckedModeHelperNameInternal(DartType type, |
1637 {bool typeCast, | 1601 {bool typeCast, bool nativeCheckOnly}) { |
1638 bool nativeCheckOnly}) { | |
1639 assert(type.kind != TypeKind.TYPEDEF); | 1602 assert(type.kind != TypeKind.TYPEDEF); |
1640 if (type.isMalformed) { | 1603 if (type.isMalformed) { |
1641 // The same error is thrown for type test and type cast of a malformed | 1604 // The same error is thrown for type test and type cast of a malformed |
1642 // type so we only need one check method. | 1605 // type so we only need one check method. |
1643 return 'checkMalformedType'; | 1606 return 'checkMalformedType'; |
1644 } | 1607 } |
1645 Element element = type.element; | 1608 Element element = type.element; |
1646 bool nativeCheck = nativeCheckOnly || | 1609 bool nativeCheck = |
1647 emitter.nativeEmitter.requiresNativeIsCheck(element); | 1610 nativeCheckOnly || emitter.nativeEmitter.requiresNativeIsCheck(element); |
1648 | 1611 |
1649 // TODO(13955), TODO(9731). The test for non-primitive types should use an | 1612 // TODO(13955), TODO(9731). The test for non-primitive types should use an |
1650 // interceptor. The interceptor should be an argument to HTypeConversion so | 1613 // interceptor. The interceptor should be an argument to HTypeConversion so |
1651 // that it can be optimized by standard interceptor optimizations. | 1614 // that it can be optimized by standard interceptor optimizations. |
1652 nativeCheck = true; | 1615 nativeCheck = true; |
1653 | 1616 |
1654 if (type.isVoid) { | 1617 if (type.isVoid) { |
1655 assert(!typeCast); // Cannot cast to void. | 1618 assert(!typeCast); // Cannot cast to void. |
1656 if (nativeCheckOnly) return null; | 1619 if (nativeCheckOnly) return null; |
1657 return 'voidTypeCheck'; | 1620 return 'voidTypeCheck'; |
1658 } else if (element == helpers.jsStringClass || | 1621 } else if (element == helpers.jsStringClass || |
1659 element == coreClasses.stringClass) { | 1622 element == coreClasses.stringClass) { |
1660 if (nativeCheckOnly) return null; | 1623 if (nativeCheckOnly) return null; |
1661 return typeCast | 1624 return typeCast ? 'stringTypeCast' : 'stringTypeCheck'; |
1662 ? 'stringTypeCast' | |
1663 : 'stringTypeCheck'; | |
1664 } else if (element == helpers.jsDoubleClass || | 1625 } else if (element == helpers.jsDoubleClass || |
1665 element == coreClasses.doubleClass) { | 1626 element == coreClasses.doubleClass) { |
1666 if (nativeCheckOnly) return null; | 1627 if (nativeCheckOnly) return null; |
1667 return typeCast | 1628 return typeCast ? 'doubleTypeCast' : 'doubleTypeCheck'; |
1668 ? 'doubleTypeCast' | |
1669 : 'doubleTypeCheck'; | |
1670 } else if (element == helpers.jsNumberClass || | 1629 } else if (element == helpers.jsNumberClass || |
1671 element == coreClasses.numClass) { | 1630 element == coreClasses.numClass) { |
1672 if (nativeCheckOnly) return null; | 1631 if (nativeCheckOnly) return null; |
1673 return typeCast | 1632 return typeCast ? 'numTypeCast' : 'numTypeCheck'; |
1674 ? 'numTypeCast' | |
1675 : 'numTypeCheck'; | |
1676 } else if (element == helpers.jsBoolClass || | 1633 } else if (element == helpers.jsBoolClass || |
1677 element == coreClasses.boolClass) { | 1634 element == coreClasses.boolClass) { |
1678 if (nativeCheckOnly) return null; | 1635 if (nativeCheckOnly) return null; |
1679 return typeCast | 1636 return typeCast ? 'boolTypeCast' : 'boolTypeCheck'; |
1680 ? 'boolTypeCast' | |
1681 : 'boolTypeCheck'; | |
1682 } else if (element == helpers.jsIntClass || | 1637 } else if (element == helpers.jsIntClass || |
1683 element == coreClasses.intClass || | 1638 element == coreClasses.intClass || |
1684 element == helpers.jsUInt32Class || | 1639 element == helpers.jsUInt32Class || |
1685 element == helpers.jsUInt31Class || | 1640 element == helpers.jsUInt31Class || |
1686 element == helpers.jsPositiveIntClass) { | 1641 element == helpers.jsPositiveIntClass) { |
1687 if (nativeCheckOnly) return null; | 1642 if (nativeCheckOnly) return null; |
1688 return typeCast | 1643 return typeCast ? 'intTypeCast' : 'intTypeCheck'; |
1689 ? 'intTypeCast' | |
1690 : 'intTypeCheck'; | |
1691 } else if (Elements.isNumberOrStringSupertype(element, compiler)) { | 1644 } else if (Elements.isNumberOrStringSupertype(element, compiler)) { |
1692 if (nativeCheck) { | 1645 if (nativeCheck) { |
1693 return typeCast | 1646 return typeCast |
1694 ? 'numberOrStringSuperNativeTypeCast' | 1647 ? 'numberOrStringSuperNativeTypeCast' |
1695 : 'numberOrStringSuperNativeTypeCheck'; | 1648 : 'numberOrStringSuperNativeTypeCheck'; |
1696 } else { | 1649 } else { |
1697 return typeCast | 1650 return typeCast |
1698 ? 'numberOrStringSuperTypeCast' | 1651 ? 'numberOrStringSuperTypeCast' |
1699 : 'numberOrStringSuperTypeCheck'; | 1652 : 'numberOrStringSuperTypeCheck'; |
1700 } | 1653 } |
1701 } else if (Elements.isStringOnlySupertype(element, compiler)) { | 1654 } else if (Elements.isStringOnlySupertype(element, compiler)) { |
1702 if (nativeCheck) { | 1655 if (nativeCheck) { |
1703 return typeCast | 1656 return typeCast |
1704 ? 'stringSuperNativeTypeCast' | 1657 ? 'stringSuperNativeTypeCast' |
1705 : 'stringSuperNativeTypeCheck'; | 1658 : 'stringSuperNativeTypeCheck'; |
1706 } else { | 1659 } else { |
1707 return typeCast | 1660 return typeCast ? 'stringSuperTypeCast' : 'stringSuperTypeCheck'; |
1708 ? 'stringSuperTypeCast' | |
1709 : 'stringSuperTypeCheck'; | |
1710 } | 1661 } |
1711 } else if ((element == coreClasses.listClass || | 1662 } else if ((element == coreClasses.listClass || |
1712 element == helpers.jsArrayClass) && | 1663 element == helpers.jsArrayClass) && |
1713 type.treatAsRaw) { | 1664 type.treatAsRaw) { |
1714 if (nativeCheckOnly) return null; | 1665 if (nativeCheckOnly) return null; |
1715 return typeCast | 1666 return typeCast ? 'listTypeCast' : 'listTypeCheck'; |
1716 ? 'listTypeCast' | |
1717 : 'listTypeCheck'; | |
1718 } else { | 1667 } else { |
1719 if (Elements.isListSupertype(element, compiler)) { | 1668 if (Elements.isListSupertype(element, compiler)) { |
1720 if (nativeCheck) { | 1669 if (nativeCheck) { |
1721 return typeCast | 1670 return typeCast |
1722 ? 'listSuperNativeTypeCast' | 1671 ? 'listSuperNativeTypeCast' |
1723 : 'listSuperNativeTypeCheck'; | 1672 : 'listSuperNativeTypeCheck'; |
1724 } else { | 1673 } else { |
1725 return typeCast | 1674 return typeCast ? 'listSuperTypeCast' : 'listSuperTypeCheck'; |
1726 ? 'listSuperTypeCast' | |
1727 : 'listSuperTypeCheck'; | |
1728 } | 1675 } |
1729 } else { | 1676 } else { |
1730 if (type.isInterfaceType && !type.treatAsRaw) { | 1677 if (type.isInterfaceType && !type.treatAsRaw) { |
1731 return typeCast | 1678 return typeCast ? 'subtypeCast' : 'assertSubtype'; |
1732 ? 'subtypeCast' | |
1733 : 'assertSubtype'; | |
1734 } else if (type.isTypeVariable) { | 1679 } else if (type.isTypeVariable) { |
1735 return typeCast | 1680 return typeCast |
1736 ? 'subtypeOfRuntimeTypeCast' | 1681 ? 'subtypeOfRuntimeTypeCast' |
1737 : 'assertSubtypeOfRuntimeType'; | 1682 : 'assertSubtypeOfRuntimeType'; |
1738 } else if (type.isFunctionType) { | 1683 } else if (type.isFunctionType) { |
1739 return null; | 1684 return null; |
1740 } else { | 1685 } else { |
1741 if (nativeCheck) { | 1686 if (nativeCheck) { |
1742 // TODO(karlklose): can we get rid of this branch when we use | 1687 // TODO(karlklose): can we get rid of this branch when we use |
1743 // interceptors? | 1688 // interceptors? |
1744 return typeCast | 1689 return typeCast ? 'interceptedTypeCast' : 'interceptedTypeCheck'; |
1745 ? 'interceptedTypeCast' | |
1746 : 'interceptedTypeCheck'; | |
1747 } else { | 1690 } else { |
1748 return typeCast | 1691 return typeCast ? 'propertyTypeCast' : 'propertyTypeCheck'; |
1749 ? 'propertyTypeCast' | |
1750 : 'propertyTypeCheck'; | |
1751 } | 1692 } |
1752 } | 1693 } |
1753 } | 1694 } |
1754 } | 1695 } |
1755 } | 1696 } |
1756 | 1697 |
1757 void registerCheckedModeHelpers(Registry registry) { | 1698 void registerCheckedModeHelpers(Registry registry) { |
1758 // We register all the helpers in the resolution queue. | 1699 // We register all the helpers in the resolution queue. |
1759 // TODO(13155): Find a way to register fewer helpers. | 1700 // TODO(13155): Find a way to register fewer helpers. |
1760 for (CheckedModeHelper helper in checkedModeHelpers) { | 1701 for (CheckedModeHelper helper in checkedModeHelpers) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1824 } else if (element == helpers.preserveUrisMarker) { | 1765 } else if (element == helpers.preserveUrisMarker) { |
1825 if (compiler.options.preserveUris) mustPreserveUris = true; | 1766 if (compiler.options.preserveUris) mustPreserveUris = true; |
1826 } else if (element == helpers.preserveLibraryNamesMarker) { | 1767 } else if (element == helpers.preserveLibraryNamesMarker) { |
1827 mustRetainLibraryNames = true; | 1768 mustRetainLibraryNames = true; |
1828 } else if (element == helpers.getIsolateAffinityTagMarker) { | 1769 } else if (element == helpers.getIsolateAffinityTagMarker) { |
1829 needToInitializeIsolateAffinityTag = true; | 1770 needToInitializeIsolateAffinityTag = true; |
1830 } else if (element.isDeferredLoaderGetter) { | 1771 } else if (element.isDeferredLoaderGetter) { |
1831 // TODO(sigurdm): Create a function registerLoadLibraryAccess. | 1772 // TODO(sigurdm): Create a function registerLoadLibraryAccess. |
1832 if (compiler.loadLibraryFunction == null) { | 1773 if (compiler.loadLibraryFunction == null) { |
1833 compiler.loadLibraryFunction = helpers.loadLibraryWrapper; | 1774 compiler.loadLibraryFunction = helpers.loadLibraryWrapper; |
1834 enqueueInResolution(compiler.loadLibraryFunction, | 1775 enqueueInResolution( |
1835 compiler.globalDependencies); | 1776 compiler.loadLibraryFunction, compiler.globalDependencies); |
1836 } | 1777 } |
1837 } else if (element == helpers.requiresPreambleMarker) { | 1778 } else if (element == helpers.requiresPreambleMarker) { |
1838 requiresPreamble = true; | 1779 requiresPreamble = true; |
1839 } | 1780 } |
1840 customElementsAnalysis.registerStaticUse(element, enqueuer); | 1781 customElementsAnalysis.registerStaticUse(element, enqueuer); |
1841 } | 1782 } |
1842 | 1783 |
1843 /// Called when [:const Symbol(name):] is seen. | 1784 /// Called when [:const Symbol(name):] is seen. |
1844 void registerConstSymbol(String name) { | 1785 void registerConstSymbol(String name) { |
1845 symbolsUsed.add(name); | 1786 symbolsUsed.add(name); |
1846 if (name.endsWith('=')) { | 1787 if (name.endsWith('=')) { |
1847 symbolsUsed.add(name.substring(0, name.length - 1)); | 1788 symbolsUsed.add(name.substring(0, name.length - 1)); |
1848 } | 1789 } |
1849 } | 1790 } |
1850 | 1791 |
1851 /// Called when [:new Symbol(...):] is seen. | 1792 /// Called when [:new Symbol(...):] is seen. |
1852 void registerNewSymbol(Registry registry) { | 1793 void registerNewSymbol(Registry registry) {} |
1853 } | |
1854 | 1794 |
1855 /// Should [element] (a getter) that would normally not be generated due to | 1795 /// Should [element] (a getter) that would normally not be generated due to |
1856 /// treeshaking be retained for reflection? | 1796 /// treeshaking be retained for reflection? |
1857 bool shouldRetainGetter(Element element) { | 1797 bool shouldRetainGetter(Element element) { |
1858 return isTreeShakingDisabled && isAccessibleByReflection(element); | 1798 return isTreeShakingDisabled && isAccessibleByReflection(element); |
1859 } | 1799 } |
1860 | 1800 |
1861 /// Should [element] (a setter) hat would normally not be generated due to | 1801 /// Should [element] (a setter) hat would normally not be generated due to |
1862 /// treeshaking be retained for reflection? | 1802 /// treeshaking be retained for reflection? |
1863 bool shouldRetainSetter(Element element) { | 1803 bool shouldRetainSetter(Element element) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1923 implementationClasses = <ClassElement, ClassElement>{}; | 1863 implementationClasses = <ClassElement, ClassElement>{}; |
1924 implementationClasses[coreClasses.intClass] = helpers.jsIntClass; | 1864 implementationClasses[coreClasses.intClass] = helpers.jsIntClass; |
1925 implementationClasses[coreClasses.boolClass] = helpers.jsBoolClass; | 1865 implementationClasses[coreClasses.boolClass] = helpers.jsBoolClass; |
1926 implementationClasses[coreClasses.numClass] = helpers.jsNumberClass; | 1866 implementationClasses[coreClasses.numClass] = helpers.jsNumberClass; |
1927 implementationClasses[coreClasses.doubleClass] = helpers.jsDoubleClass; | 1867 implementationClasses[coreClasses.doubleClass] = helpers.jsDoubleClass; |
1928 implementationClasses[coreClasses.stringClass] = helpers.jsStringClass; | 1868 implementationClasses[coreClasses.stringClass] = helpers.jsStringClass; |
1929 implementationClasses[coreClasses.listClass] = helpers.jsArrayClass; | 1869 implementationClasses[coreClasses.listClass] = helpers.jsArrayClass; |
1930 implementationClasses[coreClasses.nullClass] = helpers.jsNullClass; | 1870 implementationClasses[coreClasses.nullClass] = helpers.jsNullClass; |
1931 | 1871 |
1932 // These methods are overwritten with generated versions. | 1872 // These methods are overwritten with generated versions. |
1933 inlineCache.markAsNonInlinable( | 1873 inlineCache.markAsNonInlinable(helpers.getInterceptorMethod, |
1934 helpers.getInterceptorMethod, insideLoop: true); | 1874 insideLoop: true); |
1935 | 1875 |
1936 specialOperatorEqClasses | 1876 specialOperatorEqClasses |
1937 ..add(coreClasses.objectClass) | 1877 ..add(coreClasses.objectClass) |
1938 ..add(helpers.jsInterceptorClass) | 1878 ..add(helpers.jsInterceptorClass) |
1939 ..add(helpers.jsNullClass); | 1879 ..add(helpers.jsNullClass); |
1940 | 1880 |
1941 validateInterceptorImplementsAllObjectMethods(helpers.jsInterceptorClass); | 1881 validateInterceptorImplementsAllObjectMethods(helpers.jsInterceptorClass); |
1942 // The null-interceptor must also implement *all* methods. | 1882 // The null-interceptor must also implement *all* methods. |
1943 validateInterceptorImplementsAllObjectMethods(helpers.jsNullClass); | 1883 validateInterceptorImplementsAllObjectMethods(helpers.jsNullClass); |
1944 | 1884 |
1945 return new Future.value(); | 1885 return new Future.value(); |
1946 } | 1886 } |
1947 | 1887 |
1948 void registerMirrorUsage(Set<String> symbols, | 1888 void registerMirrorUsage( |
1949 Set<Element> targets, | 1889 Set<String> symbols, Set<Element> targets, Set<Element> metaTargets) { |
1950 Set<Element> metaTargets) { | |
1951 if (symbols == null && targets == null && metaTargets == null) { | 1890 if (symbols == null && targets == null && metaTargets == null) { |
1952 // The user didn't specify anything, or there are imports of | 1891 // The user didn't specify anything, or there are imports of |
1953 // 'dart:mirrors' without @MirrorsUsed. | 1892 // 'dart:mirrors' without @MirrorsUsed. |
1954 hasInsufficientMirrorsUsed = true; | 1893 hasInsufficientMirrorsUsed = true; |
1955 return; | 1894 return; |
1956 } | 1895 } |
1957 if (symbols != null) symbolsUsed.addAll(symbols); | 1896 if (symbols != null) symbolsUsed.addAll(symbols); |
1958 if (targets != null) { | 1897 if (targets != null) { |
1959 for (Element target in targets) { | 1898 for (Element target in targets) { |
1960 if (target.isAbstractField) { | 1899 if (target.isAbstractField) { |
(...skipping 24 matching lines...) Expand all Loading... |
1985 return membersNeededForReflection.contains(element); | 1924 return membersNeededForReflection.contains(element); |
1986 } | 1925 } |
1987 | 1926 |
1988 /** | 1927 /** |
1989 * Returns true if the element has to be resolved due to a mirrorsUsed | 1928 * Returns true if the element has to be resolved due to a mirrorsUsed |
1990 * annotation. If we have insufficient mirrors used annotations, we only | 1929 * annotation. If we have insufficient mirrors used annotations, we only |
1991 * keep additonal elements if treeshaking has been disabled. | 1930 * keep additonal elements if treeshaking has been disabled. |
1992 */ | 1931 */ |
1993 bool requiredByMirrorSystem(Element element) { | 1932 bool requiredByMirrorSystem(Element element) { |
1994 return hasInsufficientMirrorsUsed && isTreeShakingDisabled || | 1933 return hasInsufficientMirrorsUsed && isTreeShakingDisabled || |
1995 matchesMirrorsMetaTarget(element) || | 1934 matchesMirrorsMetaTarget(element) || |
1996 targetsUsed.contains(element); | 1935 targetsUsed.contains(element); |
1997 } | 1936 } |
1998 | 1937 |
1999 /** | 1938 /** |
2000 * Returns true if the element matches a mirrorsUsed annotation. If | 1939 * Returns true if the element matches a mirrorsUsed annotation. If |
2001 * we have insufficient mirrorsUsed information, this returns true for | 1940 * we have insufficient mirrorsUsed information, this returns true for |
2002 * all elements, as they might all be potentially referenced. | 1941 * all elements, as they might all be potentially referenced. |
2003 */ | 1942 */ |
2004 bool referencedFromMirrorSystem(Element element, [recursive = true]) { | 1943 bool referencedFromMirrorSystem(Element element, [recursive = true]) { |
2005 Element enclosing = recursive ? element.enclosingElement : null; | 1944 Element enclosing = recursive ? element.enclosingElement : null; |
2006 | 1945 |
2007 return hasInsufficientMirrorsUsed || | 1946 return hasInsufficientMirrorsUsed || |
2008 matchesMirrorsMetaTarget(element) || | 1947 matchesMirrorsMetaTarget(element) || |
2009 targetsUsed.contains(element) || | 1948 targetsUsed.contains(element) || |
2010 (enclosing != null && referencedFromMirrorSystem(enclosing)); | 1949 (enclosing != null && referencedFromMirrorSystem(enclosing)); |
2011 } | 1950 } |
2012 | 1951 |
2013 /** | 1952 /** |
2014 * Returns `true` if the element is needed because it has an annotation | 1953 * Returns `true` if the element is needed because it has an annotation |
2015 * of a type that is used as a meta target for reflection. | 1954 * of a type that is used as a meta target for reflection. |
2016 */ | 1955 */ |
2017 bool matchesMirrorsMetaTarget(Element element) { | 1956 bool matchesMirrorsMetaTarget(Element element) { |
2018 if (metaTargetsUsed.isEmpty) return false; | 1957 if (metaTargetsUsed.isEmpty) return false; |
2019 for (MetadataAnnotation metadata in element.metadata) { | 1958 for (MetadataAnnotation metadata in element.metadata) { |
2020 // TODO(kasperl): It would be nice if we didn't have to resolve | 1959 // TODO(kasperl): It would be nice if we didn't have to resolve |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2173 // [computeMembersNeededForReflection]. | 2112 // [computeMembersNeededForReflection]. |
2174 void maybeMarkClosureAsNeededForReflection( | 2113 void maybeMarkClosureAsNeededForReflection( |
2175 ClosureClassElement globalizedElement, | 2114 ClosureClassElement globalizedElement, |
2176 FunctionElement callFunction, | 2115 FunctionElement callFunction, |
2177 FunctionElement function) { | 2116 FunctionElement function) { |
2178 if (!_membersNeededForReflection.contains(function)) return; | 2117 if (!_membersNeededForReflection.contains(function)) return; |
2179 _membersNeededForReflection.add(callFunction); | 2118 _membersNeededForReflection.add(callFunction); |
2180 _membersNeededForReflection.add(globalizedElement); | 2119 _membersNeededForReflection.add(globalizedElement); |
2181 } | 2120 } |
2182 | 2121 |
2183 jsAst.Call generateIsJsIndexableCall(jsAst.Expression use1, | 2122 jsAst.Call generateIsJsIndexableCall( |
2184 jsAst.Expression use2) { | 2123 jsAst.Expression use1, jsAst.Expression use2) { |
2185 String dispatchPropertyName = embeddedNames.DISPATCH_PROPERTY_NAME; | 2124 String dispatchPropertyName = embeddedNames.DISPATCH_PROPERTY_NAME; |
2186 jsAst.Expression dispatchProperty = | 2125 jsAst.Expression dispatchProperty = |
2187 emitter.generateEmbeddedGlobalAccess(dispatchPropertyName); | 2126 emitter.generateEmbeddedGlobalAccess(dispatchPropertyName); |
2188 | 2127 |
2189 // We pass the dispatch property record to the isJsIndexable | 2128 // We pass the dispatch property record to the isJsIndexable |
2190 // helper rather than reading it inside the helper to increase the | 2129 // helper rather than reading it inside the helper to increase the |
2191 // chance of making the dispatch record access monomorphic. | 2130 // chance of making the dispatch record access monomorphic. |
2192 jsAst.PropertyAccess record = | 2131 jsAst.PropertyAccess record = |
2193 new jsAst.PropertyAccess(use2, dispatchProperty); | 2132 new jsAst.PropertyAccess(use2, dispatchProperty); |
2194 | 2133 |
2195 List<jsAst.Expression> arguments = <jsAst.Expression>[use1, record]; | 2134 List<jsAst.Expression> arguments = <jsAst.Expression>[use1, record]; |
2196 FunctionElement helper = helpers.isJsIndexable; | 2135 FunctionElement helper = helpers.isJsIndexable; |
2197 jsAst.Expression helperExpression = emitter.staticFunctionAccess(helper); | 2136 jsAst.Expression helperExpression = emitter.staticFunctionAccess(helper); |
2198 return new jsAst.Call(helperExpression, arguments); | 2137 return new jsAst.Call(helperExpression, arguments); |
2199 } | 2138 } |
2200 | 2139 |
2201 bool isTypedArray(TypeMask mask) { | 2140 bool isTypedArray(TypeMask mask) { |
2202 // Just checking for [:TypedData:] is not sufficient, as it is an | 2141 // Just checking for [:TypedData:] is not sufficient, as it is an |
2203 // abstract class any user-defined class can implement. So we also | 2142 // abstract class any user-defined class can implement. So we also |
2204 // check for the interface [JavaScriptIndexingBehavior]. | 2143 // check for the interface [JavaScriptIndexingBehavior]. |
2205 return | 2144 return compiler.typedDataClass != null && |
2206 compiler.typedDataClass != null && | |
2207 compiler.world.isInstantiated(compiler.typedDataClass) && | 2145 compiler.world.isInstantiated(compiler.typedDataClass) && |
2208 mask.satisfies(compiler.typedDataClass, compiler.world) && | 2146 mask.satisfies(compiler.typedDataClass, compiler.world) && |
2209 mask.satisfies(helpers.jsIndexingBehaviorInterface, compiler.world); | 2147 mask.satisfies(helpers.jsIndexingBehaviorInterface, compiler.world); |
2210 } | 2148 } |
2211 | 2149 |
2212 bool couldBeTypedArray(TypeMask mask) { | 2150 bool couldBeTypedArray(TypeMask mask) { |
2213 bool intersects(TypeMask type1, TypeMask type2) => | 2151 bool intersects(TypeMask type1, TypeMask type2) => |
2214 !type1.intersection(type2, compiler.world).isEmpty; | 2152 !type1.intersection(type2, compiler.world).isEmpty; |
2215 // TODO(herhut): Maybe cache the TypeMask for typedDataClass and | 2153 // TODO(herhut): Maybe cache the TypeMask for typedDataClass and |
2216 // jsIndexingBehaviourInterface. | 2154 // jsIndexingBehaviourInterface. |
2217 return | 2155 return compiler.typedDataClass != null && |
2218 compiler.typedDataClass != null && | |
2219 compiler.world.isInstantiated(compiler.typedDataClass) && | 2156 compiler.world.isInstantiated(compiler.typedDataClass) && |
2220 intersects(mask, | 2157 intersects(mask, |
2221 new TypeMask.subtype(compiler.typedDataClass, compiler.world)) && | 2158 new TypeMask.subtype(compiler.typedDataClass, compiler.world)) && |
2222 intersects(mask, | 2159 intersects( |
2223 new TypeMask.subtype(helpers.jsIndexingBehaviorInterface, compiler.w
orld)); | 2160 mask, |
| 2161 new TypeMask.subtype( |
| 2162 helpers.jsIndexingBehaviorInterface, compiler.world)); |
2224 } | 2163 } |
2225 | 2164 |
2226 /// Returns all static fields that are referenced through [targetsUsed]. | 2165 /// Returns all static fields that are referenced through [targetsUsed]. |
2227 /// If the target is a library or class all nested static fields are | 2166 /// If the target is a library or class all nested static fields are |
2228 /// included too. | 2167 /// included too. |
2229 Iterable<Element> _findStaticFieldTargets() { | 2168 Iterable<Element> _findStaticFieldTargets() { |
2230 List staticFields = []; | 2169 List staticFields = []; |
2231 | 2170 |
2232 void addFieldsInContainer(ScopeContainerElement container) { | 2171 void addFieldsInContainer(ScopeContainerElement container) { |
2233 container.forEachLocalMember((Element member) { | 2172 container.forEachLocalMember((Element member) { |
(...skipping 19 matching lines...) Expand all Loading... |
2253 /// Called when [enqueuer] is empty, but before it is closed. | 2192 /// Called when [enqueuer] is empty, but before it is closed. |
2254 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassElement> recentClasses) { | 2193 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassElement> recentClasses) { |
2255 // Add elements referenced only via custom elements. Return early if any | 2194 // Add elements referenced only via custom elements. Return early if any |
2256 // elements are added to avoid counting the elements as due to mirrors. | 2195 // elements are added to avoid counting the elements as due to mirrors. |
2257 customElementsAnalysis.onQueueEmpty(enqueuer); | 2196 customElementsAnalysis.onQueueEmpty(enqueuer); |
2258 if (!enqueuer.queueIsEmpty) return false; | 2197 if (!enqueuer.queueIsEmpty) return false; |
2259 | 2198 |
2260 noSuchMethodRegistry.onQueueEmpty(); | 2199 noSuchMethodRegistry.onQueueEmpty(); |
2261 if (!enabledNoSuchMethod && | 2200 if (!enabledNoSuchMethod && |
2262 (noSuchMethodRegistry.hasThrowingNoSuchMethod || | 2201 (noSuchMethodRegistry.hasThrowingNoSuchMethod || |
2263 noSuchMethodRegistry.hasComplexNoSuchMethod)) { | 2202 noSuchMethodRegistry.hasComplexNoSuchMethod)) { |
2264 enableNoSuchMethod(enqueuer); | 2203 enableNoSuchMethod(enqueuer); |
2265 enabledNoSuchMethod = true; | 2204 enabledNoSuchMethod = true; |
2266 } | 2205 } |
2267 | 2206 |
2268 if (compiler.options.hasIncrementalSupport) { | 2207 if (compiler.options.hasIncrementalSupport) { |
2269 // Always enable tear-off closures during incremental compilation. | 2208 // Always enable tear-off closures during incremental compilation. |
2270 Element e = helpers.closureFromTearOff; | 2209 Element e = helpers.closureFromTearOff; |
2271 if (e != null && !enqueuer.isProcessed(e)) { | 2210 if (e != null && !enqueuer.isProcessed(e)) { |
2272 registerBackendUse(e); | 2211 registerBackendUse(e); |
2273 enqueuer.addToWorkList(e); | 2212 enqueuer.addToWorkList(e); |
(...skipping 13 matching lines...) Expand all Loading... |
2287 enqueuer.enqueueReflectiveStaticFields(_findStaticFieldTargets()); | 2226 enqueuer.enqueueReflectiveStaticFields(_findStaticFieldTargets()); |
2288 } | 2227 } |
2289 | 2228 |
2290 if (mustPreserveNames) reporter.log('Preserving names.'); | 2229 if (mustPreserveNames) reporter.log('Preserving names.'); |
2291 | 2230 |
2292 if (mustRetainMetadata) { | 2231 if (mustRetainMetadata) { |
2293 reporter.log('Retaining metadata.'); | 2232 reporter.log('Retaining metadata.'); |
2294 | 2233 |
2295 compiler.libraryLoader.libraries.forEach(retainMetadataOf); | 2234 compiler.libraryLoader.libraries.forEach(retainMetadataOf); |
2296 for (Dependency dependency in metadataConstants) { | 2235 for (Dependency dependency in metadataConstants) { |
2297 registerCompileTimeConstant( | 2236 registerCompileTimeConstant(dependency.constant, |
2298 dependency.constant, | |
2299 new EagerRegistry('EagerRegistry for ${dependency}', enqueuer)); | 2237 new EagerRegistry('EagerRegistry for ${dependency}', enqueuer)); |
2300 } | 2238 } |
2301 if (!enqueuer.isResolutionQueue) { | 2239 if (!enqueuer.isResolutionQueue) { |
2302 metadataConstants.clear(); | 2240 metadataConstants.clear(); |
2303 } | 2241 } |
2304 } | 2242 } |
2305 return true; | 2243 return true; |
2306 } | 2244 } |
2307 | 2245 |
2308 void onQueueClosed() { | 2246 void onQueueClosed() { |
(...skipping 27 matching lines...) Expand all Loading... |
2336 metadata.ensureResolved(resolution); | 2274 metadata.ensureResolved(resolution); |
2337 ConstantValue constantValue = | 2275 ConstantValue constantValue = |
2338 compiler.constants.getConstantValue(metadata.constant); | 2276 compiler.constants.getConstantValue(metadata.constant); |
2339 if (!constantValue.isConstructedObject) continue; | 2277 if (!constantValue.isConstructedObject) continue; |
2340 ObjectConstantValue value = constantValue; | 2278 ObjectConstantValue value = constantValue; |
2341 ClassElement cls = value.type.element; | 2279 ClassElement cls = value.type.element; |
2342 if (cls == helpers.forceInlineClass) { | 2280 if (cls == helpers.forceInlineClass) { |
2343 hasForceInline = true; | 2281 hasForceInline = true; |
2344 if (VERBOSE_OPTIMIZER_HINTS) { | 2282 if (VERBOSE_OPTIMIZER_HINTS) { |
2345 reporter.reportHintMessage( | 2283 reporter.reportHintMessage( |
2346 element, | 2284 element, MessageKind.GENERIC, {'text': "Must inline"}); |
2347 MessageKind.GENERIC, | |
2348 {'text': "Must inline"}); | |
2349 } | 2285 } |
2350 inlineCache.markAsMustInline(element); | 2286 inlineCache.markAsMustInline(element); |
2351 } else if (cls == helpers.noInlineClass) { | 2287 } else if (cls == helpers.noInlineClass) { |
2352 hasNoInline = true; | 2288 hasNoInline = true; |
2353 if (VERBOSE_OPTIMIZER_HINTS) { | 2289 if (VERBOSE_OPTIMIZER_HINTS) { |
2354 reporter.reportHintMessage( | 2290 reporter.reportHintMessage( |
2355 element, | 2291 element, MessageKind.GENERIC, {'text': "Cannot inline"}); |
2356 MessageKind.GENERIC, | |
2357 {'text': "Cannot inline"}); | |
2358 } | 2292 } |
2359 inlineCache.markAsNonInlinable(element); | 2293 inlineCache.markAsNonInlinable(element); |
2360 } else if (cls == helpers.noThrowsClass) { | 2294 } else if (cls == helpers.noThrowsClass) { |
2361 hasNoThrows = true; | 2295 hasNoThrows = true; |
2362 if (!Elements.isStaticOrTopLevelFunction(element) && | 2296 if (!Elements.isStaticOrTopLevelFunction(element) && |
2363 !element.isFactoryConstructor) { | 2297 !element.isFactoryConstructor) { |
2364 reporter.internalError(element, | 2298 reporter.internalError( |
| 2299 element, |
2365 "@NoThrows() is currently limited to top-level" | 2300 "@NoThrows() is currently limited to top-level" |
2366 " or static functions and factory constructors."); | 2301 " or static functions and factory constructors."); |
2367 } | 2302 } |
2368 if (VERBOSE_OPTIMIZER_HINTS) { | 2303 if (VERBOSE_OPTIMIZER_HINTS) { |
2369 reporter.reportHintMessage( | 2304 reporter.reportHintMessage( |
2370 element, | 2305 element, MessageKind.GENERIC, {'text': "Cannot throw"}); |
2371 MessageKind.GENERIC, | |
2372 {'text': "Cannot throw"}); | |
2373 } | 2306 } |
2374 compiler.world.registerCannotThrow(element); | 2307 compiler.world.registerCannotThrow(element); |
2375 } else if (cls == helpers.noSideEffectsClass) { | 2308 } else if (cls == helpers.noSideEffectsClass) { |
2376 hasNoSideEffects = true; | 2309 hasNoSideEffects = true; |
2377 if (VERBOSE_OPTIMIZER_HINTS) { | 2310 if (VERBOSE_OPTIMIZER_HINTS) { |
2378 reporter.reportHintMessage( | 2311 reporter.reportHintMessage( |
2379 element, | 2312 element, MessageKind.GENERIC, {'text': "Has no side effects"}); |
2380 MessageKind.GENERIC, | |
2381 {'text': "Has no side effects"}); | |
2382 } | 2313 } |
2383 compiler.world.registerSideEffectsFree(element); | 2314 compiler.world.registerSideEffectsFree(element); |
2384 } | 2315 } |
2385 } | 2316 } |
2386 if (hasForceInline && hasNoInline) { | 2317 if (hasForceInline && hasNoInline) { |
2387 reporter.internalError(element, | 2318 reporter.internalError( |
2388 "@ForceInline() must not be used with @NoInline."); | 2319 element, "@ForceInline() must not be used with @NoInline."); |
2389 } | 2320 } |
2390 if (hasNoThrows && !hasNoInline) { | 2321 if (hasNoThrows && !hasNoInline) { |
2391 reporter.internalError(element, | 2322 reporter.internalError( |
2392 "@NoThrows() should always be combined with @NoInline."); | 2323 element, "@NoThrows() should always be combined with @NoInline."); |
2393 } | 2324 } |
2394 if (hasNoSideEffects && !hasNoInline) { | 2325 if (hasNoSideEffects && !hasNoInline) { |
2395 reporter.internalError(element, | 2326 reporter.internalError(element, |
2396 "@NoSideEffects() should always be combined with @NoInline."); | 2327 "@NoSideEffects() should always be combined with @NoInline."); |
2397 } | 2328 } |
2398 if (element == helpers.invokeOnMethod) { | 2329 if (element == helpers.invokeOnMethod) { |
2399 compiler.enabledInvokeOn = true; | 2330 compiler.enabledInvokeOn = true; |
2400 } | 2331 } |
2401 } | 2332 } |
| 2333 |
2402 /* | 2334 /* |
2403 CodeBuffer codeOf(Element element) { | 2335 CodeBuffer codeOf(Element element) { |
2404 return generatedCode.containsKey(element) | 2336 return generatedCode.containsKey(element) |
2405 ? jsAst.prettyPrint(generatedCode[element], compiler) | 2337 ? jsAst.prettyPrint(generatedCode[element], compiler) |
2406 : null; | 2338 : null; |
2407 } | 2339 } |
2408 */ | 2340 */ |
2409 FunctionElement helperForBadMain() => helpers.badMain; | 2341 FunctionElement helperForBadMain() => helpers.badMain; |
2410 | 2342 |
2411 FunctionElement helperForMissingMain() => helpers.missingMain; | 2343 FunctionElement helperForMissingMain() => helpers.missingMain; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2443 @override | 2375 @override |
2444 bool enableDeferredLoadingIfSupported(Spannable node, Registry registry) { | 2376 bool enableDeferredLoadingIfSupported(Spannable node, Registry registry) { |
2445 registerCheckDeferredIsLoaded(registry); | 2377 registerCheckDeferredIsLoaded(registry); |
2446 return true; | 2378 return true; |
2447 } | 2379 } |
2448 | 2380 |
2449 @override | 2381 @override |
2450 bool enableCodegenWithErrorsIfSupported(Spannable node) { | 2382 bool enableCodegenWithErrorsIfSupported(Spannable node) { |
2451 if (compiler.options.useCpsIr) { | 2383 if (compiler.options.useCpsIr) { |
2452 // TODO(25747): Support code generation with compile-time errors. | 2384 // TODO(25747): Support code generation with compile-time errors. |
2453 reporter.reportHintMessage( | 2385 reporter.reportHintMessage(node, MessageKind.GENERIC, { |
2454 node, | 2386 'text': "Generation of code with compile time errors is currently " |
2455 MessageKind.GENERIC, | 2387 "not supported with the CPS IR." |
2456 {'text': "Generation of code with compile time errors is currently " | 2388 }); |
2457 "not supported with the CPS IR."}); | |
2458 return false; | 2389 return false; |
2459 } | 2390 } |
2460 return true; | 2391 return true; |
2461 } | 2392 } |
2462 | 2393 |
2463 jsAst.Expression rewriteAsync(FunctionElement element, | 2394 jsAst.Expression rewriteAsync( |
2464 jsAst.Expression code) { | 2395 FunctionElement element, jsAst.Expression code) { |
2465 AsyncRewriterBase rewriter = null; | 2396 AsyncRewriterBase rewriter = null; |
2466 jsAst.Name name = namer.methodPropertyName(element); | 2397 jsAst.Name name = namer.methodPropertyName(element); |
2467 switch (element.asyncMarker) { | 2398 switch (element.asyncMarker) { |
2468 case AsyncMarker.ASYNC: | 2399 case AsyncMarker.ASYNC: |
2469 rewriter = new AsyncRewriter( | 2400 rewriter = new AsyncRewriter(reporter, element, |
2470 reporter, | 2401 asyncHelper: emitter.staticFunctionAccess(helpers.asyncHelper), |
2471 element, | 2402 wrapBody: emitter.staticFunctionAccess(helpers.wrapBody), |
2472 asyncHelper: | 2403 newCompleter: |
2473 emitter.staticFunctionAccess(helpers.asyncHelper), | 2404 emitter.staticFunctionAccess(helpers.syncCompleterConstructor), |
2474 wrapBody: | |
2475 emitter.staticFunctionAccess(helpers.wrapBody), | |
2476 newCompleter: emitter.staticFunctionAccess( | |
2477 helpers.syncCompleterConstructor), | |
2478 safeVariableName: namer.safeVariablePrefixForAsyncRewrite, | 2405 safeVariableName: namer.safeVariablePrefixForAsyncRewrite, |
2479 bodyName: namer.deriveAsyncBodyName(name)); | 2406 bodyName: namer.deriveAsyncBodyName(name)); |
2480 break; | 2407 break; |
2481 case AsyncMarker.SYNC_STAR: | 2408 case AsyncMarker.SYNC_STAR: |
2482 rewriter = new SyncStarRewriter( | 2409 rewriter = new SyncStarRewriter(reporter, element, |
2483 reporter, | 2410 endOfIteration: |
2484 element, | 2411 emitter.staticFunctionAccess(helpers.endOfIteration), |
2485 endOfIteration: emitter.staticFunctionAccess( | 2412 newIterable: emitter |
2486 helpers.endOfIteration), | 2413 .staticFunctionAccess(helpers.syncStarIterableConstructor), |
2487 newIterable: emitter.staticFunctionAccess( | 2414 yieldStarExpression: |
2488 helpers.syncStarIterableConstructor), | 2415 emitter.staticFunctionAccess(helpers.yieldStar), |
2489 yieldStarExpression: emitter.staticFunctionAccess( | 2416 uncaughtErrorExpression: |
2490 helpers.yieldStar), | 2417 emitter.staticFunctionAccess(helpers.syncStarUncaughtError), |
2491 uncaughtErrorExpression: emitter.staticFunctionAccess( | |
2492 helpers.syncStarUncaughtError), | |
2493 safeVariableName: namer.safeVariablePrefixForAsyncRewrite, | 2418 safeVariableName: namer.safeVariablePrefixForAsyncRewrite, |
2494 bodyName: namer.deriveAsyncBodyName(name)); | 2419 bodyName: namer.deriveAsyncBodyName(name)); |
2495 break; | 2420 break; |
2496 case AsyncMarker.ASYNC_STAR: | 2421 case AsyncMarker.ASYNC_STAR: |
2497 rewriter = new AsyncStarRewriter( | 2422 rewriter = new AsyncStarRewriter(reporter, element, |
2498 reporter, | 2423 asyncStarHelper: |
2499 element, | 2424 emitter.staticFunctionAccess(helpers.asyncStarHelper), |
2500 asyncStarHelper: emitter.staticFunctionAccess( | 2425 streamOfController: |
2501 helpers.asyncStarHelper), | 2426 emitter.staticFunctionAccess(helpers.streamOfController), |
2502 streamOfController: emitter.staticFunctionAccess( | 2427 wrapBody: emitter.staticFunctionAccess(helpers.wrapBody), |
2503 helpers.streamOfController), | 2428 newController: emitter |
2504 wrapBody: | 2429 .staticFunctionAccess(helpers.asyncStarControllerConstructor), |
2505 emitter.staticFunctionAccess(helpers.wrapBody), | |
2506 newController: emitter.staticFunctionAccess( | |
2507 helpers.asyncStarControllerConstructor), | |
2508 safeVariableName: namer.safeVariablePrefixForAsyncRewrite, | 2430 safeVariableName: namer.safeVariablePrefixForAsyncRewrite, |
2509 yieldExpression: emitter.staticFunctionAccess( | 2431 yieldExpression: emitter.staticFunctionAccess(helpers.yieldSingle), |
2510 helpers.yieldSingle), | 2432 yieldStarExpression: |
2511 yieldStarExpression: emitter.staticFunctionAccess( | 2433 emitter.staticFunctionAccess(helpers.yieldStar), |
2512 helpers.yieldStar), | |
2513 bodyName: namer.deriveAsyncBodyName(name)); | 2434 bodyName: namer.deriveAsyncBodyName(name)); |
2514 break; | 2435 break; |
2515 default: | 2436 default: |
2516 assert(element.asyncMarker == AsyncMarker.SYNC); | 2437 assert(element.asyncMarker == AsyncMarker.SYNC); |
2517 return code; | 2438 return code; |
2518 } | 2439 } |
2519 return rewriter.rewrite(code); | 2440 return rewriter.rewrite(code); |
2520 } | 2441 } |
2521 | 2442 |
2522 /// The locations of js patch-files relative to the sdk-descriptors. | 2443 /// The locations of js patch-files relative to the sdk-descriptors. |
2523 static const _patchLocations = const <String, String>{ | 2444 static const _patchLocations = const <String, String>{ |
2524 "async": "_internal/js_runtime/lib/async_patch.dart", | 2445 "async": "_internal/js_runtime/lib/async_patch.dart", |
2525 "collection": "_internal/js_runtime/lib/collection_patch.dart", | 2446 "collection": "_internal/js_runtime/lib/collection_patch.dart", |
2526 "convert": "_internal/js_runtime/lib/convert_patch.dart", | 2447 "convert": "_internal/js_runtime/lib/convert_patch.dart", |
2527 "core": "_internal/js_runtime/lib/core_patch.dart", | 2448 "core": "_internal/js_runtime/lib/core_patch.dart", |
2528 "developer": "_internal/js_runtime/lib/developer_patch.dart", | 2449 "developer": "_internal/js_runtime/lib/developer_patch.dart", |
2529 "io": "_internal/js_runtime/lib/io_patch.dart", | 2450 "io": "_internal/js_runtime/lib/io_patch.dart", |
2530 "isolate": "_internal/js_runtime/lib/isolate_patch.dart", | 2451 "isolate": "_internal/js_runtime/lib/isolate_patch.dart", |
2531 "math": "_internal/js_runtime/lib/math_patch.dart", | 2452 "math": "_internal/js_runtime/lib/math_patch.dart", |
2532 "mirrors": "_internal/js_runtime/lib/mirrors_patch.dart", | 2453 "mirrors": "_internal/js_runtime/lib/mirrors_patch.dart", |
2533 "typed_data": "_internal/js_runtime/lib/typed_data_patch.dart", | 2454 "typed_data": "_internal/js_runtime/lib/typed_data_patch.dart", |
2534 "_internal": "_internal/js_runtime/lib/internal_patch.dart" | 2455 "_internal": "_internal/js_runtime/lib/internal_patch.dart" |
2535 }; | 2456 }; |
2536 | 2457 |
2537 @override | 2458 @override |
2538 Uri resolvePatchUri(String libraryName, Uri platformConfigUri) { | 2459 Uri resolvePatchUri(String libraryName, Uri platformConfigUri) { |
2539 String patchLocation = _patchLocations[libraryName]; | 2460 String patchLocation = _patchLocations[libraryName]; |
2540 if (patchLocation == null) return null; | 2461 if (patchLocation == null) return null; |
2541 return platformConfigUri.resolve(patchLocation); | 2462 return platformConfigUri.resolve(patchLocation); |
2542 } | 2463 } |
2543 | 2464 |
2544 @override | 2465 @override |
2545 ImpactStrategy createImpactStrategy( | 2466 ImpactStrategy createImpactStrategy( |
2546 {bool supportDeferredLoad: true, | 2467 {bool supportDeferredLoad: true, |
2547 bool supportDumpInfo: true, | 2468 bool supportDumpInfo: true, |
2548 bool supportSerialization: true}) { | 2469 bool supportSerialization: true}) { |
2549 return new JavaScriptImpactStrategy( | 2470 return new JavaScriptImpactStrategy(resolution, compiler.dumpInfoTask, |
2550 resolution, | |
2551 compiler.dumpInfoTask, | |
2552 supportDeferredLoad: supportDeferredLoad, | 2471 supportDeferredLoad: supportDeferredLoad, |
2553 supportDumpInfo: supportDumpInfo, | 2472 supportDumpInfo: supportDumpInfo, |
2554 supportSerialization: supportSerialization); | 2473 supportSerialization: supportSerialization); |
2555 } | 2474 } |
2556 } | 2475 } |
2557 | 2476 |
2558 /// Handling of special annotations for tests. | 2477 /// Handling of special annotations for tests. |
2559 class Annotations { | 2478 class Annotations { |
2560 static final Uri PACKAGE_EXPECT = | 2479 static final Uri PACKAGE_EXPECT = |
2561 new Uri(scheme: 'package', path: 'expect/expect.dart'); | 2480 new Uri(scheme: 'package', path: 'expect/expect.dart'); |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2751 hasTypeLiteral = true; | 2670 hasTypeLiteral = true; |
2752 break; | 2671 break; |
2753 } | 2672 } |
2754 } | 2673 } |
2755 | 2674 |
2756 if (hasAsCast) { | 2675 if (hasAsCast) { |
2757 registerBackendImpact(transformed, impacts.asCheck); | 2676 registerBackendImpact(transformed, impacts.asCheck); |
2758 } | 2677 } |
2759 | 2678 |
2760 if (hasTypeLiteral) { | 2679 if (hasTypeLiteral) { |
2761 transformed.registerTypeUse(new TypeUse.instantiation( | 2680 transformed.registerTypeUse( |
2762 backend.compiler.coreTypes.typeType)); | 2681 new TypeUse.instantiation(backend.compiler.coreTypes.typeType)); |
2763 registerBackendImpact(transformed, impacts.typeLiteral); | 2682 registerBackendImpact(transformed, impacts.typeLiteral); |
2764 } | 2683 } |
2765 | 2684 |
2766 for (MapLiteralUse mapLiteralUse in worldImpact.mapLiterals) { | 2685 for (MapLiteralUse mapLiteralUse in worldImpact.mapLiterals) { |
2767 // TODO(johnniwinther): Use the [isEmpty] property when factory | 2686 // TODO(johnniwinther): Use the [isEmpty] property when factory |
2768 // constructors are registered directly. | 2687 // constructors are registered directly. |
2769 if (mapLiteralUse.isConstant) { | 2688 if (mapLiteralUse.isConstant) { |
2770 registerBackendImpact(transformed, impacts.constantMapLiteral); | 2689 registerBackendImpact(transformed, impacts.constantMapLiteral); |
2771 } else { | 2690 } else { |
2772 transformed.registerTypeUse( | 2691 transformed |
2773 new TypeUse.instantiation(mapLiteralUse.type)); | 2692 .registerTypeUse(new TypeUse.instantiation(mapLiteralUse.type)); |
2774 } | 2693 } |
2775 registerRequiredType(mapLiteralUse.type); | 2694 registerRequiredType(mapLiteralUse.type); |
2776 } | 2695 } |
2777 | 2696 |
2778 for (ListLiteralUse listLiteralUse in worldImpact.listLiterals) { | 2697 for (ListLiteralUse listLiteralUse in worldImpact.listLiterals) { |
2779 // TODO(johnniwinther): Use the [isConstant] and [isEmpty] property when | 2698 // TODO(johnniwinther): Use the [isConstant] and [isEmpty] property when |
2780 // factory constructors are registered directly. | 2699 // factory constructors are registered directly. |
2781 transformed.registerTypeUse( | 2700 transformed |
2782 new TypeUse.instantiation(listLiteralUse.type)); | 2701 .registerTypeUse(new TypeUse.instantiation(listLiteralUse.type)); |
2783 registerRequiredType(listLiteralUse.type); | 2702 registerRequiredType(listLiteralUse.type); |
2784 } | 2703 } |
2785 | 2704 |
2786 if (worldImpact.constSymbolNames.isNotEmpty) { | 2705 if (worldImpact.constSymbolNames.isNotEmpty) { |
2787 registerBackendImpact(transformed, impacts.constSymbol); | 2706 registerBackendImpact(transformed, impacts.constSymbol); |
2788 for (String constSymbolName in worldImpact.constSymbolNames) { | 2707 for (String constSymbolName in worldImpact.constSymbolNames) { |
2789 backend.registerConstSymbol(constSymbolName); | 2708 backend.registerConstSymbol(constSymbolName); |
2790 } | 2709 } |
2791 } | 2710 } |
2792 | 2711 |
2793 for (StaticUse staticUse in worldImpact.staticUses) { | 2712 for (StaticUse staticUse in worldImpact.staticUses) { |
2794 if (staticUse.kind == StaticUseKind.CLOSURE) { | 2713 if (staticUse.kind == StaticUseKind.CLOSURE) { |
2795 registerBackendImpact(transformed, impacts.closure); | 2714 registerBackendImpact(transformed, impacts.closure); |
2796 LocalFunctionElement closure = staticUse.element; | 2715 LocalFunctionElement closure = staticUse.element; |
2797 if (closure.type.containsTypeVariables) { | 2716 if (closure.type.containsTypeVariables) { |
2798 backend.compiler.enqueuer.resolution.universe | 2717 backend.compiler.enqueuer.resolution.universe |
2799 .closuresWithFreeTypeVariables.add(closure); | 2718 .closuresWithFreeTypeVariables |
| 2719 .add(closure); |
2800 registerBackendImpact(transformed, impacts.computeSignature); | 2720 registerBackendImpact(transformed, impacts.computeSignature); |
2801 } | 2721 } |
2802 } | 2722 } |
2803 } | 2723 } |
2804 | 2724 |
2805 for (ConstantExpression constant in worldImpact.constantLiterals) { | 2725 for (ConstantExpression constant in worldImpact.constantLiterals) { |
2806 switch (constant.kind) { | 2726 switch (constant.kind) { |
2807 case ConstantExpressionKind.NULL: | 2727 case ConstantExpressionKind.NULL: |
2808 registerBackendImpact(transformed, impacts.nullLiteral); | 2728 registerBackendImpact(transformed, impacts.nullLiteral); |
2809 break; | 2729 break; |
(...skipping 11 matching lines...) Expand all Loading... |
2821 break; | 2741 break; |
2822 default: | 2742 default: |
2823 assert(invariant(NO_LOCATION_SPANNABLE, false, | 2743 assert(invariant(NO_LOCATION_SPANNABLE, false, |
2824 message: "Unexpected constant literal: ${constant.kind}.")); | 2744 message: "Unexpected constant literal: ${constant.kind}.")); |
2825 } | 2745 } |
2826 } | 2746 } |
2827 | 2747 |
2828 return transformed; | 2748 return transformed; |
2829 } | 2749 } |
2830 | 2750 |
2831 void registerBackendImpact(TransformedWorldImpact worldImpact, | 2751 void registerBackendImpact( |
2832 BackendImpact backendImpact) { | 2752 TransformedWorldImpact worldImpact, BackendImpact backendImpact) { |
2833 for (Element staticUse in backendImpact.staticUses) { | 2753 for (Element staticUse in backendImpact.staticUses) { |
2834 assert(staticUse != null); | 2754 assert(staticUse != null); |
2835 backend.registerBackendUse(staticUse); | 2755 backend.registerBackendUse(staticUse); |
2836 worldImpact.registerStaticUse( | 2756 worldImpact.registerStaticUse( |
2837 // TODO(johnniwinther): Store the correct use in impacts. | 2757 // TODO(johnniwinther): Store the correct use in impacts. |
2838 new StaticUse.foreignUse(staticUse)); | 2758 new StaticUse.foreignUse(staticUse)); |
2839 } | 2759 } |
2840 for (InterfaceType instantiatedType in backendImpact.instantiatedTypes) { | 2760 for (InterfaceType instantiatedType in backendImpact.instantiatedTypes) { |
2841 backend.registerBackendUse(instantiatedType.element); | 2761 backend.registerBackendUse(instantiatedType.element); |
2842 worldImpact.registerTypeUse( | 2762 worldImpact.registerTypeUse(new TypeUse.instantiation(instantiatedType)); |
2843 new TypeUse.instantiation(instantiatedType)); | |
2844 } | 2763 } |
2845 for (ClassElement cls in backendImpact.instantiatedClasses) { | 2764 for (ClassElement cls in backendImpact.instantiatedClasses) { |
2846 cls.ensureResolved(backend.resolution); | 2765 cls.ensureResolved(backend.resolution); |
2847 backend.registerBackendUse(cls); | 2766 backend.registerBackendUse(cls); |
2848 worldImpact.registerTypeUse( | 2767 worldImpact.registerTypeUse(new TypeUse.instantiation(cls.rawType)); |
2849 new TypeUse.instantiation(cls.rawType)); | |
2850 } | 2768 } |
2851 for (BackendImpact otherImpact in backendImpact.otherImpacts) { | 2769 for (BackendImpact otherImpact in backendImpact.otherImpacts) { |
2852 registerBackendImpact(worldImpact, otherImpact); | 2770 registerBackendImpact(worldImpact, otherImpact); |
2853 } | 2771 } |
2854 } | 2772 } |
2855 | 2773 |
2856 /// Register [type] as required for the runtime type information system. | 2774 /// Register [type] as required for the runtime type information system. |
2857 void registerRequiredType(DartType type) { | 2775 void registerRequiredType(DartType type) { |
2858 // If [argument] has type variables or is a type variable, this method | 2776 // If [argument] has type variables or is a type variable, this method |
2859 // registers a RTI dependency between the class where the type variable is | 2777 // registers a RTI dependency between the class where the type variable is |
(...skipping 21 matching lines...) Expand all Loading... |
2881 registerBackendImpact(transformed, impacts.malformedTypeCheck); | 2799 registerBackendImpact(transformed, impacts.malformedTypeCheck); |
2882 } | 2800 } |
2883 if (!type.treatAsRaw || type.containsTypeVariables || type.isFunctionType) { | 2801 if (!type.treatAsRaw || type.containsTypeVariables || type.isFunctionType) { |
2884 registerBackendImpact(transformed, impacts.genericTypeCheck); | 2802 registerBackendImpact(transformed, impacts.genericTypeCheck); |
2885 if (inCheckedMode) { | 2803 if (inCheckedMode) { |
2886 registerBackendImpact(transformed, impacts.genericCheckedModeTypeCheck); | 2804 registerBackendImpact(transformed, impacts.genericCheckedModeTypeCheck); |
2887 } | 2805 } |
2888 if (type.isTypeVariable) { | 2806 if (type.isTypeVariable) { |
2889 registerBackendImpact(transformed, impacts.typeVariableTypeCheck); | 2807 registerBackendImpact(transformed, impacts.typeVariableTypeCheck); |
2890 if (inCheckedMode) { | 2808 if (inCheckedMode) { |
2891 registerBackendImpact(transformed, | 2809 registerBackendImpact( |
2892 impacts.typeVariableCheckedModeTypeCheck); | 2810 transformed, impacts.typeVariableCheckedModeTypeCheck); |
2893 } | 2811 } |
2894 } | 2812 } |
2895 } | 2813 } |
2896 if (type is FunctionType) { | 2814 if (type is FunctionType) { |
2897 registerBackendImpact(transformed, impacts.functionTypeCheck); | 2815 registerBackendImpact(transformed, impacts.functionTypeCheck); |
2898 } | 2816 } |
2899 if (type.element != null && backend.isNative(type.element)) { | 2817 if (type.element != null && backend.isNative(type.element)) { |
2900 registerBackendImpact(transformed, impacts.nativeTypeCheck); | 2818 registerBackendImpact(transformed, impacts.nativeTypeCheck); |
2901 } | 2819 } |
2902 } | 2820 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2956 break; | 2874 break; |
2957 default: | 2875 default: |
2958 } | 2876 } |
2959 } | 2877 } |
2960 | 2878 |
2961 for (ConstantValue constant in impact.compileTimeConstants) { | 2879 for (ConstantValue constant in impact.compileTimeConstants) { |
2962 backend.registerCompileTimeConstant(constant, registry); | 2880 backend.registerCompileTimeConstant(constant, registry); |
2963 backend.addCompileTimeConstantForEmission(constant); | 2881 backend.addCompileTimeConstantForEmission(constant); |
2964 } | 2882 } |
2965 | 2883 |
2966 for (Pair<DartType, DartType> check in | 2884 for (Pair<DartType, DartType> check |
2967 impact.typeVariableBoundsSubtypeChecks) { | 2885 in impact.typeVariableBoundsSubtypeChecks) { |
2968 backend.registerTypeVariableBoundsSubtypeCheck(check.a, check.b); | 2886 backend.registerTypeVariableBoundsSubtypeCheck(check.a, check.b); |
2969 } | 2887 } |
2970 | 2888 |
2971 | |
2972 for (StaticUse staticUse in impact.staticUses) { | 2889 for (StaticUse staticUse in impact.staticUses) { |
2973 if (staticUse.kind == StaticUseKind.CLOSURE) { | 2890 if (staticUse.kind == StaticUseKind.CLOSURE) { |
2974 LocalFunctionElement closure = staticUse.element; | 2891 LocalFunctionElement closure = staticUse.element; |
2975 if (backend.methodNeedsRti(closure)) { | 2892 if (backend.methodNeedsRti(closure)) { |
2976 registerBackendImpact(transformed, impacts.computeSignature); | 2893 registerBackendImpact(transformed, impacts.computeSignature); |
2977 } | 2894 } |
2978 } | 2895 } |
2979 } | 2896 } |
2980 | 2897 |
2981 for (String name in impact.constSymbols) { | 2898 for (String name in impact.constSymbols) { |
2982 backend.registerConstSymbol(name); | 2899 backend.registerConstSymbol(name); |
2983 } | 2900 } |
2984 | 2901 |
2985 for (Set<ClassElement> classes in impact.specializedGetInterceptors) { | 2902 for (Set<ClassElement> classes in impact.specializedGetInterceptors) { |
2986 backend.registerSpecializedGetInterceptor(classes); | 2903 backend.registerSpecializedGetInterceptor(classes); |
2987 } | 2904 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3022 const Dependency(this.constant, this.annotatedElement); | 2939 const Dependency(this.constant, this.annotatedElement); |
3023 } | 2940 } |
3024 | 2941 |
3025 class JavaScriptImpactStrategy extends ImpactStrategy { | 2942 class JavaScriptImpactStrategy extends ImpactStrategy { |
3026 final Resolution resolution; | 2943 final Resolution resolution; |
3027 final DumpInfoTask dumpInfoTask; | 2944 final DumpInfoTask dumpInfoTask; |
3028 final bool supportDeferredLoad; | 2945 final bool supportDeferredLoad; |
3029 final bool supportDumpInfo; | 2946 final bool supportDumpInfo; |
3030 final bool supportSerialization; | 2947 final bool supportSerialization; |
3031 | 2948 |
3032 JavaScriptImpactStrategy(this.resolution, | 2949 JavaScriptImpactStrategy(this.resolution, this.dumpInfoTask, |
3033 this.dumpInfoTask, | 2950 {this.supportDeferredLoad, |
3034 {this.supportDeferredLoad, | 2951 this.supportDumpInfo, |
3035 this.supportDumpInfo, | 2952 this.supportSerialization}); |
3036 this.supportSerialization}); | |
3037 | 2953 |
3038 @override | 2954 @override |
3039 void visitImpact(Element element, | 2955 void visitImpact(Element element, WorldImpact impact, |
3040 WorldImpact impact, | 2956 WorldImpactVisitor visitor, ImpactUseCase impactUse) { |
3041 WorldImpactVisitor visitor, | |
3042 ImpactUseCase impactUse) { | |
3043 // TODO(johnniwinther): Compute the application strategy once for each use. | 2957 // TODO(johnniwinther): Compute the application strategy once for each use. |
3044 if (impactUse == ResolutionEnqueuer.IMPACT_USE) { | 2958 if (impactUse == ResolutionEnqueuer.IMPACT_USE) { |
3045 if (supportDeferredLoad || supportSerialization) { | 2959 if (supportDeferredLoad || supportSerialization) { |
3046 impact.apply(visitor); | 2960 impact.apply(visitor); |
3047 } else { | 2961 } else { |
3048 impact.apply(visitor); | 2962 impact.apply(visitor); |
3049 resolution.uncacheWorldImpact(element); | 2963 resolution.uncacheWorldImpact(element); |
3050 } | 2964 } |
3051 } else if (impactUse == DeferredLoadTask.IMPACT_USE) { | 2965 } else if (impactUse == DeferredLoadTask.IMPACT_USE) { |
3052 impact.apply(visitor); | 2966 impact.apply(visitor); |
3053 // Impacts are uncached globally in [onImpactUsed]. | 2967 // Impacts are uncached globally in [onImpactUsed]. |
3054 } else if (impactUse == DumpInfoTask.IMPACT_USE) { | 2968 } else if (impactUse == DumpInfoTask.IMPACT_USE) { |
3055 impact.apply(visitor); | 2969 impact.apply(visitor); |
3056 dumpInfoTask.unregisterImpact(element); | 2970 dumpInfoTask.unregisterImpact(element); |
3057 } else { | 2971 } else { |
3058 impact.apply(visitor); | 2972 impact.apply(visitor); |
3059 } | 2973 } |
3060 } | 2974 } |
3061 | 2975 |
3062 @override | 2976 @override |
3063 void onImpactUsed(ImpactUseCase impactUse) { | 2977 void onImpactUsed(ImpactUseCase impactUse) { |
3064 if (impactUse == DeferredLoadTask.IMPACT_USE && | 2978 if (impactUse == DeferredLoadTask.IMPACT_USE && !supportSerialization) { |
3065 !supportSerialization) { | |
3066 // TODO(johnniwinther): Allow emptying when serialization has been | 2979 // TODO(johnniwinther): Allow emptying when serialization has been |
3067 // performed. | 2980 // performed. |
3068 resolution.emptyCache(); | 2981 resolution.emptyCache(); |
3069 } | 2982 } |
3070 } | 2983 } |
3071 } | 2984 } |
OLD | NEW |