Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: pkg/compiler/lib/src/js_backend/backend.dart

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js/rewrite_async.dart ('k') | pkg/compiler/lib/src/js_backend/backend_helpers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698