| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 const VERBOSE_OPTIMIZER_HINTS = false; | 7 const VERBOSE_OPTIMIZER_HINTS = false; |
| 8 | 8 |
| 9 class JavaScriptItemCompilationContext extends ItemCompilationContext { | 9 class JavaScriptItemCompilationContext extends ItemCompilationContext { |
| 10 final Set<HInstruction> boundsChecked = new Set<HInstruction>(); | 10 final Set<HInstruction> boundsChecked = new Set<HInstruction>(); |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 } | 213 } |
| 214 | 214 |
| 215 enum SyntheticConstantKind { | 215 enum SyntheticConstantKind { |
| 216 DUMMY_INTERCEPTOR, | 216 DUMMY_INTERCEPTOR, |
| 217 EMPTY_VALUE, | 217 EMPTY_VALUE, |
| 218 TYPEVARIABLE_REFERENCE, // Reference to a type in reflection data. | 218 TYPEVARIABLE_REFERENCE, // Reference to a type in reflection data. |
| 219 NAME | 219 NAME |
| 220 } | 220 } |
| 221 | 221 |
| 222 class JavaScriptBackend extends Backend { | 222 class JavaScriptBackend extends Backend { |
| 223 static final Uri DART_JS_HELPER = new Uri(scheme: 'dart', path: '_js_helper'); | |
| 224 static final Uri DART_INTERCEPTORS = | |
| 225 new Uri(scheme: 'dart', path: '_interceptors'); | |
| 226 static final Uri DART_FOREIGN_HELPER = | |
| 227 new Uri(scheme: 'dart', path: '_foreign_helper'); | |
| 228 static final Uri DART_JS_MIRRORS = | |
| 229 new Uri(scheme: 'dart', path: '_js_mirrors'); | |
| 230 static final Uri DART_JS_NAMES = | |
| 231 new Uri(scheme: 'dart', path: '_js_names'); | |
| 232 static final Uri DART_EMBEDDED_NAMES = | |
| 233 new Uri(scheme: 'dart', path: '_js_embedded_names'); | |
| 234 static final Uri DART_ISOLATE_HELPER = | |
| 235 new Uri(scheme: 'dart', path: '_isolate_helper'); | |
| 236 static final Uri PACKAGE_JS = | |
| 237 new Uri(scheme: 'package', path: 'js/js.dart'); | |
| 238 static final Uri PACKAGE_LOOKUP_MAP = | |
| 239 new Uri(scheme: 'package', path: 'lookup_map/lookup_map.dart'); | |
| 240 | |
| 241 static const String INVOKE_ON = '_getCachedInvocation'; | |
| 242 static const String START_ROOT_ISOLATE = 'startRootIsolate'; | |
| 243 | |
| 244 | |
| 245 String get patchVersion => emitter.patchVersion; | 223 String get patchVersion => emitter.patchVersion; |
| 246 | 224 |
| 247 bool get supportsReflection => emitter.emitter.supportsReflection; | 225 bool get supportsReflection => emitter.emitter.supportsReflection; |
| 248 | 226 |
| 249 final Annotations annotations; | 227 final Annotations annotations; |
| 250 | 228 |
| 251 /// Reference to the internal library to lookup functions to always inline. | |
| 252 LibraryElement internalLibrary; | |
| 253 | |
| 254 | 229 |
| 255 /// Set of classes that need to be considered for reflection although not | 230 /// Set of classes that need to be considered for reflection although not |
| 256 /// otherwise visible during resolution. | 231 /// otherwise visible during resolution. |
| 257 Iterable<ClassElement> get classesRequiredForReflection { | 232 Iterable<ClassElement> get classesRequiredForReflection { |
| 258 // TODO(herhut): Clean this up when classes needed for rti are tracked. | 233 // TODO(herhut): Clean this up when classes needed for rti are tracked. |
| 259 return [closureClass, jsIndexableClass]; | 234 return [helpers.closureClass, helpers.jsIndexableClass]; |
| 260 } | 235 } |
| 261 | 236 |
| 262 FunctionCompiler functionCompiler; | 237 FunctionCompiler functionCompiler; |
| 263 | 238 |
| 264 CodeEmitterTask emitter; | 239 CodeEmitterTask emitter; |
| 265 | 240 |
| 266 /** | 241 /** |
| 267 * The generated code as a js AST for compiled methods. | 242 * The generated code as a js AST for compiled methods. |
| 268 */ | 243 */ |
| 269 Map<Element, jsAst.Expression> get generatedCode { | 244 Map<Element, jsAst.Expression> get generatedCode { |
| 270 return compiler.enqueuer.codegen.generatedCode; | 245 return compiler.enqueuer.codegen.generatedCode; |
| 271 } | 246 } |
| 272 | 247 |
| 273 FunctionInlineCache inlineCache = new FunctionInlineCache(); | 248 FunctionInlineCache inlineCache = new FunctionInlineCache(); |
| 274 | 249 |
| 275 LibraryElement jsHelperLibrary; | |
| 276 LibraryElement asyncLibrary; | |
| 277 LibraryElement interceptorsLibrary; | |
| 278 LibraryElement foreignLibrary; | |
| 279 LibraryElement isolateHelperLibrary; | |
| 280 | |
| 281 ClassElement closureClass; | |
| 282 ClassElement boundClosureClass; | |
| 283 Element assertUnreachableMethod; | |
| 284 Element invokeOnMethod; | |
| 285 | |
| 286 ClassElement jsInterceptorClass; | |
| 287 ClassElement jsStringClass; | |
| 288 ClassElement jsArrayClass; | |
| 289 ClassElement jsNumberClass; | |
| 290 ClassElement jsIntClass; | |
| 291 ClassElement jsDoubleClass; | |
| 292 ClassElement jsNullClass; | |
| 293 ClassElement jsBoolClass; | |
| 294 ClassElement jsPlainJavaScriptObjectClass; | |
| 295 ClassElement jsUnknownJavaScriptObjectClass; | |
| 296 ClassElement jsJavaScriptFunctionClass; | |
| 297 ClassElement jsJavaScriptObjectClass; | |
| 298 | |
| 299 ClassElement jsIndexableClass; | |
| 300 ClassElement jsMutableIndexableClass; | |
| 301 | |
| 302 ClassElement jsMutableArrayClass; | |
| 303 ClassElement jsFixedArrayClass; | |
| 304 ClassElement jsExtendableArrayClass; | |
| 305 ClassElement jsUnmodifiableArrayClass; | |
| 306 ClassElement jsPositiveIntClass; | |
| 307 ClassElement jsUInt32Class; | |
| 308 ClassElement jsUInt31Class; | |
| 309 | |
| 310 Element jsIndexableLength; | |
| 311 Element jsArrayTypedConstructor; | |
| 312 Element jsArrayRemoveLast; | |
| 313 Element jsArrayAdd; | |
| 314 Element jsStringSplit; | |
| 315 Element jsStringToString; | |
| 316 Element jsStringOperatorAdd; | |
| 317 Element objectEquals; | |
| 318 | |
| 319 ClassElement typeLiteralClass; | |
| 320 ClassElement mapLiteralClass; | |
| 321 ClassElement constMapLiteralClass; | |
| 322 ClassElement typeVariableClass; | |
| 323 ConstructorElement mapLiteralConstructor; | |
| 324 ConstructorElement mapLiteralConstructorEmpty; | |
| 325 Element mapLiteralUntypedMaker; | |
| 326 Element mapLiteralUntypedEmptyMaker; | |
| 327 | |
| 328 ClassElement noSideEffectsClass; | |
| 329 ClassElement noThrowsClass; | |
| 330 ClassElement noInlineClass; | |
| 331 ClassElement forceInlineClass; | |
| 332 ClassElement irRepresentationClass; | |
| 333 | |
| 334 ClassElement jsAnnotationClass; | |
| 335 | |
| 336 Element getInterceptorMethod; | |
| 337 | |
| 338 ClassElement jsInvocationMirrorClass; | |
| 339 | |
| 340 ClassElement typedArrayClass; | |
| 341 ClassElement typedArrayOfIntClass; | |
| 342 | |
| 343 /// If [true], the compiler will emit code that logs whenever a method is | 250 /// If [true], the compiler will emit code that logs whenever a method is |
| 344 /// called. When TRACE_METHOD is 'console' this will be logged | 251 /// called. When TRACE_METHOD is 'console' this will be logged |
| 345 /// directly in the JavaScript console. When TRACE_METHOD is 'post' the | 252 /// directly in the JavaScript console. When TRACE_METHOD is 'post' the |
| 346 /// information will be sent to a server via a POST request. | 253 /// information will be sent to a server via a POST request. |
| 347 static const String TRACE_METHOD = const String.fromEnvironment('traceCalls'); | 254 static const String TRACE_METHOD = const String.fromEnvironment('traceCalls'); |
| 348 static const bool TRACE_CALLS = | 255 static const bool TRACE_CALLS = |
| 349 TRACE_METHOD == 'post' || TRACE_METHOD == 'console'; | 256 TRACE_METHOD == 'post' || TRACE_METHOD == 'console'; |
| 350 Element traceHelper; | 257 Element traceHelper; |
| 351 | 258 |
| 352 TypeMask get stringType => compiler.typesTask.stringType; | 259 TypeMask get stringType => compiler.typesTask.stringType; |
| 353 TypeMask get doubleType => compiler.typesTask.doubleType; | 260 TypeMask get doubleType => compiler.typesTask.doubleType; |
| 354 TypeMask get intType => compiler.typesTask.intType; | 261 TypeMask get intType => compiler.typesTask.intType; |
| 355 TypeMask get uint32Type => compiler.typesTask.uint32Type; | 262 TypeMask get uint32Type => compiler.typesTask.uint32Type; |
| 356 TypeMask get uint31Type => compiler.typesTask.uint31Type; | 263 TypeMask get uint31Type => compiler.typesTask.uint31Type; |
| 357 TypeMask get positiveIntType => compiler.typesTask.positiveIntType; | 264 TypeMask get positiveIntType => compiler.typesTask.positiveIntType; |
| 358 TypeMask get numType => compiler.typesTask.numType; | 265 TypeMask get numType => compiler.typesTask.numType; |
| 359 TypeMask get boolType => compiler.typesTask.boolType; | 266 TypeMask get boolType => compiler.typesTask.boolType; |
| 360 TypeMask get dynamicType => compiler.typesTask.dynamicType; | 267 TypeMask get dynamicType => compiler.typesTask.dynamicType; |
| 361 TypeMask get nullType => compiler.typesTask.nullType; | 268 TypeMask get nullType => compiler.typesTask.nullType; |
| 362 TypeMask get emptyType => const TypeMask.nonNullEmpty(); | 269 TypeMask get emptyType => const TypeMask.nonNullEmpty(); |
| 363 | 270 |
| 364 TypeMask _indexablePrimitiveTypeCache; | 271 TypeMask _indexablePrimitiveTypeCache; |
| 365 TypeMask get indexablePrimitiveType { | 272 TypeMask get indexablePrimitiveType { |
| 366 if (_indexablePrimitiveTypeCache == null) { | 273 if (_indexablePrimitiveTypeCache == null) { |
| 367 _indexablePrimitiveTypeCache = | 274 _indexablePrimitiveTypeCache = new TypeMask.nonNullSubtype( |
| 368 new TypeMask.nonNullSubtype(jsIndexableClass, compiler.world); | 275 helpers.jsIndexableClass, compiler.world); |
| 369 } | 276 } |
| 370 return _indexablePrimitiveTypeCache; | 277 return _indexablePrimitiveTypeCache; |
| 371 } | 278 } |
| 372 | 279 |
| 373 TypeMask _readableArrayTypeCache; | 280 TypeMask _readableArrayTypeCache; |
| 374 TypeMask get readableArrayType { | 281 TypeMask get readableArrayType { |
| 375 if (_readableArrayTypeCache == null) { | 282 if (_readableArrayTypeCache == null) { |
| 376 _readableArrayTypeCache = new TypeMask.nonNullSubclass(jsArrayClass, | 283 _readableArrayTypeCache = new TypeMask.nonNullSubclass( |
| 377 compiler.world); | 284 helpers.jsArrayClass, compiler.world); |
| 378 } | 285 } |
| 379 return _readableArrayTypeCache; | 286 return _readableArrayTypeCache; |
| 380 } | 287 } |
| 381 | 288 |
| 382 TypeMask _mutableArrayTypeCache; | 289 TypeMask _mutableArrayTypeCache; |
| 383 TypeMask get mutableArrayType { | 290 TypeMask get mutableArrayType { |
| 384 if (_mutableArrayTypeCache == null) { | 291 if (_mutableArrayTypeCache == null) { |
| 385 _mutableArrayTypeCache = new TypeMask.nonNullSubclass(jsMutableArrayClass, | 292 _mutableArrayTypeCache = new TypeMask.nonNullSubclass( |
| 386 compiler.world); | 293 helpers.jsMutableArrayClass, compiler.world); |
| 387 } | 294 } |
| 388 return _mutableArrayTypeCache; | 295 return _mutableArrayTypeCache; |
| 389 } | 296 } |
| 390 | 297 |
| 391 TypeMask _fixedArrayTypeCache; | 298 TypeMask _fixedArrayTypeCache; |
| 392 TypeMask get fixedArrayType { | 299 TypeMask get fixedArrayType { |
| 393 if (_fixedArrayTypeCache == null) { | 300 if (_fixedArrayTypeCache == null) { |
| 394 _fixedArrayTypeCache = new TypeMask.nonNullExact(jsFixedArrayClass, | 301 _fixedArrayTypeCache = new TypeMask.nonNullExact( |
| 395 compiler.world); | 302 helpers.jsFixedArrayClass, compiler.world); |
| 396 } | 303 } |
| 397 return _fixedArrayTypeCache; | 304 return _fixedArrayTypeCache; |
| 398 } | 305 } |
| 399 | 306 |
| 400 TypeMask _extendableArrayTypeCache; | 307 TypeMask _extendableArrayTypeCache; |
| 401 TypeMask get extendableArrayType { | 308 TypeMask get extendableArrayType { |
| 402 if (_extendableArrayTypeCache == null) { | 309 if (_extendableArrayTypeCache == null) { |
| 403 _extendableArrayTypeCache = | 310 _extendableArrayTypeCache = new TypeMask.nonNullExact( |
| 404 new TypeMask.nonNullExact(jsExtendableArrayClass, compiler.world); | 311 helpers.jsExtendableArrayClass, compiler.world); |
| 405 } | 312 } |
| 406 return _extendableArrayTypeCache; | 313 return _extendableArrayTypeCache; |
| 407 } | 314 } |
| 408 | 315 |
| 409 TypeMask _unmodifiableArrayTypeCache; | 316 TypeMask _unmodifiableArrayTypeCache; |
| 410 TypeMask get unmodifiableArrayType { | 317 TypeMask get unmodifiableArrayType { |
| 411 if (_unmodifiableArrayTypeCache == null) { | 318 if (_unmodifiableArrayTypeCache == null) { |
| 412 _unmodifiableArrayTypeCache = | 319 _unmodifiableArrayTypeCache = new TypeMask.nonNullExact( |
| 413 new TypeMask.nonNullExact(jsUnmodifiableArrayClass, compiler.world); | 320 helpers.jsUnmodifiableArrayClass, compiler.world); |
| 414 } | 321 } |
| 415 return _fixedArrayTypeCache; | 322 return _fixedArrayTypeCache; |
| 416 } | 323 } |
| 417 | 324 |
| 418 TypeMask _nonNullTypeCache; | 325 TypeMask _nonNullTypeCache; |
| 419 TypeMask get nonNullType { | 326 TypeMask get nonNullType { |
| 420 if (_nonNullTypeCache == null) { | 327 if (_nonNullTypeCache == null) { |
| 421 _nonNullTypeCache = | 328 _nonNullTypeCache = |
| 422 compiler.typesTask.dynamicType.nonNullable(); | 329 compiler.typesTask.dynamicType.nonNullable(); |
| 423 } | 330 } |
| 424 return _nonNullTypeCache; | 331 return _nonNullTypeCache; |
| 425 } | 332 } |
| 426 | 333 |
| 427 /// Maps special classes to their implementation (JSXxx) class. | 334 /// Maps special classes to their implementation (JSXxx) class. |
| 428 Map<ClassElement, ClassElement> implementationClasses; | 335 Map<ClassElement, ClassElement> implementationClasses; |
| 429 | 336 |
| 430 Element getNativeInterceptorMethod; | |
| 431 bool needToInitializeIsolateAffinityTag = false; | 337 bool needToInitializeIsolateAffinityTag = false; |
| 432 bool needToInitializeDispatchProperty = false; | 338 bool needToInitializeDispatchProperty = false; |
| 433 | 339 |
| 434 /// Holds the method "getIsolateAffinityTag" when dart:_js_helper has been | |
| 435 /// loaded. | |
| 436 FunctionElement getIsolateAffinityTagMarker; | |
| 437 | |
| 438 final Namer namer; | 340 final Namer namer; |
| 439 | 341 |
| 440 /** | 342 /** |
| 441 * Interface used to determine if an object has the JavaScript | |
| 442 * indexing behavior. The interface is only visible to specific | |
| 443 * libraries. | |
| 444 */ | |
| 445 ClassElement jsIndexingBehaviorInterface; | |
| 446 | |
| 447 /** | |
| 448 * A collection of selectors that must have a one shot interceptor | 343 * A collection of selectors that must have a one shot interceptor |
| 449 * generated. | 344 * generated. |
| 450 */ | 345 */ |
| 451 final Map<jsAst.Name, Selector> oneShotInterceptors; | 346 final Map<jsAst.Name, Selector> oneShotInterceptors; |
| 452 | 347 |
| 453 /** | 348 /** |
| 454 * The members of instantiated interceptor classes: maps a member name to the | 349 * The members of instantiated interceptor classes: maps a member name to the |
| 455 * list of members that have that name. This map is used by the codegen to | 350 * list of members that have that name. This map is used by the codegen to |
| 456 * know whether a send must be intercepted or not. | 351 * know whether a send must be intercepted or not. |
| 457 */ | 352 */ |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 List<CompilerTask> get tasks { | 403 List<CompilerTask> get tasks { |
| 509 List<CompilerTask> result = functionCompiler.tasks; | 404 List<CompilerTask> result = functionCompiler.tasks; |
| 510 result.add(emitter); | 405 result.add(emitter); |
| 511 result.add(patchResolverTask); | 406 result.add(patchResolverTask); |
| 512 return result; | 407 return result; |
| 513 } | 408 } |
| 514 | 409 |
| 515 final RuntimeTypes rti; | 410 final RuntimeTypes rti; |
| 516 final RuntimeTypesEncoder rtiEncoder; | 411 final RuntimeTypesEncoder rtiEncoder; |
| 517 | 412 |
| 518 /// Holds the method "disableTreeShaking" in js_mirrors when | |
| 519 /// dart:mirrors has been loaded. | |
| 520 FunctionElement disableTreeShakingMarker; | |
| 521 | |
| 522 /// Holds the method "preserveNames" in js_mirrors when | |
| 523 /// dart:mirrors has been loaded. | |
| 524 FunctionElement preserveNamesMarker; | |
| 525 | |
| 526 /// Holds the method "preserveMetadata" in js_mirrors when | |
| 527 /// dart:mirrors has been loaded. | |
| 528 FunctionElement preserveMetadataMarker; | |
| 529 | |
| 530 /// Holds the method "preserveUris" in js_mirrors when | |
| 531 /// dart:mirrors has been loaded. | |
| 532 FunctionElement preserveUrisMarker; | |
| 533 | |
| 534 /// Holds the method "preserveLibraryNames" in js_mirrors when | |
| 535 /// dart:mirrors has been loaded. | |
| 536 FunctionElement preserveLibraryNamesMarker; | |
| 537 | |
| 538 /// Holds the method "requiresPreamble" in _js_helper. | |
| 539 FunctionElement requiresPreambleMarker; | |
| 540 | |
| 541 /// Holds the class for the [JsGetName] enum. | |
| 542 EnumClassElement jsGetNameEnum; | |
| 543 | |
| 544 /// Holds the class for the [JsBuiltins] enum. | |
| 545 EnumClassElement jsBuiltinEnum; | |
| 546 | |
| 547 /// True if a call to preserveMetadataMarker has been seen. This means that | 413 /// True if a call to preserveMetadataMarker has been seen. This means that |
| 548 /// metadata must be retained for dart:mirrors to work correctly. | 414 /// metadata must be retained for dart:mirrors to work correctly. |
| 549 bool mustRetainMetadata = false; | 415 bool mustRetainMetadata = false; |
| 550 | 416 |
| 551 /// True if any metadata has been retained. This is slightly different from | 417 /// True if any metadata has been retained. This is slightly different from |
| 552 /// [mustRetainMetadata] and tells us if any metadata was retained. For | 418 /// [mustRetainMetadata] and tells us if any metadata was retained. For |
| 553 /// example, if [mustRetainMetadata] is true but there is no metadata in the | 419 /// example, if [mustRetainMetadata] is true but there is no metadata in the |
| 554 /// program, this variable will stil be false. | 420 /// program, this variable will stil be false. |
| 555 bool hasRetainedMetadata = false; | 421 bool hasRetainedMetadata = false; |
| 556 | 422 |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 return constantCompilerTask.jsConstantCompiler; | 559 return constantCompilerTask.jsConstantCompiler; |
| 694 } | 560 } |
| 695 | 561 |
| 696 FunctionElement resolveExternalFunction(FunctionElement element) { | 562 FunctionElement resolveExternalFunction(FunctionElement element) { |
| 697 if (isForeign(element) || isJsInterop(element)) return element; | 563 if (isForeign(element) || isJsInterop(element)) return element; |
| 698 return patchResolverTask.measure(() { | 564 return patchResolverTask.measure(() { |
| 699 return patchResolverTask.resolveExternalFunction(element); | 565 return patchResolverTask.resolveExternalFunction(element); |
| 700 }); | 566 }); |
| 701 } | 567 } |
| 702 | 568 |
| 703 // TODO(karlklose): Split into findHelperFunction and findHelperClass and | 569 bool isForeign(Element element) => element.library == helpers.foreignLibrary; |
| 704 // add a check that the element has the expected kind. | |
| 705 Element findHelper(String name) => find(jsHelperLibrary, name); | |
| 706 Element findAsyncHelper(String name) => find(asyncLibrary, name); | |
| 707 Element findInterceptor(String name) => find(interceptorsLibrary, name); | |
| 708 | |
| 709 Element find(LibraryElement library, String name) { | |
| 710 Element element = library.implementation.findLocal(name); | |
| 711 assert(invariant(library, element != null, | |
| 712 message: "Element '$name' not found in '${library.canonicalUri}'.")); | |
| 713 return element; | |
| 714 } | |
| 715 | |
| 716 bool isForeign(Element element) => element.library == foreignLibrary; | |
| 717 | 570 |
| 718 bool isBackendLibrary(LibraryElement library) { | 571 bool isBackendLibrary(LibraryElement library) { |
| 719 return library == interceptorsLibrary || | 572 return library == helpers.interceptorsLibrary || |
| 720 library == jsHelperLibrary; | 573 library == helpers.jsHelperLibrary; |
| 721 } | 574 } |
| 722 | 575 |
| 723 static Namer determineNamer(Compiler compiler) { | 576 static Namer determineNamer(Compiler compiler) { |
| 724 return compiler.enableMinification ? | 577 return compiler.enableMinification ? |
| 725 compiler.useFrequencyNamer ? | 578 compiler.useFrequencyNamer ? |
| 726 new FrequencyBasedNamer(compiler) : | 579 new FrequencyBasedNamer(compiler) : |
| 727 new MinifyNamer(compiler) : | 580 new MinifyNamer(compiler) : |
| 728 new Namer(compiler); | 581 new Namer(compiler); |
| 729 } | 582 } |
| 730 | 583 |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1110 classesMixedIntoInterceptedClasses.add(mixinApplication.mixin); | 963 classesMixedIntoInterceptedClasses.add(mixinApplication.mixin); |
| 1111 } | 964 } |
| 1112 } | 965 } |
| 1113 } | 966 } |
| 1114 } | 967 } |
| 1115 | 968 |
| 1116 void addInterceptors(ClassElement cls, | 969 void addInterceptors(ClassElement cls, |
| 1117 Enqueuer enqueuer, | 970 Enqueuer enqueuer, |
| 1118 Registry registry) { | 971 Registry registry) { |
| 1119 if (enqueuer.isResolutionQueue) { | 972 if (enqueuer.isResolutionQueue) { |
| 1120 _interceptedClasses.add(jsInterceptorClass); | 973 _interceptedClasses.add(helpers.jsInterceptorClass); |
| 1121 _interceptedClasses.add(cls); | 974 _interceptedClasses.add(cls); |
| 1122 cls.ensureResolved(resolution); | 975 cls.ensureResolved(resolution); |
| 1123 cls.forEachMember((ClassElement classElement, Element member) { | 976 cls.forEachMember((ClassElement classElement, Element member) { |
| 1124 // All methods on [Object] are shadowed by [Interceptor]. | 977 // All methods on [Object] are shadowed by [Interceptor]. |
| 1125 if (classElement == coreClasses.objectClass) return; | 978 if (classElement == coreClasses.objectClass) return; |
| 1126 Set<Element> set = interceptedElements.putIfAbsent( | 979 Set<Element> set = interceptedElements.putIfAbsent( |
| 1127 member.name, () => new Set<Element>()); | 980 member.name, () => new Set<Element>()); |
| 1128 set.add(member); | 981 set.add(member); |
| 1129 }, | 982 }, |
| 1130 includeSuperAndInjectedMembers: true); | 983 includeSuperAndInjectedMembers: true); |
| 1131 } | 984 } |
| 1132 enqueueClass(enqueuer, cls, registry); | 985 enqueueClass(enqueuer, cls, registry); |
| 1133 } | 986 } |
| 1134 | 987 |
| 1135 Set<ClassElement> get interceptedClasses { | 988 Set<ClassElement> get interceptedClasses { |
| 1136 assert(compiler.enqueuer.resolution.queueIsClosed); | 989 assert(compiler.enqueuer.resolution.queueIsClosed); |
| 1137 return _interceptedClasses; | 990 return _interceptedClasses; |
| 1138 } | 991 } |
| 1139 | 992 |
| 1140 void registerSpecializedGetInterceptor(Set<ClassElement> classes) { | 993 void registerSpecializedGetInterceptor(Set<ClassElement> classes) { |
| 1141 jsAst.Name name = namer.nameForGetInterceptor(classes); | 994 jsAst.Name name = namer.nameForGetInterceptor(classes); |
| 1142 if (classes.contains(jsInterceptorClass)) { | 995 if (classes.contains(helpers.jsInterceptorClass)) { |
| 1143 // We can't use a specialized [getInterceptorMethod], so we make | 996 // We can't use a specialized [getInterceptorMethod], so we make |
| 1144 // sure we emit the one with all checks. | 997 // sure we emit the one with all checks. |
| 1145 specializedGetInterceptors[name] = interceptedClasses; | 998 specializedGetInterceptors[name] = interceptedClasses; |
| 1146 } else { | 999 } else { |
| 1147 specializedGetInterceptors[name] = classes; | 1000 specializedGetInterceptors[name] = classes; |
| 1148 } | 1001 } |
| 1149 } | 1002 } |
| 1150 | 1003 |
| 1151 void registerCompileTimeConstant(ConstantValue constant, Registry registry) { | 1004 void registerCompileTimeConstant(ConstantValue constant, Registry registry) { |
| 1152 registerCompileTimeConstantInternal(constant, registry); | 1005 registerCompileTimeConstantInternal(constant, registry); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1232 registry); | 1085 registry); |
| 1233 } | 1086 } |
| 1234 | 1087 |
| 1235 // Register any helper that will be needed by the backend. | 1088 // Register any helper that will be needed by the backend. |
| 1236 if (enqueuer.isResolutionQueue) { | 1089 if (enqueuer.isResolutionQueue) { |
| 1237 if (cls == coreClasses.intClass || | 1090 if (cls == coreClasses.intClass || |
| 1238 cls == coreClasses.doubleClass || | 1091 cls == coreClasses.doubleClass || |
| 1239 cls == coreClasses.numClass) { | 1092 cls == coreClasses.numClass) { |
| 1240 // The backend will try to optimize number operations and use the | 1093 // The backend will try to optimize number operations and use the |
| 1241 // `iae` helper directly. | 1094 // `iae` helper directly. |
| 1242 enqueue(enqueuer, findHelper('iae'), registry); | 1095 enqueue(enqueuer, helpers.throwIllegalArgumentException, registry); |
| 1243 } else if (cls == coreClasses.listClass || | 1096 } else if (cls == coreClasses.listClass || |
| 1244 cls == coreClasses.stringClass) { | 1097 cls == coreClasses.stringClass) { |
| 1245 // The backend will try to optimize array and string access and use the | 1098 // The backend will try to optimize array and string access and use the |
| 1246 // `ioore` and `iae` helpers directly. | 1099 // `ioore` and `iae` helpers directly. |
| 1247 enqueue(enqueuer, findHelper('ioore'), registry); | 1100 enqueue(enqueuer, helpers.throwIndexOutOfRangeException, registry); |
| 1248 enqueue(enqueuer, findHelper('iae'), registry); | 1101 enqueue(enqueuer, helpers.throwIllegalArgumentException, registry); |
| 1249 } else if (cls == coreClasses.functionClass) { | 1102 } else if (cls == coreClasses.functionClass) { |
| 1250 enqueueClass(enqueuer, closureClass, registry); | 1103 enqueueClass(enqueuer, helpers.closureClass, registry); |
| 1251 } else if (cls == coreClasses.mapClass) { | 1104 } else if (cls == coreClasses.mapClass) { |
| 1252 // The backend will use a literal list to initialize the entries | 1105 // The backend will use a literal list to initialize the entries |
| 1253 // of the map. | 1106 // of the map. |
| 1254 enqueueClass(enqueuer, coreClasses.listClass, registry); | 1107 enqueueClass(enqueuer, coreClasses.listClass, registry); |
| 1255 enqueueClass(enqueuer, mapLiteralClass, registry); | 1108 enqueueClass(enqueuer, helpers.mapLiteralClass, registry); |
| 1256 // For map literals, the dependency between the implementation class | 1109 // For map literals, the dependency between the implementation class |
| 1257 // and [Map] is not visible, so we have to add it manually. | 1110 // and [Map] is not visible, so we have to add it manually. |
| 1258 rti.registerRtiDependency(mapLiteralClass, cls); | 1111 rti.registerRtiDependency(helpers.mapLiteralClass, cls); |
| 1259 } else if (cls == boundClosureClass) { | 1112 } else if (cls == helpers.boundClosureClass) { |
| 1260 // TODO(johnniwinther): Is this a noop? | 1113 // TODO(johnniwinther): Is this a noop? |
| 1261 enqueueClass(enqueuer, boundClosureClass, registry); | 1114 enqueueClass(enqueuer, helpers.boundClosureClass, registry); |
| 1262 } else if (isNativeOrExtendsNative(cls)) { | 1115 } else if (isNativeOrExtendsNative(cls)) { |
| 1263 enqueue(enqueuer, getNativeInterceptorMethod, registry); | 1116 enqueue(enqueuer, helpers.getNativeInterceptorMethod, registry); |
| 1264 enqueueClass(enqueuer, jsInterceptorClass, compiler.globalDependencies); | 1117 enqueueClass(enqueuer, helpers.jsInterceptorClass, |
| 1265 enqueueClass(enqueuer, jsJavaScriptObjectClass, registry); | 1118 compiler.globalDependencies); |
| 1266 enqueueClass(enqueuer, jsPlainJavaScriptObjectClass, registry); | 1119 enqueueClass(enqueuer, helpers.jsJavaScriptObjectClass, registry); |
| 1267 enqueueClass(enqueuer, jsJavaScriptFunctionClass, registry); | 1120 enqueueClass(enqueuer, helpers.jsPlainJavaScriptObjectClass, registry); |
| 1268 } else if (cls == mapLiteralClass) { | 1121 enqueueClass(enqueuer, helpers.jsJavaScriptFunctionClass, registry); |
| 1122 } else if (cls == helpers.mapLiteralClass) { |
| 1269 // For map literals, the dependency between the implementation class | 1123 // For map literals, the dependency between the implementation class |
| 1270 // and [Map] is not visible, so we have to add it manually. | 1124 // and [Map] is not visible, so we have to add it manually. |
| 1271 Element getFactory(String name, int arity) { | 1125 Element getFactory(String name, int arity) { |
| 1272 // The constructor is on the patch class, but dart2js unit tests don't | 1126 // The constructor is on the patch class, but dart2js unit tests don't |
| 1273 // have a patch class. | 1127 // have a patch class. |
| 1274 ClassElement implementation = cls.patch != null ? cls.patch : cls; | 1128 ClassElement implementation = cls.patch != null ? cls.patch : cls; |
| 1275 ConstructorElement ctor = implementation.lookupConstructor(name); | 1129 ConstructorElement ctor = implementation.lookupConstructor(name); |
| 1276 if (ctor == null | 1130 if (ctor == null || |
| 1277 || (Name.isPrivateName(name) | 1131 (Name.isPrivateName(name) && |
| 1278 && ctor.library != mapLiteralClass.library)) { | 1132 ctor.library != helpers.mapLiteralClass.library)) { |
| 1279 reporter.internalError(mapLiteralClass, | 1133 reporter.internalError( |
| 1280 "Map literal class $mapLiteralClass missing " | 1134 helpers.mapLiteralClass, |
| 1281 "'$name' constructor" | 1135 "Map literal class ${helpers.mapLiteralClass} missing " |
| 1282 " ${mapLiteralClass.constructors}"); | 1136 "'$name' constructor" |
| 1137 " ${helpers.mapLiteralClass.constructors}"); |
| 1283 } | 1138 } |
| 1284 return ctor; | 1139 return ctor; |
| 1285 } | 1140 } |
| 1286 Element getMember(String name) { | 1141 Element getMember(String name) { |
| 1287 // The constructor is on the patch class, but dart2js unit tests don't | 1142 // The constructor is on the patch class, but dart2js unit tests don't |
| 1288 // have a patch class. | 1143 // have a patch class. |
| 1289 ClassElement implementation = cls.patch != null ? cls.patch : cls; | 1144 ClassElement implementation = cls.patch != null ? cls.patch : cls; |
| 1290 Element element = implementation.lookupLocalMember(name); | 1145 Element element = implementation.lookupLocalMember(name); |
| 1291 if (element == null || !element.isFunction || !element.isStatic) { | 1146 if (element == null || !element.isFunction || !element.isStatic) { |
| 1292 reporter.internalError(mapLiteralClass, | 1147 reporter.internalError(helpers.mapLiteralClass, |
| 1293 "Map literal class $mapLiteralClass missing " | 1148 "Map literal class ${helpers.mapLiteralClass} missing " |
| 1294 "'$name' static member function"); | 1149 "'$name' static member function"); |
| 1295 } | 1150 } |
| 1296 return element; | 1151 return element; |
| 1297 } | 1152 } |
| 1298 mapLiteralConstructor = getFactory('_literal', 1); | 1153 helpers.mapLiteralConstructor = getFactory('_literal', 1); |
| 1299 mapLiteralConstructorEmpty = getFactory('_empty', 0); | 1154 helpers.mapLiteralConstructorEmpty = getFactory('_empty', 0); |
| 1300 enqueueInResolution(mapLiteralConstructor, registry); | 1155 enqueueInResolution(helpers.mapLiteralConstructor, registry); |
| 1301 enqueueInResolution(mapLiteralConstructorEmpty, registry); | 1156 enqueueInResolution(helpers.mapLiteralConstructorEmpty, registry); |
| 1302 | 1157 |
| 1303 mapLiteralUntypedMaker = getMember('_makeLiteral'); | 1158 helpers.mapLiteralUntypedMaker = getMember('_makeLiteral'); |
| 1304 mapLiteralUntypedEmptyMaker = getMember('_makeEmpty'); | 1159 helpers.mapLiteralUntypedEmptyMaker = getMember('_makeEmpty'); |
| 1305 enqueueInResolution(mapLiteralUntypedMaker, registry); | 1160 enqueueInResolution(helpers.mapLiteralUntypedMaker, registry); |
| 1306 enqueueInResolution(mapLiteralUntypedEmptyMaker, registry); | 1161 enqueueInResolution(helpers.mapLiteralUntypedEmptyMaker, registry); |
| 1307 } | 1162 } |
| 1308 } | 1163 } |
| 1309 if (cls == closureClass) { | 1164 if (cls == helpers.closureClass) { |
| 1310 enqueue(enqueuer, findHelper('closureFromTearOff'), registry); | 1165 enqueue(enqueuer, helpers.closureFromTearOff, registry); |
| 1311 } | 1166 } |
| 1312 if (cls == coreClasses.stringClass || | 1167 if (cls == coreClasses.stringClass || |
| 1313 cls == jsStringClass) { | 1168 cls == helpers.jsStringClass) { |
| 1314 addInterceptors(jsStringClass, enqueuer, registry); | 1169 addInterceptors(helpers.jsStringClass, enqueuer, registry); |
| 1315 } else if (cls == coreClasses.listClass || | 1170 } else if (cls == coreClasses.listClass || |
| 1316 cls == jsArrayClass || | 1171 cls == helpers.jsArrayClass || |
| 1317 cls == jsFixedArrayClass || | 1172 cls == helpers.jsFixedArrayClass || |
| 1318 cls == jsExtendableArrayClass || | 1173 cls == helpers.jsExtendableArrayClass || |
| 1319 cls == jsUnmodifiableArrayClass) { | 1174 cls == helpers.jsUnmodifiableArrayClass) { |
| 1320 addInterceptors(jsArrayClass, enqueuer, registry); | 1175 addInterceptors(helpers.jsArrayClass, enqueuer, registry); |
| 1321 addInterceptors(jsMutableArrayClass, enqueuer, registry); | 1176 addInterceptors(helpers.jsMutableArrayClass, enqueuer, registry); |
| 1322 addInterceptors(jsFixedArrayClass, enqueuer, registry); | 1177 addInterceptors(helpers.jsFixedArrayClass, enqueuer, registry); |
| 1323 addInterceptors(jsExtendableArrayClass, enqueuer, registry); | 1178 addInterceptors(helpers.jsExtendableArrayClass, enqueuer, registry); |
| 1324 addInterceptors(jsUnmodifiableArrayClass, enqueuer, registry); | 1179 addInterceptors(helpers.jsUnmodifiableArrayClass, enqueuer, registry); |
| 1325 } else if (cls == coreClasses.intClass || | 1180 } else if (cls == coreClasses.intClass || |
| 1326 cls == jsIntClass) { | 1181 cls == helpers.jsIntClass) { |
| 1327 addInterceptors(jsIntClass, enqueuer, registry); | 1182 addInterceptors(helpers.jsIntClass, enqueuer, registry); |
| 1328 addInterceptors(jsPositiveIntClass, enqueuer, registry); | 1183 addInterceptors(helpers.jsPositiveIntClass, enqueuer, registry); |
| 1329 addInterceptors(jsUInt32Class, enqueuer, registry); | 1184 addInterceptors(helpers.jsUInt32Class, enqueuer, registry); |
| 1330 addInterceptors(jsUInt31Class, enqueuer, registry); | 1185 addInterceptors(helpers.jsUInt31Class, enqueuer, registry); |
| 1331 addInterceptors(jsNumberClass, enqueuer, registry); | 1186 addInterceptors(helpers.jsNumberClass, enqueuer, registry); |
| 1332 } else if (cls == coreClasses.doubleClass || | 1187 } else if (cls == coreClasses.doubleClass || |
| 1333 cls == jsDoubleClass) { | 1188 cls == helpers.jsDoubleClass) { |
| 1334 addInterceptors(jsDoubleClass, enqueuer, registry); | 1189 addInterceptors(helpers.jsDoubleClass, enqueuer, registry); |
| 1335 addInterceptors(jsNumberClass, enqueuer, registry); | 1190 addInterceptors(helpers.jsNumberClass, enqueuer, registry); |
| 1336 } else if (cls == coreClasses.boolClass || | 1191 } else if (cls == coreClasses.boolClass || |
| 1337 cls == jsBoolClass) { | 1192 cls == helpers.jsBoolClass) { |
| 1338 addInterceptors(jsBoolClass, enqueuer, registry); | 1193 addInterceptors(helpers.jsBoolClass, enqueuer, registry); |
| 1339 } else if (cls == coreClasses.nullClass || | 1194 } else if (cls == coreClasses.nullClass || |
| 1340 cls == jsNullClass) { | 1195 cls == helpers.jsNullClass) { |
| 1341 addInterceptors(jsNullClass, enqueuer, registry); | 1196 addInterceptors(helpers.jsNullClass, enqueuer, registry); |
| 1342 } else if (cls == coreClasses.numClass || | 1197 } else if (cls == coreClasses.numClass || |
| 1343 cls == jsNumberClass) { | 1198 cls == helpers.jsNumberClass) { |
| 1344 addInterceptors(jsIntClass, enqueuer, registry); | 1199 addInterceptors(helpers.jsIntClass, enqueuer, registry); |
| 1345 addInterceptors(jsPositiveIntClass, enqueuer, registry); | 1200 addInterceptors(helpers.jsPositiveIntClass, enqueuer, registry); |
| 1346 addInterceptors(jsUInt32Class, enqueuer, registry); | 1201 addInterceptors(helpers.jsUInt32Class, enqueuer, registry); |
| 1347 addInterceptors(jsUInt31Class, enqueuer, registry); | 1202 addInterceptors(helpers.jsUInt31Class, enqueuer, registry); |
| 1348 addInterceptors(jsDoubleClass, enqueuer, registry); | 1203 addInterceptors(helpers.jsDoubleClass, enqueuer, registry); |
| 1349 addInterceptors(jsNumberClass, enqueuer, registry); | 1204 addInterceptors(helpers.jsNumberClass, enqueuer, registry); |
| 1350 } else if (cls == jsJavaScriptObjectClass) { | 1205 } else if (cls == helpers.jsJavaScriptObjectClass) { |
| 1351 addInterceptors(jsJavaScriptObjectClass, enqueuer, registry); | 1206 addInterceptors(helpers.jsJavaScriptObjectClass, enqueuer, registry); |
| 1352 } else if (cls == jsPlainJavaScriptObjectClass) { | 1207 } else if (cls == helpers.jsPlainJavaScriptObjectClass) { |
| 1353 addInterceptors(jsPlainJavaScriptObjectClass, enqueuer, registry); | 1208 addInterceptors(helpers.jsPlainJavaScriptObjectClass, enqueuer, registry); |
| 1354 } else if (cls == jsUnknownJavaScriptObjectClass) { | 1209 } else if (cls == helpers.jsUnknownJavaScriptObjectClass) { |
| 1355 addInterceptors(jsUnknownJavaScriptObjectClass, enqueuer, registry); | 1210 addInterceptors(helpers.jsUnknownJavaScriptObjectClass, enqueuer, registry
); |
| 1356 } else if (cls == jsJavaScriptFunctionClass) { | 1211 } else if (cls == helpers.jsJavaScriptFunctionClass) { |
| 1357 addInterceptors(jsJavaScriptFunctionClass, enqueuer, registry); | 1212 addInterceptors(helpers.jsJavaScriptFunctionClass, enqueuer, registry); |
| 1358 } else if (isNativeOrExtendsNative(cls)) { | 1213 } else if (isNativeOrExtendsNative(cls)) { |
| 1359 addInterceptorsForNativeClassMembers(cls, enqueuer); | 1214 addInterceptorsForNativeClassMembers(cls, enqueuer); |
| 1360 } else if (cls == jsIndexingBehaviorInterface) { | 1215 } else if (cls == helpers.jsIndexingBehaviorInterface) { |
| 1361 // These two helpers are used by the emitter and the codegen. | 1216 // These two helpers are used by the emitter and the codegen. |
| 1362 // Because we cannot enqueue elements at the time of emission, | 1217 // Because we cannot enqueue elements at the time of emission, |
| 1363 // we make sure they are always generated. | 1218 // we make sure they are always generated. |
| 1364 enqueue(enqueuer, findHelper('isJsIndexable'), registry); | 1219 enqueue(enqueuer, helpers.isJsIndexable, registry); |
| 1365 } | 1220 } |
| 1366 | 1221 |
| 1367 customElementsAnalysis.registerInstantiatedClass(cls, enqueuer); | 1222 customElementsAnalysis.registerInstantiatedClass(cls, enqueuer); |
| 1368 if (!enqueuer.isResolutionQueue) { | 1223 if (!enqueuer.isResolutionQueue) { |
| 1369 lookupMapAnalysis.registerInstantiatedClass(cls); | 1224 lookupMapAnalysis.registerInstantiatedClass(cls); |
| 1370 } | 1225 } |
| 1371 } | 1226 } |
| 1372 | 1227 |
| 1373 void registerInstantiatedType(InterfaceType type, | 1228 void registerInstantiatedType(InterfaceType type, |
| 1374 Enqueuer enqueuer, | 1229 Enqueuer enqueuer, |
| 1375 Registry registry, | 1230 Registry registry, |
| 1376 {bool mirrorUsage: false}) { | 1231 {bool mirrorUsage: false}) { |
| 1377 lookupMapAnalysis.registerInstantiatedType(type, registry); | 1232 lookupMapAnalysis.registerInstantiatedType(type, registry); |
| 1378 super.registerInstantiatedType( | 1233 super.registerInstantiatedType( |
| 1379 type, enqueuer, registry, mirrorUsage: mirrorUsage); | 1234 type, enqueuer, registry, mirrorUsage: mirrorUsage); |
| 1380 } | 1235 } |
| 1381 | 1236 |
| 1382 void registerUseInterceptor(Enqueuer enqueuer) { | 1237 void registerUseInterceptor(Enqueuer enqueuer) { |
| 1383 assert(!enqueuer.isResolutionQueue); | 1238 assert(!enqueuer.isResolutionQueue); |
| 1384 if (!enqueuer.nativeEnqueuer.hasInstantiatedNativeClasses()) return; | 1239 if (!enqueuer.nativeEnqueuer.hasInstantiatedNativeClasses()) return; |
| 1385 Registry registry = compiler.globalDependencies; | 1240 Registry registry = compiler.globalDependencies; |
| 1386 enqueue(enqueuer, getNativeInterceptorMethod, registry); | 1241 enqueue(enqueuer, helpers.getNativeInterceptorMethod, registry); |
| 1387 enqueueClass(enqueuer, jsJavaScriptObjectClass, registry); | 1242 enqueueClass(enqueuer, helpers.jsJavaScriptObjectClass, registry); |
| 1388 enqueueClass(enqueuer, jsPlainJavaScriptObjectClass, registry); | 1243 enqueueClass(enqueuer, helpers.jsPlainJavaScriptObjectClass, registry); |
| 1389 enqueueClass(enqueuer, jsJavaScriptFunctionClass, registry); | 1244 enqueueClass(enqueuer, helpers.jsJavaScriptFunctionClass, registry); |
| 1390 needToInitializeIsolateAffinityTag = true; | 1245 needToInitializeIsolateAffinityTag = true; |
| 1391 needToInitializeDispatchProperty = true; | 1246 needToInitializeDispatchProperty = true; |
| 1392 } | 1247 } |
| 1393 | 1248 |
| 1394 JavaScriptItemCompilationContext createItemCompilationContext() { | 1249 JavaScriptItemCompilationContext createItemCompilationContext() { |
| 1395 return new JavaScriptItemCompilationContext(); | 1250 return new JavaScriptItemCompilationContext(); |
| 1396 } | 1251 } |
| 1397 | 1252 |
| 1398 void enqueueHelpers(ResolutionEnqueuer world, Registry registry) { | 1253 void enqueueHelpers(ResolutionEnqueuer world, Registry registry) { |
| 1399 assert(interceptorsLibrary != null); | 1254 assert(helpers.interceptorsLibrary != null); |
| 1400 // TODO(ngeoffray): Not enqueuing those two classes currently make | 1255 // TODO(ngeoffray): Not enqueuing those two classes currently make |
| 1401 // the compiler potentially crash. However, any reasonable program | 1256 // the compiler potentially crash. However, any reasonable program |
| 1402 // will instantiate those two classes. | 1257 // will instantiate those two classes. |
| 1403 addInterceptors(jsBoolClass, world, registry); | 1258 addInterceptors(helpers.jsBoolClass, world, registry); |
| 1404 addInterceptors(jsNullClass, world, registry); | 1259 addInterceptors(helpers.jsNullClass, world, registry); |
| 1405 if (compiler.enableTypeAssertions) { | 1260 if (compiler.enableTypeAssertions) { |
| 1406 // Unconditionally register the helper that checks if the | 1261 // Unconditionally register the helper that checks if the |
| 1407 // expression in an if/while/for is a boolean. | 1262 // expression in an if/while/for is a boolean. |
| 1408 // TODO(ngeoffray): Should we have the resolver register those instead? | 1263 // TODO(ngeoffray): Should we have the resolver register those instead? |
| 1409 Element e = findHelper('boolConversionCheck'); | 1264 Element e = helpers.boolConversionCheck; |
| 1410 if (e != null) enqueue(world, e, registry); | 1265 if (e != null) enqueue(world, e, registry); |
| 1411 } | 1266 } |
| 1412 | 1267 |
| 1413 if (TRACE_CALLS) { | 1268 if (TRACE_CALLS) { |
| 1414 traceHelper = findHelper( | 1269 traceHelper = TRACE_METHOD == 'console' |
| 1415 TRACE_METHOD == 'console' ? 'consoleTraceHelper' : 'postTraceHelper'); | 1270 ? helpers.consoleTraceHelper : helpers.postTraceHelper; |
| 1416 assert(traceHelper != null); | 1271 assert(traceHelper != null); |
| 1417 enqueueInResolution(traceHelper, registry); | 1272 enqueueInResolution(traceHelper, registry); |
| 1418 } | 1273 } |
| 1419 enqueueInResolution(assertUnreachableMethod, registry); | 1274 enqueueInResolution(helpers.assertUnreachableMethod, registry); |
| 1420 registerCheckedModeHelpers(registry); | 1275 registerCheckedModeHelpers(registry); |
| 1421 } | 1276 } |
| 1422 | 1277 |
| 1423 onResolutionComplete() { | 1278 onResolutionComplete() { |
| 1424 super.onResolutionComplete(); | 1279 super.onResolutionComplete(); |
| 1425 computeMembersNeededForReflection(); | 1280 computeMembersNeededForReflection(); |
| 1426 rti.computeClassesNeedingRti(); | 1281 rti.computeClassesNeedingRti(); |
| 1427 } | 1282 } |
| 1428 | 1283 |
| 1429 onTypeInferenceComplete() { | 1284 onTypeInferenceComplete() { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1459 | 1314 |
| 1460 /// Call during codegen if an instance of [closure] is being created. | 1315 /// Call during codegen if an instance of [closure] is being created. |
| 1461 void registerInstantiatedClosure(LocalFunctionElement closure, | 1316 void registerInstantiatedClosure(LocalFunctionElement closure, |
| 1462 CodegenRegistry registry) { | 1317 CodegenRegistry registry) { |
| 1463 if (methodNeedsRti(closure)) { | 1318 if (methodNeedsRti(closure)) { |
| 1464 registerComputeSignature(compiler.enqueuer.codegen, registry); | 1319 registerComputeSignature(compiler.enqueuer.codegen, registry); |
| 1465 } | 1320 } |
| 1466 } | 1321 } |
| 1467 | 1322 |
| 1468 void registerBoundClosure(Enqueuer enqueuer) { | 1323 void registerBoundClosure(Enqueuer enqueuer) { |
| 1469 boundClosureClass.ensureResolved(resolution); | 1324 helpers.boundClosureClass.ensureResolved(resolution); |
| 1470 registerInstantiatedType( | 1325 registerInstantiatedType( |
| 1471 boundClosureClass.rawType, | 1326 helpers.boundClosureClass.rawType, |
| 1472 enqueuer, | 1327 enqueuer, |
| 1473 // Precise dependency is not important here. | 1328 // Precise dependency is not important here. |
| 1474 compiler.globalDependencies); | 1329 compiler.globalDependencies); |
| 1475 } | 1330 } |
| 1476 | 1331 |
| 1477 void registerGetOfStaticFunction(Enqueuer enqueuer) { | 1332 void registerGetOfStaticFunction(Enqueuer enqueuer) { |
| 1478 closureClass.ensureResolved(resolution); | 1333 helpers.closureClass.ensureResolved(resolution); |
| 1479 registerInstantiatedType( | 1334 registerInstantiatedType( |
| 1480 closureClass.rawType, | 1335 helpers.closureClass.rawType, |
| 1481 enqueuer, | 1336 enqueuer, |
| 1482 compiler.globalDependencies); | 1337 compiler.globalDependencies); |
| 1483 } | 1338 } |
| 1484 | 1339 |
| 1485 void registerComputeSignature(Enqueuer enqueuer, Registry registry) { | 1340 void registerComputeSignature(Enqueuer enqueuer, Registry registry) { |
| 1486 // Calls to [:computeSignature:] are generated by the emitter and we | 1341 // Calls to [:computeSignature:] are generated by the emitter and we |
| 1487 // therefore need to enqueue the used elements in the codegen enqueuer as | 1342 // therefore need to enqueue the used elements in the codegen enqueuer as |
| 1488 // well as in the resolution enqueuer. | 1343 // well as in the resolution enqueuer. |
| 1489 enqueueImpact(enqueuer, impacts.computeSignature, registry); | 1344 enqueueImpact(enqueuer, impacts.computeSignature, registry); |
| 1490 } | 1345 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1521 enqueue(world, helper.getElement(compiler), registry); | 1376 enqueue(world, helper.getElement(compiler), registry); |
| 1522 } | 1377 } |
| 1523 } | 1378 } |
| 1524 if (!type.treatAsRaw || type.containsTypeVariables) { | 1379 if (!type.treatAsRaw || type.containsTypeVariables) { |
| 1525 enqueueClass(world, coreClasses.listClass, registry); | 1380 enqueueClass(world, coreClasses.listClass, registry); |
| 1526 } | 1381 } |
| 1527 if (type.element != null && isNative(type.element)) { | 1382 if (type.element != null && isNative(type.element)) { |
| 1528 // We will neeed to add the "$is" and "$as" properties on the | 1383 // We will neeed to add the "$is" and "$as" properties on the |
| 1529 // JavaScript object prototype, so we make sure | 1384 // JavaScript object prototype, so we make sure |
| 1530 // [:defineProperty:] is compiled. | 1385 // [:defineProperty:] is compiled. |
| 1531 enqueue(world, findHelper('defineProperty'), registry); | 1386 enqueue(world, helpers.defineProperty, registry); |
| 1532 } | 1387 } |
| 1533 } | 1388 } |
| 1534 | 1389 |
| 1535 void registerTypeVariableBoundsSubtypeCheck(DartType typeArgument, | 1390 void registerTypeVariableBoundsSubtypeCheck(DartType typeArgument, |
| 1536 DartType bound) { | 1391 DartType bound) { |
| 1537 rti.registerTypeVariableBoundsSubtypeCheck(typeArgument, bound); | 1392 rti.registerTypeVariableBoundsSubtypeCheck(typeArgument, bound); |
| 1538 } | 1393 } |
| 1539 | 1394 |
| 1540 void registerCheckDeferredIsLoaded(Registry registry) { | 1395 void registerCheckDeferredIsLoaded(Registry registry) { |
| 1541 enqueueInResolution(helpers.checkDeferredIsLoaded, registry); | 1396 enqueueInResolution(helpers.checkDeferredIsLoaded, registry); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1595 // The JavaScript backend implements [Isolate.spawn] by looking up | 1450 // The JavaScript backend implements [Isolate.spawn] by looking up |
| 1596 // top-level functions by name. So all top-level function tear-off | 1451 // top-level functions by name. So all top-level function tear-off |
| 1597 // closures have a private name field. | 1452 // closures have a private name field. |
| 1598 // | 1453 // |
| 1599 // The JavaScript backend of [Isolate.spawnUri] uses the same internal | 1454 // The JavaScript backend of [Isolate.spawnUri] uses the same internal |
| 1600 // implementation as [Isolate.spawn], and fails if it cannot look main up | 1455 // implementation as [Isolate.spawn], and fails if it cannot look main up |
| 1601 // by name. | 1456 // by name. |
| 1602 enqueuer.registerGetOfStaticFunction(compiler.mainFunction); | 1457 enqueuer.registerGetOfStaticFunction(compiler.mainFunction); |
| 1603 } | 1458 } |
| 1604 if (enqueuer.isResolutionQueue) { | 1459 if (enqueuer.isResolutionQueue) { |
| 1605 for (String name in const [START_ROOT_ISOLATE, | 1460 |
| 1606 '_currentIsolate', | 1461 void enqueue(Element element) { |
| 1607 '_callInIsolate']) { | |
| 1608 Element element = find(isolateHelperLibrary, name); | |
| 1609 enqueuer.addToWorkList(element); | 1462 enqueuer.addToWorkList(element); |
| 1610 compiler.globalDependencies.registerDependency(element); | 1463 compiler.globalDependencies.registerDependency(element); |
| 1611 helpersUsed.add(element.declaration); | 1464 helpersUsed.add(element.declaration); |
| 1612 } | 1465 } |
| 1466 |
| 1467 enqueue(helpers.startRootIsolate); |
| 1468 enqueue(helpers.currentIsolate); |
| 1469 enqueue(helpers.callInIsolate); |
| 1613 } else { | 1470 } else { |
| 1614 enqueuer.addToWorkList(find(isolateHelperLibrary, START_ROOT_ISOLATE)); | 1471 enqueuer.addToWorkList(helpers.startRootIsolate); |
| 1615 } | 1472 } |
| 1616 } | 1473 } |
| 1617 | 1474 |
| 1618 bool classNeedsRti(ClassElement cls) { | 1475 bool classNeedsRti(ClassElement cls) { |
| 1619 return rti.classesNeedingRti.contains(cls.declaration) || | 1476 return rti.classesNeedingRti.contains(cls.declaration) || |
| 1620 compiler.enabledRuntimeType; | 1477 compiler.enabledRuntimeType; |
| 1621 } | 1478 } |
| 1622 | 1479 |
| 1623 bool isComplexNoSuchMethod(FunctionElement element) => | 1480 bool isComplexNoSuchMethod(FunctionElement element) => |
| 1624 noSuchMethodRegistry.isComplex(element); | 1481 noSuchMethodRegistry.isComplex(element); |
| 1625 | 1482 |
| 1626 bool isDefaultEqualityImplementation(Element element) { | 1483 bool isDefaultEqualityImplementation(Element element) { |
| 1627 assert(element.name == '=='); | 1484 assert(element.name == '=='); |
| 1628 ClassElement classElement = element.enclosingClass; | 1485 ClassElement classElement = element.enclosingClass; |
| 1629 return classElement == coreClasses.objectClass | 1486 return classElement == coreClasses.objectClass |
| 1630 || classElement == jsInterceptorClass | 1487 || classElement == helpers.jsInterceptorClass |
| 1631 || classElement == jsNullClass; | 1488 || classElement == helpers.jsNullClass; |
| 1632 } | 1489 } |
| 1633 | 1490 |
| 1634 bool methodNeedsRti(FunctionElement function) { | 1491 bool methodNeedsRti(FunctionElement function) { |
| 1635 return rti.methodsNeedingRti.contains(function) || | 1492 return rti.methodsNeedingRti.contains(function) || |
| 1636 compiler.enabledRuntimeType; | 1493 compiler.enabledRuntimeType; |
| 1637 } | 1494 } |
| 1638 | 1495 |
| 1639 /// The backend must *always* call this method when enqueuing an | 1496 /// The backend must *always* call this method when enqueuing an |
| 1640 /// element. Calls done by the backend are not seen by global | 1497 /// element. Calls done by the backend are not seen by global |
| 1641 /// optimizations, so they would make these optimizations unsound. | 1498 /// optimizations, so they would make these optimizations unsound. |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1722 Element element = work.element; | 1579 Element element = work.element; |
| 1723 if (compiler.elementHasCompileTimeError(element)) { | 1580 if (compiler.elementHasCompileTimeError(element)) { |
| 1724 generatedCode[element] = jsAst.js( | 1581 generatedCode[element] = jsAst.js( |
| 1725 "function () { throw new Error('Compile time error in $element') }"); | 1582 "function () { throw new Error('Compile time error in $element') }"); |
| 1726 return const WorldImpact(); | 1583 return const WorldImpact(); |
| 1727 } | 1584 } |
| 1728 var kind = element.kind; | 1585 var kind = element.kind; |
| 1729 if (kind == ElementKind.TYPEDEF) { | 1586 if (kind == ElementKind.TYPEDEF) { |
| 1730 return const WorldImpact(); | 1587 return const WorldImpact(); |
| 1731 } | 1588 } |
| 1732 if (element.isConstructor && element.enclosingClass == jsNullClass) { | 1589 if (element.isConstructor && |
| 1590 element.enclosingClass == helpers.jsNullClass) { |
| 1733 // Work around a problem compiling JSNull's constructor. | 1591 // Work around a problem compiling JSNull's constructor. |
| 1734 return const WorldImpact(); | 1592 return const WorldImpact(); |
| 1735 } | 1593 } |
| 1736 if (kind.category == ElementCategory.VARIABLE) { | 1594 if (kind.category == ElementCategory.VARIABLE) { |
| 1737 ConstantValue initialValue = | 1595 ConstantValue initialValue = |
| 1738 constants.getConstantValueForVariable(element); | 1596 constants.getConstantValueForVariable(element); |
| 1739 if (initialValue != null) { | 1597 if (initialValue != null) { |
| 1740 registerCompileTimeConstant(initialValue, work.registry); | 1598 registerCompileTimeConstant(initialValue, work.registry); |
| 1741 addCompileTimeConstantForEmission(initialValue); | 1599 addCompileTimeConstantForEmission(initialValue); |
| 1742 // We don't need to generate code for static or top-level | 1600 // We don't need to generate code for static or top-level |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1761 | 1619 |
| 1762 native.NativeEnqueuer nativeResolutionEnqueuer(Enqueuer world) { | 1620 native.NativeEnqueuer nativeResolutionEnqueuer(Enqueuer world) { |
| 1763 return new native.NativeResolutionEnqueuer(world, compiler); | 1621 return new native.NativeResolutionEnqueuer(world, compiler); |
| 1764 } | 1622 } |
| 1765 | 1623 |
| 1766 native.NativeEnqueuer nativeCodegenEnqueuer(Enqueuer world) { | 1624 native.NativeEnqueuer nativeCodegenEnqueuer(Enqueuer world) { |
| 1767 return new native.NativeCodegenEnqueuer(world, compiler, emitter); | 1625 return new native.NativeCodegenEnqueuer(world, compiler, emitter); |
| 1768 } | 1626 } |
| 1769 | 1627 |
| 1770 ClassElement defaultSuperclass(ClassElement element) { | 1628 ClassElement defaultSuperclass(ClassElement element) { |
| 1771 if (isJsInterop(element)) return jsJavaScriptObjectClass; | 1629 if (isJsInterop(element)) { |
| 1630 return helpers.jsJavaScriptObjectClass; |
| 1631 } |
| 1772 // Native classes inherit from Interceptor. | 1632 // Native classes inherit from Interceptor. |
| 1773 return isNative(element) ? jsInterceptorClass : coreClasses.objectClass; | 1633 return isNative(element) |
| 1634 ? helpers.jsInterceptorClass : coreClasses.objectClass; |
| 1774 } | 1635 } |
| 1775 | 1636 |
| 1776 /** | 1637 /** |
| 1777 * Unit test hook that returns code of an element as a String. | 1638 * Unit test hook that returns code of an element as a String. |
| 1778 * | 1639 * |
| 1779 * Invariant: [element] must be a declaration element. | 1640 * Invariant: [element] must be a declaration element. |
| 1780 */ | 1641 */ |
| 1781 String getGeneratedCode(Element element) { | 1642 String getGeneratedCode(Element element) { |
| 1782 assert(invariant(element, element.isDeclaration)); | 1643 assert(invariant(element, element.isDeclaration)); |
| 1783 return jsAst.prettyPrint(generatedCode[element], compiler).getText(); | 1644 return jsAst.prettyPrint(generatedCode[element], compiler).getText(); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1876 | 1737 |
| 1877 // TODO(13955), TODO(9731). The test for non-primitive types should use an | 1738 // TODO(13955), TODO(9731). The test for non-primitive types should use an |
| 1878 // interceptor. The interceptor should be an argument to HTypeConversion so | 1739 // interceptor. The interceptor should be an argument to HTypeConversion so |
| 1879 // that it can be optimized by standard interceptor optimizations. | 1740 // that it can be optimized by standard interceptor optimizations. |
| 1880 nativeCheck = true; | 1741 nativeCheck = true; |
| 1881 | 1742 |
| 1882 if (type.isVoid) { | 1743 if (type.isVoid) { |
| 1883 assert(!typeCast); // Cannot cast to void. | 1744 assert(!typeCast); // Cannot cast to void. |
| 1884 if (nativeCheckOnly) return null; | 1745 if (nativeCheckOnly) return null; |
| 1885 return 'voidTypeCheck'; | 1746 return 'voidTypeCheck'; |
| 1886 } else if (element == jsStringClass || | 1747 } else if (element == helpers.jsStringClass || |
| 1887 element == coreClasses.stringClass) { | 1748 element == coreClasses.stringClass) { |
| 1888 if (nativeCheckOnly) return null; | 1749 if (nativeCheckOnly) return null; |
| 1889 return typeCast | 1750 return typeCast |
| 1890 ? 'stringTypeCast' | 1751 ? 'stringTypeCast' |
| 1891 : 'stringTypeCheck'; | 1752 : 'stringTypeCheck'; |
| 1892 } else if (element == jsDoubleClass || | 1753 } else if (element == helpers.jsDoubleClass || |
| 1893 element == coreClasses.doubleClass) { | 1754 element == coreClasses.doubleClass) { |
| 1894 if (nativeCheckOnly) return null; | 1755 if (nativeCheckOnly) return null; |
| 1895 return typeCast | 1756 return typeCast |
| 1896 ? 'doubleTypeCast' | 1757 ? 'doubleTypeCast' |
| 1897 : 'doubleTypeCheck'; | 1758 : 'doubleTypeCheck'; |
| 1898 } else if (element == jsNumberClass || | 1759 } else if (element == helpers.jsNumberClass || |
| 1899 element == coreClasses.numClass) { | 1760 element == coreClasses.numClass) { |
| 1900 if (nativeCheckOnly) return null; | 1761 if (nativeCheckOnly) return null; |
| 1901 return typeCast | 1762 return typeCast |
| 1902 ? 'numTypeCast' | 1763 ? 'numTypeCast' |
| 1903 : 'numTypeCheck'; | 1764 : 'numTypeCheck'; |
| 1904 } else if (element == jsBoolClass || | 1765 } else if (element == helpers.jsBoolClass || |
| 1905 element == coreClasses.boolClass) { | 1766 element == coreClasses.boolClass) { |
| 1906 if (nativeCheckOnly) return null; | 1767 if (nativeCheckOnly) return null; |
| 1907 return typeCast | 1768 return typeCast |
| 1908 ? 'boolTypeCast' | 1769 ? 'boolTypeCast' |
| 1909 : 'boolTypeCheck'; | 1770 : 'boolTypeCheck'; |
| 1910 } else if (element == jsIntClass || | 1771 } else if (element == helpers.jsIntClass || |
| 1911 element == coreClasses.intClass || | 1772 element == coreClasses.intClass || |
| 1912 element == jsUInt32Class || | 1773 element == helpers.jsUInt32Class || |
| 1913 element == jsUInt31Class || | 1774 element == helpers.jsUInt31Class || |
| 1914 element == jsPositiveIntClass) { | 1775 element == helpers.jsPositiveIntClass) { |
| 1915 if (nativeCheckOnly) return null; | 1776 if (nativeCheckOnly) return null; |
| 1916 return typeCast | 1777 return typeCast |
| 1917 ? 'intTypeCast' | 1778 ? 'intTypeCast' |
| 1918 : 'intTypeCheck'; | 1779 : 'intTypeCheck'; |
| 1919 } else if (Elements.isNumberOrStringSupertype(element, compiler)) { | 1780 } else if (Elements.isNumberOrStringSupertype(element, compiler)) { |
| 1920 if (nativeCheck) { | 1781 if (nativeCheck) { |
| 1921 return typeCast | 1782 return typeCast |
| 1922 ? 'numberOrStringSuperNativeTypeCast' | 1783 ? 'numberOrStringSuperNativeTypeCast' |
| 1923 : 'numberOrStringSuperNativeTypeCheck'; | 1784 : 'numberOrStringSuperNativeTypeCheck'; |
| 1924 } else { | 1785 } else { |
| 1925 return typeCast | 1786 return typeCast |
| 1926 ? 'numberOrStringSuperTypeCast' | 1787 ? 'numberOrStringSuperTypeCast' |
| 1927 : 'numberOrStringSuperTypeCheck'; | 1788 : 'numberOrStringSuperTypeCheck'; |
| 1928 } | 1789 } |
| 1929 } else if (Elements.isStringOnlySupertype(element, compiler)) { | 1790 } else if (Elements.isStringOnlySupertype(element, compiler)) { |
| 1930 if (nativeCheck) { | 1791 if (nativeCheck) { |
| 1931 return typeCast | 1792 return typeCast |
| 1932 ? 'stringSuperNativeTypeCast' | 1793 ? 'stringSuperNativeTypeCast' |
| 1933 : 'stringSuperNativeTypeCheck'; | 1794 : 'stringSuperNativeTypeCheck'; |
| 1934 } else { | 1795 } else { |
| 1935 return typeCast | 1796 return typeCast |
| 1936 ? 'stringSuperTypeCast' | 1797 ? 'stringSuperTypeCast' |
| 1937 : 'stringSuperTypeCheck'; | 1798 : 'stringSuperTypeCheck'; |
| 1938 } | 1799 } |
| 1939 } else if ((element == coreClasses.listClass || | 1800 } else if ((element == coreClasses.listClass || |
| 1940 element == jsArrayClass) && | 1801 element == helpers.jsArrayClass) && |
| 1941 type.treatAsRaw) { | 1802 type.treatAsRaw) { |
| 1942 if (nativeCheckOnly) return null; | 1803 if (nativeCheckOnly) return null; |
| 1943 return typeCast | 1804 return typeCast |
| 1944 ? 'listTypeCast' | 1805 ? 'listTypeCast' |
| 1945 : 'listTypeCheck'; | 1806 : 'listTypeCheck'; |
| 1946 } else { | 1807 } else { |
| 1947 if (Elements.isListSupertype(element, compiler)) { | 1808 if (Elements.isListSupertype(element, compiler)) { |
| 1948 if (nativeCheck) { | 1809 if (nativeCheck) { |
| 1949 return typeCast | 1810 return typeCast |
| 1950 ? 'listSuperNativeTypeCast' | 1811 ? 'listSuperNativeTypeCast' |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1994 * Returns [:true:] if the checking of [type] is performed directly on the | 1855 * Returns [:true:] if the checking of [type] is performed directly on the |
| 1995 * object and not on an interceptor. | 1856 * object and not on an interceptor. |
| 1996 */ | 1857 */ |
| 1997 bool hasDirectCheckFor(DartType type) { | 1858 bool hasDirectCheckFor(DartType type) { |
| 1998 Element element = type.element; | 1859 Element element = type.element; |
| 1999 return element == coreClasses.stringClass || | 1860 return element == coreClasses.stringClass || |
| 2000 element == coreClasses.boolClass || | 1861 element == coreClasses.boolClass || |
| 2001 element == coreClasses.numClass || | 1862 element == coreClasses.numClass || |
| 2002 element == coreClasses.intClass || | 1863 element == coreClasses.intClass || |
| 2003 element == coreClasses.doubleClass || | 1864 element == coreClasses.doubleClass || |
| 2004 element == jsArrayClass || | 1865 element == helpers.jsArrayClass || |
| 2005 element == jsMutableArrayClass || | 1866 element == helpers.jsMutableArrayClass || |
| 2006 element == jsExtendableArrayClass || | 1867 element == helpers.jsExtendableArrayClass || |
| 2007 element == jsFixedArrayClass || | 1868 element == helpers.jsFixedArrayClass || |
| 2008 element == jsUnmodifiableArrayClass; | 1869 element == helpers.jsUnmodifiableArrayClass; |
| 2009 } | 1870 } |
| 2010 | 1871 |
| 2011 bool mayGenerateInstanceofCheck(DartType type) { | 1872 bool mayGenerateInstanceofCheck(DartType type) { |
| 2012 // We can use an instanceof check for raw types that have no subclass that | 1873 // We can use an instanceof check for raw types that have no subclass that |
| 2013 // is mixed-in or in an implements clause. | 1874 // is mixed-in or in an implements clause. |
| 2014 | 1875 |
| 2015 if (!type.isRaw) return false; | 1876 if (!type.isRaw) return false; |
| 2016 ClassElement classElement = type.element; | 1877 ClassElement classElement = type.element; |
| 2017 if (isInterceptorClass(classElement)) return false; | 1878 if (isInterceptorClass(classElement)) return false; |
| 2018 return compiler.world.hasOnlySubclasses(classElement); | 1879 return compiler.world.hasOnlySubclasses(classElement); |
| 2019 } | 1880 } |
| 2020 | 1881 |
| 2021 bool isNullImplementation(ClassElement cls) { | 1882 bool isNullImplementation(ClassElement cls) { |
| 2022 return cls == jsNullClass; | 1883 return cls == helpers.jsNullClass; |
| 2023 } | 1884 } |
| 2024 | 1885 |
| 2025 ClassElement get intImplementation => jsIntClass; | 1886 ClassElement get intImplementation => helpers.jsIntClass; |
| 2026 ClassElement get uint32Implementation => jsUInt32Class; | 1887 ClassElement get uint32Implementation => helpers.jsUInt32Class; |
| 2027 ClassElement get uint31Implementation => jsUInt31Class; | 1888 ClassElement get uint31Implementation => helpers.jsUInt31Class; |
| 2028 ClassElement get positiveIntImplementation => jsPositiveIntClass; | 1889 ClassElement get positiveIntImplementation => helpers.jsPositiveIntClass; |
| 2029 ClassElement get doubleImplementation => jsDoubleClass; | 1890 ClassElement get doubleImplementation => helpers.jsDoubleClass; |
| 2030 ClassElement get numImplementation => jsNumberClass; | 1891 ClassElement get numImplementation => helpers.jsNumberClass; |
| 2031 ClassElement get stringImplementation => jsStringClass; | 1892 ClassElement get stringImplementation => helpers.jsStringClass; |
| 2032 ClassElement get listImplementation => jsArrayClass; | 1893 ClassElement get listImplementation => helpers.jsArrayClass; |
| 2033 ClassElement get constListImplementation => jsUnmodifiableArrayClass; | 1894 ClassElement get constListImplementation => helpers.jsUnmodifiableArrayClass; |
| 2034 ClassElement get fixedListImplementation => jsFixedArrayClass; | 1895 ClassElement get fixedListImplementation => helpers.jsFixedArrayClass; |
| 2035 ClassElement get growableListImplementation => jsExtendableArrayClass; | 1896 ClassElement get growableListImplementation => helpers.jsExtendableArrayClass; |
| 2036 ClassElement get mapImplementation => mapLiteralClass; | 1897 ClassElement get mapImplementation => helpers.mapLiteralClass; |
| 2037 ClassElement get constMapImplementation => constMapLiteralClass; | 1898 ClassElement get constMapImplementation => helpers.constMapLiteralClass; |
| 2038 ClassElement get typeImplementation => typeLiteralClass; | 1899 ClassElement get typeImplementation => helpers.typeLiteralClass; |
| 2039 ClassElement get boolImplementation => jsBoolClass; | 1900 ClassElement get boolImplementation => helpers.jsBoolClass; |
| 2040 ClassElement get nullImplementation => jsNullClass; | 1901 ClassElement get nullImplementation => helpers.jsNullClass; |
| 2041 | 1902 |
| 2042 void registerStaticUse(Element element, Enqueuer enqueuer) { | 1903 void registerStaticUse(Element element, Enqueuer enqueuer) { |
| 2043 if (element == disableTreeShakingMarker) { | 1904 if (element == helpers.disableTreeShakingMarker) { |
| 2044 compiler.disableTypeInferenceForMirrors = true; | 1905 compiler.disableTypeInferenceForMirrors = true; |
| 2045 isTreeShakingDisabled = true; | 1906 isTreeShakingDisabled = true; |
| 2046 } else if (element == preserveNamesMarker) { | 1907 } else if (element == helpers.preserveNamesMarker) { |
| 2047 mustPreserveNames = true; | 1908 mustPreserveNames = true; |
| 2048 } else if (element == preserveMetadataMarker) { | 1909 } else if (element == helpers.preserveMetadataMarker) { |
| 2049 mustRetainMetadata = true; | 1910 mustRetainMetadata = true; |
| 2050 } else if (element == preserveUrisMarker) { | 1911 } else if (element == helpers.preserveUrisMarker) { |
| 2051 if (compiler.preserveUris) mustPreserveUris = true; | 1912 if (compiler.preserveUris) mustPreserveUris = true; |
| 2052 } else if (element == preserveLibraryNamesMarker) { | 1913 } else if (element == helpers.preserveLibraryNamesMarker) { |
| 2053 mustRetainLibraryNames = true; | 1914 mustRetainLibraryNames = true; |
| 2054 } else if (element == getIsolateAffinityTagMarker) { | 1915 } else if (element == helpers.getIsolateAffinityTagMarker) { |
| 2055 needToInitializeIsolateAffinityTag = true; | 1916 needToInitializeIsolateAffinityTag = true; |
| 2056 } else if (element.isDeferredLoaderGetter) { | 1917 } else if (element.isDeferredLoaderGetter) { |
| 2057 // TODO(sigurdm): Create a function registerLoadLibraryAccess. | 1918 // TODO(sigurdm): Create a function registerLoadLibraryAccess. |
| 2058 if (compiler.loadLibraryFunction == null) { | 1919 if (compiler.loadLibraryFunction == null) { |
| 2059 compiler.loadLibraryFunction = | 1920 compiler.loadLibraryFunction = helpers.loadLibraryWrapper; |
| 2060 findHelper("_loadLibraryWrapper"); | |
| 2061 enqueueInResolution(compiler.loadLibraryFunction, | 1921 enqueueInResolution(compiler.loadLibraryFunction, |
| 2062 compiler.globalDependencies); | 1922 compiler.globalDependencies); |
| 2063 } | 1923 } |
| 2064 } else if (element == requiresPreambleMarker) { | 1924 } else if (element == helpers.requiresPreambleMarker) { |
| 2065 requiresPreamble = true; | 1925 requiresPreamble = true; |
| 2066 } | 1926 } |
| 2067 customElementsAnalysis.registerStaticUse(element, enqueuer); | 1927 customElementsAnalysis.registerStaticUse(element, enqueuer); |
| 2068 } | 1928 } |
| 2069 | 1929 |
| 2070 /// Called when [:const Symbol(name):] is seen. | 1930 /// Called when [:const Symbol(name):] is seen. |
| 2071 void registerConstSymbol(String name) { | 1931 void registerConstSymbol(String name) { |
| 2072 symbolsUsed.add(name); | 1932 symbolsUsed.add(name); |
| 2073 if (name.endsWith('=')) { | 1933 if (name.endsWith('=')) { |
| 2074 symbolsUsed.add(name.substring(0, name.length - 1)); | 1934 symbolsUsed.add(name.substring(0, name.length - 1)); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2106 ConstantValue constant = | 1966 ConstantValue constant = |
| 2107 constants.getConstantValueForMetadata(metadata); | 1967 constants.getConstantValueForMetadata(metadata); |
| 2108 constants.addCompileTimeConstantForEmission(constant); | 1968 constants.addCompileTimeConstantForEmission(constant); |
| 2109 } | 1969 } |
| 2110 return true; | 1970 return true; |
| 2111 } | 1971 } |
| 2112 return false; | 1972 return false; |
| 2113 } | 1973 } |
| 2114 | 1974 |
| 2115 void onLibraryCreated(LibraryElement library) { | 1975 void onLibraryCreated(LibraryElement library) { |
| 2116 Uri uri = library.canonicalUri; | 1976 helpers.onLibraryCreated(library); |
| 2117 if (uri == DART_JS_HELPER) { | |
| 2118 jsHelperLibrary = library; | |
| 2119 } else if (uri == Uris.dart_async) { | |
| 2120 asyncLibrary = library; | |
| 2121 } else if (uri == Uris.dart__internal) { | |
| 2122 internalLibrary = library; | |
| 2123 } else if (uri == DART_INTERCEPTORS) { | |
| 2124 interceptorsLibrary = library; | |
| 2125 } else if (uri == DART_FOREIGN_HELPER) { | |
| 2126 foreignLibrary = library; | |
| 2127 } else if (uri == DART_ISOLATE_HELPER) { | |
| 2128 isolateHelperLibrary = library; | |
| 2129 } | |
| 2130 } | |
| 2131 | |
| 2132 void initializeHelperClasses() { | |
| 2133 final List missingHelperClasses = []; | |
| 2134 ClassElement lookupHelperClass(String name) { | |
| 2135 ClassElement result = findHelper(name); | |
| 2136 if (result == null) { | |
| 2137 missingHelperClasses.add(name); | |
| 2138 } | |
| 2139 return result; | |
| 2140 } | |
| 2141 jsInvocationMirrorClass = lookupHelperClass('JSInvocationMirror'); | |
| 2142 boundClosureClass = lookupHelperClass('BoundClosure'); | |
| 2143 closureClass = lookupHelperClass('Closure'); | |
| 2144 if (!missingHelperClasses.isEmpty) { | |
| 2145 reporter.internalError(jsHelperLibrary, | |
| 2146 'dart:_js_helper library does not contain required classes: ' | |
| 2147 '$missingHelperClasses'); | |
| 2148 } | |
| 2149 } | 1977 } |
| 2150 | 1978 |
| 2151 Future onLibraryScanned(LibraryElement library, LibraryLoader loader) { | 1979 Future onLibraryScanned(LibraryElement library, LibraryLoader loader) { |
| 2152 return super.onLibraryScanned(library, loader).then((_) { | 1980 return super.onLibraryScanned(library, loader).then((_) { |
| 2153 if (library.isPlatformLibrary && | 1981 if (library.isPlatformLibrary && |
| 2154 // Don't patch library currently disallowed. | 1982 // Don't patch library currently disallowed. |
| 2155 !library.isSynthesized && | 1983 !library.isSynthesized && |
| 2156 !library.isPatched) { | 1984 !library.isPatched) { |
| 2157 // Apply patch, if any. | 1985 // Apply patch, if any. |
| 2158 Uri patchUri = compiler.resolvePatchUri(library.canonicalUri.path); | 1986 Uri patchUri = compiler.resolvePatchUri(library.canonicalUri.path); |
| 2159 if (patchUri != null) { | 1987 if (patchUri != null) { |
| 2160 return compiler.patchParser.patchLibrary(loader, patchUri, library); | 1988 return compiler.patchParser.patchLibrary(loader, patchUri, library); |
| 2161 } | 1989 } |
| 2162 } | 1990 } |
| 2163 }).then((_) { | 1991 }).then((_) { |
| 1992 helpers.onLibraryScanned(library); |
| 2164 Uri uri = library.canonicalUri; | 1993 Uri uri = library.canonicalUri; |
| 2165 | 1994 if (uri == Uris.dart_html) { |
| 2166 FunctionElement findMethod(String name) { | |
| 2167 return find(library, name); | |
| 2168 } | |
| 2169 | |
| 2170 ClassElement findClass(String name) { | |
| 2171 return find(library, name); | |
| 2172 } | |
| 2173 | |
| 2174 if (uri == DART_INTERCEPTORS) { | |
| 2175 getInterceptorMethod = findMethod('getInterceptor'); | |
| 2176 getNativeInterceptorMethod = findMethod('getNativeInterceptor'); | |
| 2177 jsInterceptorClass = findClass('Interceptor'); | |
| 2178 jsStringClass = findClass('JSString'); | |
| 2179 jsArrayClass = findClass('JSArray'); | |
| 2180 // The int class must be before the double class, because the | |
| 2181 // emitter relies on this list for the order of type checks. | |
| 2182 jsIntClass = findClass('JSInt'); | |
| 2183 jsPositiveIntClass = findClass('JSPositiveInt'); | |
| 2184 jsUInt32Class = findClass('JSUInt32'); | |
| 2185 jsUInt31Class = findClass('JSUInt31'); | |
| 2186 jsDoubleClass = findClass('JSDouble'); | |
| 2187 jsNumberClass = findClass('JSNumber'); | |
| 2188 jsNullClass = findClass('JSNull'); | |
| 2189 jsBoolClass = findClass('JSBool'); | |
| 2190 jsMutableArrayClass = findClass('JSMutableArray'); | |
| 2191 jsFixedArrayClass = findClass('JSFixedArray'); | |
| 2192 jsExtendableArrayClass = findClass('JSExtendableArray'); | |
| 2193 jsUnmodifiableArrayClass = findClass('JSUnmodifiableArray'); | |
| 2194 jsPlainJavaScriptObjectClass = findClass('PlainJavaScriptObject'); | |
| 2195 jsJavaScriptObjectClass = findClass('JavaScriptObject'); | |
| 2196 jsJavaScriptFunctionClass = findClass('JavaScriptFunction'); | |
| 2197 jsUnknownJavaScriptObjectClass = findClass('UnknownJavaScriptObject'); | |
| 2198 jsIndexableClass = findClass('JSIndexable'); | |
| 2199 jsMutableIndexableClass = findClass('JSMutableIndexable'); | |
| 2200 } else if (uri == DART_JS_HELPER) { | |
| 2201 initializeHelperClasses(); | |
| 2202 helpers.assertTest = findHelper('assertTest'); | |
| 2203 helpers.assertThrow = findHelper('assertThrow'); | |
| 2204 helpers.assertHelper = findHelper('assertHelper'); | |
| 2205 assertUnreachableMethod = findHelper('assertUnreachable'); | |
| 2206 | |
| 2207 typeLiteralClass = findClass('TypeImpl'); | |
| 2208 constMapLiteralClass = findClass('ConstantMap'); | |
| 2209 typeVariableClass = findClass('TypeVariable'); | |
| 2210 | |
| 2211 jsIndexingBehaviorInterface = findClass('JavaScriptIndexingBehavior'); | |
| 2212 | |
| 2213 noSideEffectsClass = findClass('NoSideEffects'); | |
| 2214 noThrowsClass = findClass('NoThrows'); | |
| 2215 noInlineClass = findClass('NoInline'); | |
| 2216 forceInlineClass = findClass('ForceInline'); | |
| 2217 irRepresentationClass = findClass('IrRepresentation'); | |
| 2218 | |
| 2219 getIsolateAffinityTagMarker = findMethod('getIsolateAffinityTag'); | |
| 2220 | |
| 2221 requiresPreambleMarker = findMethod('requiresPreamble'); | |
| 2222 } else if (uri == DART_JS_MIRRORS) { | |
| 2223 disableTreeShakingMarker = find(library, 'disableTreeShaking'); | |
| 2224 preserveMetadataMarker = find(library, 'preserveMetadata'); | |
| 2225 preserveUrisMarker = find(library, 'preserveUris'); | |
| 2226 preserveLibraryNamesMarker = find(library, 'preserveLibraryNames'); | |
| 2227 } else if (uri == DART_JS_NAMES) { | |
| 2228 preserveNamesMarker = find(library, 'preserveNames'); | |
| 2229 } else if (uri == DART_EMBEDDED_NAMES) { | |
| 2230 jsGetNameEnum = find(library, 'JsGetName'); | |
| 2231 jsBuiltinEnum = find(library, 'JsBuiltin'); | |
| 2232 } else if (uri == Uris.dart_html) { | |
| 2233 htmlLibraryIsLoaded = true; | 1995 htmlLibraryIsLoaded = true; |
| 2234 } else if (uri == PACKAGE_LOOKUP_MAP) { | 1996 } else if (uri == LookupMapAnalysis.PACKAGE_LOOKUP_MAP) { |
| 2235 lookupMapAnalysis.init(library); | 1997 lookupMapAnalysis.init(library); |
| 2236 } else if (uri == Uris.dart__native_typed_data) { | |
| 2237 typedArrayClass = findClass('NativeTypedArray'); | |
| 2238 typedArrayOfIntClass = findClass('NativeTypedArrayOfInt'); | |
| 2239 } else if (uri == PACKAGE_JS) { | |
| 2240 jsAnnotationClass = find(library, 'JS'); | |
| 2241 } | 1998 } |
| 2242 annotations.onLibraryScanned(library); | 1999 annotations.onLibraryScanned(library); |
| 2243 }); | 2000 }); |
| 2244 } | 2001 } |
| 2245 | 2002 |
| 2246 Future onLibrariesLoaded(LoadedLibraries loadedLibraries) { | 2003 Future onLibrariesLoaded(LoadedLibraries loadedLibraries) { |
| 2247 if (!loadedLibraries.containsLibrary(Uris.dart_core)) { | 2004 if (!loadedLibraries.containsLibrary(Uris.dart_core)) { |
| 2248 return new Future.value(); | 2005 return new Future.value(); |
| 2249 } | 2006 } |
| 2250 | 2007 |
| 2251 assert(loadedLibraries.containsLibrary(Uris.dart_core)); | 2008 helpers.onLibrariesLoaded(loadedLibraries); |
| 2252 assert(loadedLibraries.containsLibrary(DART_INTERCEPTORS)); | |
| 2253 assert(loadedLibraries.containsLibrary(DART_JS_HELPER)); | |
| 2254 | |
| 2255 if (jsInvocationMirrorClass != null) { | |
| 2256 jsInvocationMirrorClass.ensureResolved(resolution); | |
| 2257 invokeOnMethod = jsInvocationMirrorClass.lookupLocalMember(INVOKE_ON); | |
| 2258 } | |
| 2259 | |
| 2260 // [LinkedHashMap] is reexported from dart:collection and can therefore not | |
| 2261 // be loaded from dart:core in [onLibraryScanned]. | |
| 2262 mapLiteralClass = compiler.coreLibrary.find('LinkedHashMap'); | |
| 2263 assert(invariant(compiler.coreLibrary, mapLiteralClass != null, | |
| 2264 message: "Element 'LinkedHashMap' not found in 'dart:core'.")); | |
| 2265 | 2009 |
| 2266 implementationClasses = <ClassElement, ClassElement>{}; | 2010 implementationClasses = <ClassElement, ClassElement>{}; |
| 2267 implementationClasses[coreClasses.intClass] = jsIntClass; | 2011 implementationClasses[coreClasses.intClass] = helpers.jsIntClass; |
| 2268 implementationClasses[coreClasses.boolClass] = jsBoolClass; | 2012 implementationClasses[coreClasses.boolClass] = helpers.jsBoolClass; |
| 2269 implementationClasses[coreClasses.numClass] = jsNumberClass; | 2013 implementationClasses[coreClasses.numClass] = helpers.jsNumberClass; |
| 2270 implementationClasses[coreClasses.doubleClass] = jsDoubleClass; | 2014 implementationClasses[coreClasses.doubleClass] = helpers.jsDoubleClass; |
| 2271 implementationClasses[coreClasses.stringClass] = jsStringClass; | 2015 implementationClasses[coreClasses.stringClass] = helpers.jsStringClass; |
| 2272 implementationClasses[coreClasses.listClass] = jsArrayClass; | 2016 implementationClasses[coreClasses.listClass] = helpers.jsArrayClass; |
| 2273 implementationClasses[coreClasses.nullClass] = jsNullClass; | 2017 implementationClasses[coreClasses.nullClass] = helpers.jsNullClass; |
| 2274 | 2018 |
| 2275 // These methods are overwritten with generated versions. | 2019 // These methods are overwritten with generated versions. |
| 2276 inlineCache.markAsNonInlinable(getInterceptorMethod, insideLoop: true); | 2020 inlineCache.markAsNonInlinable( |
| 2277 | 2021 helpers.getInterceptorMethod, insideLoop: true); |
| 2278 // TODO(kasperl): Some tests do not define the special JSArray | |
| 2279 // subclasses, so we check to see if they are defined before | |
| 2280 // trying to resolve them. | |
| 2281 if (jsFixedArrayClass != null) { | |
| 2282 jsFixedArrayClass.ensureResolved(resolution); | |
| 2283 } | |
| 2284 if (jsExtendableArrayClass != null) { | |
| 2285 jsExtendableArrayClass.ensureResolved(resolution); | |
| 2286 } | |
| 2287 if (jsUnmodifiableArrayClass != null) { | |
| 2288 jsUnmodifiableArrayClass.ensureResolved(resolution); | |
| 2289 } | |
| 2290 | |
| 2291 jsIndexableClass.ensureResolved(resolution); | |
| 2292 jsIndexableLength = compiler.lookupElementIn( | |
| 2293 jsIndexableClass, 'length'); | |
| 2294 if (jsIndexableLength != null && jsIndexableLength.isAbstractField) { | |
| 2295 AbstractFieldElement element = jsIndexableLength; | |
| 2296 jsIndexableLength = element.getter; | |
| 2297 } | |
| 2298 | |
| 2299 jsArrayClass.ensureResolved(resolution); | |
| 2300 jsArrayTypedConstructor = compiler.lookupElementIn(jsArrayClass, 'typed'); | |
| 2301 jsArrayRemoveLast = compiler.lookupElementIn(jsArrayClass, 'removeLast'); | |
| 2302 jsArrayAdd = compiler.lookupElementIn(jsArrayClass, 'add'); | |
| 2303 | |
| 2304 jsStringClass.ensureResolved(resolution); | |
| 2305 jsStringSplit = compiler.lookupElementIn(jsStringClass, 'split'); | |
| 2306 jsStringOperatorAdd = compiler.lookupElementIn(jsStringClass, '+'); | |
| 2307 jsStringToString = compiler.lookupElementIn(jsStringClass, 'toString'); | |
| 2308 | |
| 2309 objectEquals = compiler.lookupElementIn(coreClasses.objectClass, '=='); | |
| 2310 | 2022 |
| 2311 specialOperatorEqClasses | 2023 specialOperatorEqClasses |
| 2312 ..add(coreClasses.objectClass) | 2024 ..add(coreClasses.objectClass) |
| 2313 ..add(jsInterceptorClass) | 2025 ..add(helpers.jsInterceptorClass) |
| 2314 ..add(jsNullClass); | 2026 ..add(helpers.jsNullClass); |
| 2315 | 2027 |
| 2316 validateInterceptorImplementsAllObjectMethods(jsInterceptorClass); | 2028 validateInterceptorImplementsAllObjectMethods(helpers.jsInterceptorClass); |
| 2317 // The null-interceptor must also implement *all* methods. | 2029 // The null-interceptor must also implement *all* methods. |
| 2318 validateInterceptorImplementsAllObjectMethods(jsNullClass); | 2030 validateInterceptorImplementsAllObjectMethods(helpers.jsNullClass); |
| 2319 | 2031 |
| 2320 return new Future.value(); | 2032 return new Future.value(); |
| 2321 } | 2033 } |
| 2322 | 2034 |
| 2323 void registerMirrorUsage(Set<String> symbols, | 2035 void registerMirrorUsage(Set<String> symbols, |
| 2324 Set<Element> targets, | 2036 Set<Element> targets, |
| 2325 Set<Element> metaTargets) { | 2037 Set<Element> metaTargets) { |
| 2326 if (symbols == null && targets == null && metaTargets == null) { | 2038 if (symbols == null && targets == null && metaTargets == null) { |
| 2327 // The user didn't specify anything, or there are imports of | 2039 // The user didn't specify anything, or there are imports of |
| 2328 // 'dart:mirrors' without @MirrorsUsed. | 2040 // 'dart:mirrors' without @MirrorsUsed. |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2521 for (Element closure in closureMap[null]) { | 2233 for (Element closure in closureMap[null]) { |
| 2522 if (referencedFromMirrorSystem(closure)) { | 2234 if (referencedFromMirrorSystem(closure)) { |
| 2523 reflectableMembers.add(closure); | 2235 reflectableMembers.add(closure); |
| 2524 foundClosure = true; | 2236 foundClosure = true; |
| 2525 } | 2237 } |
| 2526 } | 2238 } |
| 2527 } | 2239 } |
| 2528 // As we do not think about closures as classes, yet, we have to make sure | 2240 // As we do not think about closures as classes, yet, we have to make sure |
| 2529 // their superclasses are available for reflection manually. | 2241 // their superclasses are available for reflection manually. |
| 2530 if (foundClosure) { | 2242 if (foundClosure) { |
| 2531 reflectableMembers.add(closureClass); | 2243 reflectableMembers.add(helpers.closureClass); |
| 2532 } | 2244 } |
| 2533 Set<Element> closurizedMembers = compiler.resolverWorld.closurizedMembers; | 2245 Set<Element> closurizedMembers = compiler.resolverWorld.closurizedMembers; |
| 2534 if (closurizedMembers.any(reflectableMembers.contains)) { | 2246 if (closurizedMembers.any(reflectableMembers.contains)) { |
| 2535 reflectableMembers.add(boundClosureClass); | 2247 reflectableMembers.add(helpers.boundClosureClass); |
| 2536 } | 2248 } |
| 2537 // Add typedefs. | 2249 // Add typedefs. |
| 2538 reflectableMembers | 2250 reflectableMembers |
| 2539 .addAll(compiler.world.allTypedefs.where(referencedFromMirrorSystem)); | 2251 .addAll(compiler.world.allTypedefs.where(referencedFromMirrorSystem)); |
| 2540 // Register all symbols of reflectable elements | 2252 // Register all symbols of reflectable elements |
| 2541 for (Element element in reflectableMembers) { | 2253 for (Element element in reflectableMembers) { |
| 2542 symbolsUsed.add(element.name); | 2254 symbolsUsed.add(element.name); |
| 2543 } | 2255 } |
| 2544 _membersNeededForReflection = reflectableMembers; | 2256 _membersNeededForReflection = reflectableMembers; |
| 2545 } | 2257 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2561 jsAst.Expression dispatchProperty = | 2273 jsAst.Expression dispatchProperty = |
| 2562 emitter.generateEmbeddedGlobalAccess(dispatchPropertyName); | 2274 emitter.generateEmbeddedGlobalAccess(dispatchPropertyName); |
| 2563 | 2275 |
| 2564 // We pass the dispatch property record to the isJsIndexable | 2276 // We pass the dispatch property record to the isJsIndexable |
| 2565 // helper rather than reading it inside the helper to increase the | 2277 // helper rather than reading it inside the helper to increase the |
| 2566 // chance of making the dispatch record access monomorphic. | 2278 // chance of making the dispatch record access monomorphic. |
| 2567 jsAst.PropertyAccess record = | 2279 jsAst.PropertyAccess record = |
| 2568 new jsAst.PropertyAccess(use2, dispatchProperty); | 2280 new jsAst.PropertyAccess(use2, dispatchProperty); |
| 2569 | 2281 |
| 2570 List<jsAst.Expression> arguments = <jsAst.Expression>[use1, record]; | 2282 List<jsAst.Expression> arguments = <jsAst.Expression>[use1, record]; |
| 2571 FunctionElement helper = findHelper('isJsIndexable'); | 2283 FunctionElement helper = helpers.isJsIndexable; |
| 2572 jsAst.Expression helperExpression = emitter.staticFunctionAccess(helper); | 2284 jsAst.Expression helperExpression = emitter.staticFunctionAccess(helper); |
| 2573 return new jsAst.Call(helperExpression, arguments); | 2285 return new jsAst.Call(helperExpression, arguments); |
| 2574 } | 2286 } |
| 2575 | 2287 |
| 2576 bool isTypedArray(TypeMask mask) { | 2288 bool isTypedArray(TypeMask mask) { |
| 2577 // Just checking for [:TypedData:] is not sufficient, as it is an | 2289 // Just checking for [:TypedData:] is not sufficient, as it is an |
| 2578 // abstract class any user-defined class can implement. So we also | 2290 // abstract class any user-defined class can implement. So we also |
| 2579 // check for the interface [JavaScriptIndexingBehavior]. | 2291 // check for the interface [JavaScriptIndexingBehavior]. |
| 2580 return | 2292 return |
| 2581 compiler.typedDataClass != null && | 2293 compiler.typedDataClass != null && |
| 2582 compiler.world.isInstantiated(compiler.typedDataClass) && | 2294 compiler.world.isInstantiated(compiler.typedDataClass) && |
| 2583 mask.satisfies(compiler.typedDataClass, compiler.world) && | 2295 mask.satisfies(compiler.typedDataClass, compiler.world) && |
| 2584 mask.satisfies(jsIndexingBehaviorInterface, compiler.world); | 2296 mask.satisfies(helpers.jsIndexingBehaviorInterface, compiler.world); |
| 2585 } | 2297 } |
| 2586 | 2298 |
| 2587 bool couldBeTypedArray(TypeMask mask) { | 2299 bool couldBeTypedArray(TypeMask mask) { |
| 2588 bool intersects(TypeMask type1, TypeMask type2) => | 2300 bool intersects(TypeMask type1, TypeMask type2) => |
| 2589 !type1.intersection(type2, compiler.world).isEmpty; | 2301 !type1.intersection(type2, compiler.world).isEmpty; |
| 2590 // TODO(herhut): Maybe cache the TypeMask for typedDataClass and | 2302 // TODO(herhut): Maybe cache the TypeMask for typedDataClass and |
| 2591 // jsIndexingBehaviourInterface. | 2303 // jsIndexingBehaviourInterface. |
| 2592 return | 2304 return |
| 2593 compiler.typedDataClass != null && | 2305 compiler.typedDataClass != null && |
| 2594 compiler.world.isInstantiated(compiler.typedDataClass) && | 2306 compiler.world.isInstantiated(compiler.typedDataClass) && |
| 2595 intersects(mask, | 2307 intersects(mask, |
| 2596 new TypeMask.subtype(compiler.typedDataClass, compiler.world)) && | 2308 new TypeMask.subtype(compiler.typedDataClass, compiler.world)) && |
| 2597 intersects(mask, | 2309 intersects(mask, |
| 2598 new TypeMask.subtype(jsIndexingBehaviorInterface, compiler.world)); | 2310 new TypeMask.subtype(helpers.jsIndexingBehaviorInterface, compiler.w
orld)); |
| 2599 } | 2311 } |
| 2600 | 2312 |
| 2601 /// Returns all static fields that are referenced through [targetsUsed]. | 2313 /// Returns all static fields that are referenced through [targetsUsed]. |
| 2602 /// If the target is a library or class all nested static fields are | 2314 /// If the target is a library or class all nested static fields are |
| 2603 /// included too. | 2315 /// included too. |
| 2604 Iterable<Element> _findStaticFieldTargets() { | 2316 Iterable<Element> _findStaticFieldTargets() { |
| 2605 List staticFields = []; | 2317 List staticFields = []; |
| 2606 | 2318 |
| 2607 void addFieldsInContainer(ScopeContainerElement container) { | 2319 void addFieldsInContainer(ScopeContainerElement container) { |
| 2608 container.forEachLocalMember((Element member) { | 2320 container.forEachLocalMember((Element member) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2635 noSuchMethodRegistry.onQueueEmpty(); | 2347 noSuchMethodRegistry.onQueueEmpty(); |
| 2636 if (!enabledNoSuchMethod && | 2348 if (!enabledNoSuchMethod && |
| 2637 (noSuchMethodRegistry.hasThrowingNoSuchMethod || | 2349 (noSuchMethodRegistry.hasThrowingNoSuchMethod || |
| 2638 noSuchMethodRegistry.hasComplexNoSuchMethod)) { | 2350 noSuchMethodRegistry.hasComplexNoSuchMethod)) { |
| 2639 enableNoSuchMethod(enqueuer); | 2351 enableNoSuchMethod(enqueuer); |
| 2640 enabledNoSuchMethod = true; | 2352 enabledNoSuchMethod = true; |
| 2641 } | 2353 } |
| 2642 | 2354 |
| 2643 if (compiler.hasIncrementalSupport) { | 2355 if (compiler.hasIncrementalSupport) { |
| 2644 // Always enable tear-off closures during incremental compilation. | 2356 // Always enable tear-off closures during incremental compilation. |
| 2645 Element e = findHelper('closureFromTearOff'); | 2357 Element e = helpers.closureFromTearOff; |
| 2646 if (e != null && !enqueuer.isProcessed(e)) { | 2358 if (e != null && !enqueuer.isProcessed(e)) { |
| 2647 registerBackendUse(e); | 2359 registerBackendUse(e); |
| 2648 enqueuer.addToWorkList(e); | 2360 enqueuer.addToWorkList(e); |
| 2649 } | 2361 } |
| 2650 } | 2362 } |
| 2651 | 2363 |
| 2652 if (!enqueuer.isResolutionQueue && preMirrorsMethodCount == 0) { | 2364 if (!enqueuer.isResolutionQueue && preMirrorsMethodCount == 0) { |
| 2653 preMirrorsMethodCount = generatedCode.length; | 2365 preMirrorsMethodCount = generatedCode.length; |
| 2654 } | 2366 } |
| 2655 | 2367 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2709 bool hasForceInline = false; | 2421 bool hasForceInline = false; |
| 2710 bool hasNoThrows = false; | 2422 bool hasNoThrows = false; |
| 2711 bool hasNoSideEffects = false; | 2423 bool hasNoSideEffects = false; |
| 2712 for (MetadataAnnotation metadata in element.implementation.metadata) { | 2424 for (MetadataAnnotation metadata in element.implementation.metadata) { |
| 2713 metadata.ensureResolved(resolution); | 2425 metadata.ensureResolved(resolution); |
| 2714 ConstantValue constantValue = | 2426 ConstantValue constantValue = |
| 2715 compiler.constants.getConstantValue(metadata.constant); | 2427 compiler.constants.getConstantValue(metadata.constant); |
| 2716 if (!constantValue.isConstructedObject) continue; | 2428 if (!constantValue.isConstructedObject) continue; |
| 2717 ObjectConstantValue value = constantValue; | 2429 ObjectConstantValue value = constantValue; |
| 2718 ClassElement cls = value.type.element; | 2430 ClassElement cls = value.type.element; |
| 2719 if (cls == forceInlineClass) { | 2431 if (cls == helpers.forceInlineClass) { |
| 2720 hasForceInline = true; | 2432 hasForceInline = true; |
| 2721 if (VERBOSE_OPTIMIZER_HINTS) { | 2433 if (VERBOSE_OPTIMIZER_HINTS) { |
| 2722 reporter.reportHintMessage( | 2434 reporter.reportHintMessage( |
| 2723 element, | 2435 element, |
| 2724 MessageKind.GENERIC, | 2436 MessageKind.GENERIC, |
| 2725 {'text': "Must inline"}); | 2437 {'text': "Must inline"}); |
| 2726 } | 2438 } |
| 2727 inlineCache.markAsMustInline(element); | 2439 inlineCache.markAsMustInline(element); |
| 2728 } else if (cls == noInlineClass) { | 2440 } else if (cls == helpers.noInlineClass) { |
| 2729 hasNoInline = true; | 2441 hasNoInline = true; |
| 2730 if (VERBOSE_OPTIMIZER_HINTS) { | 2442 if (VERBOSE_OPTIMIZER_HINTS) { |
| 2731 reporter.reportHintMessage( | 2443 reporter.reportHintMessage( |
| 2732 element, | 2444 element, |
| 2733 MessageKind.GENERIC, | 2445 MessageKind.GENERIC, |
| 2734 {'text': "Cannot inline"}); | 2446 {'text': "Cannot inline"}); |
| 2735 } | 2447 } |
| 2736 inlineCache.markAsNonInlinable(element); | 2448 inlineCache.markAsNonInlinable(element); |
| 2737 } else if (cls == noThrowsClass) { | 2449 } else if (cls == helpers.noThrowsClass) { |
| 2738 hasNoThrows = true; | 2450 hasNoThrows = true; |
| 2739 if (!Elements.isStaticOrTopLevelFunction(element) && | 2451 if (!Elements.isStaticOrTopLevelFunction(element) && |
| 2740 !element.isFactoryConstructor) { | 2452 !element.isFactoryConstructor) { |
| 2741 reporter.internalError(element, | 2453 reporter.internalError(element, |
| 2742 "@NoThrows() is currently limited to top-level" | 2454 "@NoThrows() is currently limited to top-level" |
| 2743 " or static functions and factory constructors."); | 2455 " or static functions and factory constructors."); |
| 2744 } | 2456 } |
| 2745 if (VERBOSE_OPTIMIZER_HINTS) { | 2457 if (VERBOSE_OPTIMIZER_HINTS) { |
| 2746 reporter.reportHintMessage( | 2458 reporter.reportHintMessage( |
| 2747 element, | 2459 element, |
| 2748 MessageKind.GENERIC, | 2460 MessageKind.GENERIC, |
| 2749 {'text': "Cannot throw"}); | 2461 {'text': "Cannot throw"}); |
| 2750 } | 2462 } |
| 2751 compiler.world.registerCannotThrow(element); | 2463 compiler.world.registerCannotThrow(element); |
| 2752 } else if (cls == noSideEffectsClass) { | 2464 } else if (cls == helpers.noSideEffectsClass) { |
| 2753 hasNoSideEffects = true; | 2465 hasNoSideEffects = true; |
| 2754 if (VERBOSE_OPTIMIZER_HINTS) { | 2466 if (VERBOSE_OPTIMIZER_HINTS) { |
| 2755 reporter.reportHintMessage( | 2467 reporter.reportHintMessage( |
| 2756 element, | 2468 element, |
| 2757 MessageKind.GENERIC, | 2469 MessageKind.GENERIC, |
| 2758 {'text': "Has no side effects"}); | 2470 {'text': "Has no side effects"}); |
| 2759 } | 2471 } |
| 2760 compiler.world.registerSideEffectsFree(element); | 2472 compiler.world.registerSideEffectsFree(element); |
| 2761 } | 2473 } |
| 2762 } | 2474 } |
| 2763 if (hasForceInline && hasNoInline) { | 2475 if (hasForceInline && hasNoInline) { |
| 2764 reporter.internalError(element, | 2476 reporter.internalError(element, |
| 2765 "@ForceInline() must not be used with @NoInline."); | 2477 "@ForceInline() must not be used with @NoInline."); |
| 2766 } | 2478 } |
| 2767 if (hasNoThrows && !hasNoInline) { | 2479 if (hasNoThrows && !hasNoInline) { |
| 2768 reporter.internalError(element, | 2480 reporter.internalError(element, |
| 2769 "@NoThrows() should always be combined with @NoInline."); | 2481 "@NoThrows() should always be combined with @NoInline."); |
| 2770 } | 2482 } |
| 2771 if (hasNoSideEffects && !hasNoInline) { | 2483 if (hasNoSideEffects && !hasNoInline) { |
| 2772 reporter.internalError(element, | 2484 reporter.internalError(element, |
| 2773 "@NoSideEffects() should always be combined with @NoInline."); | 2485 "@NoSideEffects() should always be combined with @NoInline."); |
| 2774 } | 2486 } |
| 2775 if (element == invokeOnMethod) { | 2487 if (element == helpers.invokeOnMethod) { |
| 2776 compiler.enabledInvokeOn = true; | 2488 compiler.enabledInvokeOn = true; |
| 2777 } | 2489 } |
| 2778 } | 2490 } |
| 2779 | 2491 |
| 2780 CodeBuffer codeOf(Element element) { | 2492 CodeBuffer codeOf(Element element) { |
| 2781 return generatedCode.containsKey(element) | 2493 return generatedCode.containsKey(element) |
| 2782 ? jsAst.prettyPrint(generatedCode[element], compiler) | 2494 ? jsAst.prettyPrint(generatedCode[element], compiler) |
| 2783 : null; | 2495 : null; |
| 2784 } | 2496 } |
| 2785 | 2497 |
| 2786 FunctionElement helperForBadMain() => findHelper('badMain'); | 2498 FunctionElement helperForBadMain() => helpers.badMain; |
| 2787 | 2499 |
| 2788 FunctionElement helperForMissingMain() => findHelper('missingMain'); | 2500 FunctionElement helperForMissingMain() => helpers.missingMain; |
| 2789 | 2501 |
| 2790 FunctionElement helperForMainArity() { | 2502 FunctionElement helperForMainArity() => helpers.mainHasTooManyParameters; |
| 2791 return findHelper('mainHasTooManyParameters'); | |
| 2792 } | |
| 2793 | 2503 |
| 2794 void forgetElement(Element element) { | 2504 void forgetElement(Element element) { |
| 2795 constants.forgetElement(element); | 2505 constants.forgetElement(element); |
| 2796 constantCompilerTask.dartConstantCompiler.forgetElement(element); | 2506 constantCompilerTask.dartConstantCompiler.forgetElement(element); |
| 2797 aliasedSuperMembers.remove(element); | 2507 aliasedSuperMembers.remove(element); |
| 2798 } | 2508 } |
| 2799 | 2509 |
| 2800 void registerMainHasArguments(Enqueuer enqueuer) { | 2510 void registerMainHasArguments(Enqueuer enqueuer) { |
| 2801 // If the main method takes arguments, this compilation could be the target | 2511 // If the main method takes arguments, this compilation could be the target |
| 2802 // of Isolate.spawnUri. Strictly speaking, that can happen also if main | 2512 // of Isolate.spawnUri. Strictly speaking, that can happen also if main |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2957 } | 2667 } |
| 2958 } | 2668 } |
| 2959 } | 2669 } |
| 2960 | 2670 |
| 2961 /// Returns `true` if inlining is disabled for [element]. | 2671 /// Returns `true` if inlining is disabled for [element]. |
| 2962 bool noInline(Element element) { | 2672 bool noInline(Element element) { |
| 2963 if (_hasAnnotation(element, expectNoInlineClass)) { | 2673 if (_hasAnnotation(element, expectNoInlineClass)) { |
| 2964 // TODO(floitsch): restrict to elements from the test directory. | 2674 // TODO(floitsch): restrict to elements from the test directory. |
| 2965 return true; | 2675 return true; |
| 2966 } | 2676 } |
| 2967 return _hasAnnotation(element, backend.noInlineClass); | 2677 return _hasAnnotation(element, backend.helpers.noInlineClass); |
| 2968 } | 2678 } |
| 2969 | 2679 |
| 2970 /// Returns `true` if parameter and returns types should be trusted for | 2680 /// Returns `true` if parameter and returns types should be trusted for |
| 2971 /// [element]. | 2681 /// [element]. |
| 2972 bool trustTypeAnnotations(Element element) { | 2682 bool trustTypeAnnotations(Element element) { |
| 2973 return _hasAnnotation(element, expectTrustTypeAnnotationsClass); | 2683 return _hasAnnotation(element, expectTrustTypeAnnotationsClass); |
| 2974 } | 2684 } |
| 2975 | 2685 |
| 2976 /// Returns `true` if inference of parameter types is disabled for [element]. | 2686 /// Returns `true` if inference of parameter types is disabled for [element]. |
| 2977 bool assumeDynamic(Element element) { | 2687 bool assumeDynamic(Element element) { |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3232 } | 2942 } |
| 3233 | 2943 |
| 3234 /// Records that [constant] is used by the element behind [registry]. | 2944 /// Records that [constant] is used by the element behind [registry]. |
| 3235 class Dependency { | 2945 class Dependency { |
| 3236 final ConstantValue constant; | 2946 final ConstantValue constant; |
| 3237 final Element annotatedElement; | 2947 final Element annotatedElement; |
| 3238 | 2948 |
| 3239 const Dependency(this.constant, this.annotatedElement); | 2949 const Dependency(this.constant, this.annotatedElement); |
| 3240 } | 2950 } |
| 3241 | 2951 |
| OLD | NEW |