| 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 library js_backend.backend; | 5 library js_backend.backend; |
| 6 | 6 |
| 7 import 'dart:async' show Future; | 7 import 'dart:async' show Future; |
| 8 | 8 |
| 9 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames; | 9 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames; |
| 10 | 10 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 WorldImpact, | 61 WorldImpact, |
| 62 WorldImpactBuilder, | 62 WorldImpactBuilder, |
| 63 WorldImpactBuilderImpl, | 63 WorldImpactBuilderImpl, |
| 64 WorldImpactVisitor, | 64 WorldImpactVisitor, |
| 65 StagedWorldImpactBuilder; | 65 StagedWorldImpactBuilder; |
| 66 import '../util/util.dart'; | 66 import '../util/util.dart'; |
| 67 import '../world.dart' show ClosedWorld, ClosedWorldRefiner; | 67 import '../world.dart' show ClosedWorld, ClosedWorldRefiner; |
| 68 import 'backend_helpers.dart'; | 68 import 'backend_helpers.dart'; |
| 69 import 'backend_impact.dart'; | 69 import 'backend_impact.dart'; |
| 70 import 'backend_serialization.dart' show JavaScriptBackendSerialization; | 70 import 'backend_serialization.dart' show JavaScriptBackendSerialization; |
| 71 import 'backend_usage.dart'; |
| 71 import 'checked_mode_helpers.dart'; | 72 import 'checked_mode_helpers.dart'; |
| 72 import 'constant_handler_javascript.dart'; | 73 import 'constant_handler_javascript.dart'; |
| 73 import 'custom_elements_analysis.dart'; | 74 import 'custom_elements_analysis.dart'; |
| 74 import 'enqueuer.dart'; | 75 import 'enqueuer.dart'; |
| 75 import 'interceptor_data.dart' show InterceptorData; | 76 import 'interceptor_data.dart' show InterceptorData; |
| 76 import 'js_interop_analysis.dart' show JsInteropAnalysis; | 77 import 'js_interop_analysis.dart' show JsInteropAnalysis; |
| 77 import 'lookup_map_analysis.dart' show LookupMapAnalysis; | 78 import 'lookup_map_analysis.dart' show LookupMapAnalysis; |
| 78 import 'mirrors_analysis.dart'; | 79 import 'mirrors_analysis.dart'; |
| 80 import 'mirrors_data.dart'; |
| 79 import 'namer.dart'; | 81 import 'namer.dart'; |
| 80 import 'native_data.dart' show NativeData; | 82 import 'native_data.dart' show NativeData; |
| 81 import 'no_such_method_registry.dart'; | 83 import 'no_such_method_registry.dart'; |
| 82 import 'patch_resolver.dart'; | 84 import 'patch_resolver.dart'; |
| 83 import 'type_variable_handler.dart'; | 85 import 'type_variable_handler.dart'; |
| 84 | 86 |
| 85 part 'runtime_types.dart'; | 87 part 'runtime_types.dart'; |
| 86 | 88 |
| 87 const VERBOSE_OPTIMIZER_HINTS = false; | 89 const VERBOSE_OPTIMIZER_HINTS = false; |
| 88 | 90 |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 /// called. When TRACE_METHOD is 'console' this will be logged | 337 /// called. When TRACE_METHOD is 'console' this will be logged |
| 336 /// directly in the JavaScript console. When TRACE_METHOD is 'post' the | 338 /// directly in the JavaScript console. When TRACE_METHOD is 'post' the |
| 337 /// information will be sent to a server via a POST request. | 339 /// information will be sent to a server via a POST request. |
| 338 static const String TRACE_METHOD = const String.fromEnvironment('traceCalls'); | 340 static const String TRACE_METHOD = const String.fromEnvironment('traceCalls'); |
| 339 static const bool TRACE_CALLS = | 341 static const bool TRACE_CALLS = |
| 340 TRACE_METHOD == 'post' || TRACE_METHOD == 'console'; | 342 TRACE_METHOD == 'post' || TRACE_METHOD == 'console'; |
| 341 | 343 |
| 342 /// Maps special classes to their implementation (JSXxx) class. | 344 /// Maps special classes to their implementation (JSXxx) class. |
| 343 Map<ClassElement, ClassElement> implementationClasses; | 345 Map<ClassElement, ClassElement> implementationClasses; |
| 344 | 346 |
| 345 bool needToInitializeIsolateAffinityTag = false; | |
| 346 bool needToInitializeDispatchProperty = false; | |
| 347 | |
| 348 Namer _namer; | 347 Namer _namer; |
| 349 | 348 |
| 350 Namer get namer { | 349 Namer get namer { |
| 351 assert(invariant(NO_LOCATION_SPANNABLE, _namer != null, | 350 assert(invariant(NO_LOCATION_SPANNABLE, _namer != null, |
| 352 message: "Namer has not been created yet.")); | 351 message: "Namer has not been created yet.")); |
| 353 return _namer; | 352 return _namer; |
| 354 } | 353 } |
| 355 | 354 |
| 356 /** | 355 /** |
| 357 * Set of classes whose `operator ==` methods handle `null` themselves. | 356 * Set of classes whose `operator ==` methods handle `null` themselves. |
| 358 */ | 357 */ |
| 359 final Set<ClassElement> specialOperatorEqClasses = new Set<ClassElement>(); | 358 final Set<ClassElement> specialOperatorEqClasses = new Set<ClassElement>(); |
| 360 | 359 |
| 361 /** | 360 /** |
| 362 * A set of members that are called from subclasses via `super`. | 361 * A set of members that are called from subclasses via `super`. |
| 363 */ | 362 */ |
| 364 final Set<MethodElement> aliasedSuperMembers = new Setlet<MethodElement>(); | 363 final Set<MethodElement> aliasedSuperMembers = new Setlet<MethodElement>(); |
| 365 | 364 |
| 366 List<CompilerTask> get tasks { | 365 List<CompilerTask> get tasks { |
| 367 List<CompilerTask> result = functionCompiler.tasks; | 366 List<CompilerTask> result = functionCompiler.tasks; |
| 368 result.add(emitter); | 367 result.add(emitter); |
| 369 result.add(patchResolverTask); | 368 result.add(patchResolverTask); |
| 370 result.add(kernelTask); | 369 result.add(kernelTask); |
| 371 return result; | 370 return result; |
| 372 } | 371 } |
| 373 | 372 |
| 374 final RuntimeTypes rti; | 373 final RuntimeTypes rti; |
| 375 final RuntimeTypesEncoder rtiEncoder; | 374 final RuntimeTypesEncoder rtiEncoder; |
| 376 | 375 |
| 377 /// True if a call to preserveMetadataMarker has been seen. This means that | |
| 378 /// metadata must be retained for dart:mirrors to work correctly. | |
| 379 bool mustRetainMetadata = false; | |
| 380 | |
| 381 /// True if any metadata has been retained. This is slightly different from | |
| 382 /// [mustRetainMetadata] and tells us if any metadata was retained. For | |
| 383 /// example, if [mustRetainMetadata] is true but there is no metadata in the | |
| 384 /// program, this variable will stil be false. | |
| 385 bool hasRetainedMetadata = false; | |
| 386 | |
| 387 /// True if a call to preserveUris has been seen and the preserve-uris flag | 376 /// True if a call to preserveUris has been seen and the preserve-uris flag |
| 388 /// is set. | 377 /// is set. |
| 389 bool mustPreserveUris = false; | 378 bool mustPreserveUris = false; |
| 390 | 379 |
| 391 /// True if a call to preserveLibraryNames has been seen. | |
| 392 bool mustRetainLibraryNames = false; | |
| 393 | |
| 394 /// True if a call to preserveNames has been seen. | |
| 395 bool mustPreserveNames = false; | |
| 396 | |
| 397 /// True if a call to disableTreeShaking has been seen. | |
| 398 bool isTreeShakingDisabled = false; | |
| 399 | |
| 400 /// True if there isn't sufficient @MirrorsUsed data. | |
| 401 bool hasInsufficientMirrorsUsed = false; | |
| 402 | |
| 403 /// True if a core-library function requires the preamble file to function. | 380 /// True if a core-library function requires the preamble file to function. |
| 404 bool requiresPreamble = false; | 381 bool requiresPreamble = false; |
| 405 | 382 |
| 406 /// True if the html library has been loaded. | 383 /// True if the html library has been loaded. |
| 407 bool htmlLibraryIsLoaded = false; | 384 bool htmlLibraryIsLoaded = false; |
| 408 | 385 |
| 409 /// True when we enqueue the loadLibrary code. | 386 /// True when we enqueue the loadLibrary code. |
| 410 bool isLoadLibraryFunctionResolved = false; | 387 bool isLoadLibraryFunctionResolved = false; |
| 411 | 388 |
| 412 /// `true` if access to [BackendHelpers.invokeOnMethod] is supported. | 389 /// `true` if access to [BackendHelpers.invokeOnMethod] is supported. |
| 413 bool hasInvokeOnSupport = false; | 390 bool hasInvokeOnSupport = false; |
| 414 | 391 |
| 415 /// `true` of `Object.runtimeType` is supported. | 392 /// `true` of `Object.runtimeType` is supported. |
| 416 bool hasRuntimeTypeSupport = false; | 393 bool hasRuntimeTypeSupport = false; |
| 417 | 394 |
| 418 /// `true` of use of the `dart:isolate` library is supported. | 395 /// `true` of use of the `dart:isolate` library is supported. |
| 419 bool hasIsolateSupport = false; | 396 bool hasIsolateSupport = false; |
| 420 | 397 |
| 421 /// `true` of `Function.apply` is supported. | 398 /// `true` of `Function.apply` is supported. |
| 422 bool hasFunctionApplySupport = false; | 399 bool hasFunctionApplySupport = false; |
| 423 | 400 |
| 424 /// List of constants from metadata. If metadata must be preserved, | 401 /// List of constants from metadata. If metadata must be preserved, |
| 425 /// these constants must be registered. | 402 /// these constants must be registered. |
| 426 final List<Dependency> metadataConstants = <Dependency>[]; | 403 final List<Dependency> metadataConstants = <Dependency>[]; |
| 427 | 404 |
| 428 /// Set of elements for which metadata has been registered as dependencies. | 405 /// Set of elements for which metadata has been registered as dependencies. |
| 429 final Set<Element> _registeredMetadata = new Set<Element>(); | 406 final Set<Element> _registeredMetadata = new Set<Element>(); |
| 430 | 407 |
| 431 /// List of elements that the user has requested for reflection. | |
| 432 final Set<Element> targetsUsed = new Set<Element>(); | |
| 433 | |
| 434 /// List of annotations provided by user that indicate that the annotated | |
| 435 /// element must be retained. | |
| 436 final Set<Element> metaTargetsUsed = new Set<Element>(); | |
| 437 | |
| 438 /// Set of methods that are needed by reflection. Computed using | |
| 439 /// [computeMembersNeededForReflection] on first use. | |
| 440 Set<Element> _membersNeededForReflection = null; | |
| 441 Iterable<Element> get membersNeededForReflection { | |
| 442 assert(_membersNeededForReflection != null); | |
| 443 return _membersNeededForReflection; | |
| 444 } | |
| 445 | |
| 446 /// List of symbols that the user has requested for reflection. | |
| 447 final Set<String> symbolsUsed = new Set<String>(); | |
| 448 | |
| 449 /// List of elements that the backend may use. | |
| 450 final Set<Element> helpersUsed = new Set<Element>(); | |
| 451 | |
| 452 /// All the checked mode helpers. | |
| 453 static const checkedModeHelpers = CheckedModeHelper.helpers; | |
| 454 | |
| 455 // Checked mode helpers indexed by name. | |
| 456 Map<String, CheckedModeHelper> checkedModeHelperByName = | |
| 457 new Map<String, CheckedModeHelper>.fromIterable(checkedModeHelpers, | |
| 458 key: (helper) => helper.name); | |
| 459 | |
| 460 TypeVariableHandler typeVariableHandler; | 408 TypeVariableHandler typeVariableHandler; |
| 461 | 409 |
| 462 /// Number of methods compiled before considering reflection. | 410 /// Number of methods compiled before considering reflection. |
| 463 int preMirrorsMethodCount = 0; | 411 int preMirrorsMethodCount = 0; |
| 464 | 412 |
| 465 /// Resolution and codegen support for generating table of interceptors and | 413 /// Resolution and codegen support for generating table of interceptors and |
| 466 /// constructors for custom elements. | 414 /// constructors for custom elements. |
| 467 CustomElementsAnalysis customElementsAnalysis; | 415 CustomElementsAnalysis customElementsAnalysis; |
| 468 | 416 |
| 469 /// Codegen support for tree-shaking entries of `LookupMap`. | 417 /// Codegen support for tree-shaking entries of `LookupMap`. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 501 JavaScriptBackendSerialization serialization; | 449 JavaScriptBackendSerialization serialization; |
| 502 | 450 |
| 503 StagedWorldImpactBuilder constantImpactsForResolution = | 451 StagedWorldImpactBuilder constantImpactsForResolution = |
| 504 new StagedWorldImpactBuilder(); | 452 new StagedWorldImpactBuilder(); |
| 505 | 453 |
| 506 StagedWorldImpactBuilder constantImpactsForCodegen = | 454 StagedWorldImpactBuilder constantImpactsForCodegen = |
| 507 new StagedWorldImpactBuilder(); | 455 new StagedWorldImpactBuilder(); |
| 508 | 456 |
| 509 final NativeData nativeData = new NativeData(); | 457 final NativeData nativeData = new NativeData(); |
| 510 InterceptorData _interceptorData; | 458 InterceptorData _interceptorData; |
| 459 BackendUsage _backendUsage; |
| 460 final MirrorsData mirrorsData; |
| 461 CheckedModeHelpers _checkedModeHelpers; |
| 511 | 462 |
| 512 BackendHelpers helpers; | 463 BackendHelpers helpers; |
| 513 final BackendImpacts impacts; | 464 final BackendImpacts impacts; |
| 514 | 465 |
| 515 /// Common classes used by the backend. | 466 /// Common classes used by the backend. |
| 516 BackendClasses backendClasses; | 467 BackendClasses backendClasses; |
| 517 | 468 |
| 518 /// Backend access to the front-end. | 469 /// Backend access to the front-end. |
| 519 final JSFrontendAccess frontend; | 470 final JSFrontendAccess frontend; |
| 520 | 471 |
| 521 Tracer tracer; | 472 Tracer tracer; |
| 522 | 473 |
| 523 JavaScriptBackend(Compiler compiler, | 474 JavaScriptBackend(Compiler compiler, |
| 524 {bool generateSourceMap: true, | 475 {bool generateSourceMap: true, |
| 525 bool useStartupEmitter: false, | 476 bool useStartupEmitter: false, |
| 526 bool useNewSourceInfo: false, | 477 bool useNewSourceInfo: false, |
| 527 bool useKernel: false}) | 478 bool useKernel: false}) |
| 528 : rti = new _RuntimeTypes(compiler), | 479 : rti = new _RuntimeTypes(compiler), |
| 529 rtiEncoder = new _RuntimeTypesEncoder(compiler), | 480 rtiEncoder = new _RuntimeTypesEncoder(compiler), |
| 530 annotations = new Annotations(compiler), | 481 annotations = new Annotations(compiler), |
| 531 this.sourceInformationStrategy = generateSourceMap | 482 this.sourceInformationStrategy = generateSourceMap |
| 532 ? (useNewSourceInfo | 483 ? (useNewSourceInfo |
| 533 ? new PositionSourceInformationStrategy() | 484 ? new PositionSourceInformationStrategy() |
| 534 : const StartEndSourceInformationStrategy()) | 485 : const StartEndSourceInformationStrategy()) |
| 535 : const JavaScriptSourceInformationStrategy(), | 486 : const JavaScriptSourceInformationStrategy(), |
| 536 impacts = new BackendImpacts(compiler), | 487 impacts = new BackendImpacts(compiler), |
| 537 frontend = new JSFrontendAccess(compiler), | 488 frontend = new JSFrontendAccess(compiler), |
| 489 mirrorsData = new MirrorsData(compiler), |
| 538 this.compiler = compiler { | 490 this.compiler = compiler { |
| 539 helpers = new BackendHelpers(compiler.elementEnvironment, commonElements); | 491 helpers = new BackendHelpers(compiler.elementEnvironment, commonElements); |
| 492 _backendUsage = new BackendUsage(commonElements, helpers); |
| 493 _checkedModeHelpers = new CheckedModeHelpers(commonElements, helpers); |
| 540 emitter = | 494 emitter = |
| 541 new CodeEmitterTask(compiler, generateSourceMap, useStartupEmitter); | 495 new CodeEmitterTask(compiler, generateSourceMap, useStartupEmitter); |
| 542 typeVariableHandler = new TypeVariableHandler(compiler); | 496 typeVariableHandler = new TypeVariableHandler(compiler); |
| 543 customElementsAnalysis = new CustomElementsAnalysis(this); | 497 customElementsAnalysis = new CustomElementsAnalysis(this); |
| 544 lookupMapAnalysis = new LookupMapAnalysis(this, reporter); | 498 lookupMapAnalysis = new LookupMapAnalysis(this, reporter); |
| 545 jsInteropAnalysis = new JsInteropAnalysis(this); | 499 jsInteropAnalysis = new JsInteropAnalysis(this); |
| 546 mirrorsAnalysis = new MirrorsAnalysis(this, compiler.resolution); | 500 mirrorsAnalysis = new MirrorsAnalysis(this, compiler.resolution); |
| 547 | 501 |
| 548 noSuchMethodRegistry = new NoSuchMethodRegistry(this); | 502 noSuchMethodRegistry = new NoSuchMethodRegistry(this); |
| 549 kernelTask = new KernelTask(compiler); | 503 kernelTask = new KernelTask(compiler); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 563 ConstantSystem get constantSystem => constants.constantSystem; | 517 ConstantSystem get constantSystem => constants.constantSystem; |
| 564 | 518 |
| 565 DiagnosticReporter get reporter => compiler.reporter; | 519 DiagnosticReporter get reporter => compiler.reporter; |
| 566 | 520 |
| 567 CommonElements get commonElements => compiler.commonElements; | 521 CommonElements get commonElements => compiler.commonElements; |
| 568 | 522 |
| 569 Resolution get resolution => compiler.resolution; | 523 Resolution get resolution => compiler.resolution; |
| 570 | 524 |
| 571 InterceptorData get interceptorData => _interceptorData; | 525 InterceptorData get interceptorData => _interceptorData; |
| 572 | 526 |
| 527 BackendUsage get backendUsage => _backendUsage; |
| 528 |
| 529 CheckedModeHelpers get checkedModeHelpers => _checkedModeHelpers; |
| 530 |
| 573 /// Returns constant environment for the JavaScript interpretation of the | 531 /// Returns constant environment for the JavaScript interpretation of the |
| 574 /// constants. | 532 /// constants. |
| 575 JavaScriptConstantCompiler get constants { | 533 JavaScriptConstantCompiler get constants { |
| 576 return constantCompilerTask.jsConstantCompiler; | 534 return constantCompilerTask.jsConstantCompiler; |
| 577 } | 535 } |
| 578 | 536 |
| 579 @override | 537 @override |
| 580 bool isDefaultNoSuchMethod(MethodElement element) { | 538 bool isDefaultNoSuchMethod(MethodElement element) { |
| 581 return noSuchMethodRegistry.isDefaultNoSuchMethodImplementation(element); | 539 return noSuchMethodRegistry.isDefaultNoSuchMethodImplementation(element); |
| 582 } | 540 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 607 | 565 |
| 608 Namer determineNamer( | 566 Namer determineNamer( |
| 609 ClosedWorld closedWorld, CodegenWorldBuilder codegenWorldBuilder) { | 567 ClosedWorld closedWorld, CodegenWorldBuilder codegenWorldBuilder) { |
| 610 return compiler.options.enableMinification | 568 return compiler.options.enableMinification |
| 611 ? compiler.options.useFrequencyNamer | 569 ? compiler.options.useFrequencyNamer |
| 612 ? new FrequencyBasedNamer(this, closedWorld, codegenWorldBuilder) | 570 ? new FrequencyBasedNamer(this, closedWorld, codegenWorldBuilder) |
| 613 : new MinifyNamer(this, closedWorld, codegenWorldBuilder) | 571 : new MinifyNamer(this, closedWorld, codegenWorldBuilder) |
| 614 : new Namer(this, closedWorld, codegenWorldBuilder); | 572 : new Namer(this, closedWorld, codegenWorldBuilder); |
| 615 } | 573 } |
| 616 | 574 |
| 617 /// The backend must *always* call this method when enqueuing an | |
| 618 /// element. Calls done by the backend are not seen by global | |
| 619 /// optimizations, so they would make these optimizations unsound. | |
| 620 /// Therefore we need to collect the list of helpers the backend may | |
| 621 /// use. | |
| 622 // TODO(johnniwinther): Replace this with a more precise modelling; type | |
| 623 // inference of these elements is disabled. | |
| 624 Element registerBackendUse(Element element) { | |
| 625 if (element == null) return null; | |
| 626 assert(invariant(element, _isValidBackendUse(element), | |
| 627 message: "Backend use of $element is not allowed.")); | |
| 628 helpersUsed.add(element.declaration); | |
| 629 if (element.isClass && element.isPatched) { | |
| 630 // Both declaration and implementation may declare fields, so we | |
| 631 // add both to the list of helpers. | |
| 632 helpersUsed.add(element.implementation); | |
| 633 } | |
| 634 return element; | |
| 635 } | |
| 636 | |
| 637 bool _isValidBackendUse(Element element) { | |
| 638 assert(invariant(element, element.isDeclaration, message: "")); | |
| 639 if (element is ConstructorElement && | |
| 640 (element == helpers.streamIteratorConstructor || | |
| 641 compiler.commonElements.isSymbolConstructor(element) || | |
| 642 helpers.isSymbolValidatedConstructor(element) || | |
| 643 element == helpers.syncCompleterConstructor)) { | |
| 644 // TODO(johnniwinther): These are valid but we could be more precise. | |
| 645 return true; | |
| 646 } else if (element == commonElements.symbolClass || | |
| 647 element == helpers.objectNoSuchMethod) { | |
| 648 // TODO(johnniwinther): These are valid but we could be more precise. | |
| 649 return true; | |
| 650 } else if (element.implementationLibrary.isPatch || | |
| 651 // Needed to detect deserialized injected elements, that is | |
| 652 // element declared in patch files. | |
| 653 (element.library.isPlatformLibrary && | |
| 654 element.sourcePosition.uri.path | |
| 655 .contains('_internal/js_runtime/lib/')) || | |
| 656 element.library == helpers.jsHelperLibrary || | |
| 657 element.library == helpers.interceptorsLibrary || | |
| 658 element.library == helpers.isolateHelperLibrary) { | |
| 659 // TODO(johnniwinther): We should be more precise about these. | |
| 660 return true; | |
| 661 } else if (element == commonElements.listClass || | |
| 662 element == helpers.mapLiteralClass || | |
| 663 element == commonElements.functionClass || | |
| 664 element == commonElements.stringClass) { | |
| 665 // TODO(johnniwinther): Avoid these. | |
| 666 return true; | |
| 667 } else if (element == helpers.genericNoSuchMethod || | |
| 668 element == helpers.unresolvedConstructorError || | |
| 669 element == helpers.malformedTypeError) { | |
| 670 return true; | |
| 671 } | |
| 672 return false; | |
| 673 } | |
| 674 | |
| 675 bool usedByBackend(Element element) { | |
| 676 if (element.isRegularParameter || | |
| 677 element.isInitializingFormal || | |
| 678 element.isField) { | |
| 679 if (usedByBackend(element.enclosingElement)) return true; | |
| 680 } | |
| 681 return helpersUsed.contains(element.declaration); | |
| 682 } | |
| 683 | |
| 684 bool invokedReflectively(Element element) { | |
| 685 if (element.isRegularParameter || element.isInitializingFormal) { | |
| 686 ParameterElement parameter = element; | |
| 687 if (invokedReflectively(parameter.functionDeclaration)) return true; | |
| 688 } | |
| 689 | |
| 690 if (element.isField) { | |
| 691 if (Elements.isStaticOrTopLevel(element) && | |
| 692 (element.isFinal || element.isConst)) { | |
| 693 return false; | |
| 694 } | |
| 695 } | |
| 696 | |
| 697 return isAccessibleByReflection(element.declaration); | |
| 698 } | |
| 699 | |
| 700 /// Returns true if global optimizations such as type inferencing | 575 /// Returns true if global optimizations such as type inferencing |
| 701 /// can apply to this element. One category of elements that do not | 576 /// can apply to this element. One category of elements that do not |
| 702 /// apply is runtime helpers that the backend calls, but the | 577 /// apply is runtime helpers that the backend calls, but the |
| 703 /// optimizations don't see those calls. | 578 /// optimizations don't see those calls. |
| 704 bool canBeUsedForGlobalOptimizations(Element element) { | 579 bool canBeUsedForGlobalOptimizations(Element element) { |
| 705 return !usedByBackend(element) && !invokedReflectively(element); | 580 return !backendUsage.usedByBackend(element) && |
| 581 !mirrorsData.invokedReflectively(element); |
| 706 } | 582 } |
| 707 | 583 |
| 708 /** | 584 /** |
| 709 * Record that [method] is called from a subclass via `super`. | 585 * Record that [method] is called from a subclass via `super`. |
| 710 */ | 586 */ |
| 711 bool maybeRegisterAliasedSuperMember( | 587 bool maybeRegisterAliasedSuperMember( |
| 712 MemberElement member, Selector selector) { | 588 MemberElement member, Selector selector) { |
| 713 if (!canUseAliasedSuperMember(member, selector)) { | 589 if (!canUseAliasedSuperMember(member, selector)) { |
| 714 // Invoking a super getter isn't supported, this would require changes to | 590 // Invoking a super getter isn't supported, this would require changes to |
| 715 // compact field descriptors in the emitter. | 591 // compact field descriptors in the emitter. |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 881 InterceptorConstantValue interceptor = constant; | 757 InterceptorConstantValue interceptor = constant; |
| 882 ClassElement cls = interceptor.cls; | 758 ClassElement cls = interceptor.cls; |
| 883 computeImpactForInstantiatedConstantType(cls.thisType, impactBuilder); | 759 computeImpactForInstantiatedConstantType(cls.thisType, impactBuilder); |
| 884 } else if (constant.isType) { | 760 } else if (constant.isType) { |
| 885 if (isForResolution) { | 761 if (isForResolution) { |
| 886 MethodElement helper = helpers.createRuntimeType; | 762 MethodElement helper = helpers.createRuntimeType; |
| 887 impactBuilder.registerStaticUse(new StaticUse.staticInvoke( | 763 impactBuilder.registerStaticUse(new StaticUse.staticInvoke( |
| 888 // TODO(johnniwinther): Find the right [CallStructure]. | 764 // TODO(johnniwinther): Find the right [CallStructure]. |
| 889 helper, | 765 helper, |
| 890 null)); | 766 null)); |
| 891 registerBackendUse(helper); | 767 backendUsage.registerBackendUse(helper); |
| 892 } | 768 } |
| 893 impactBuilder | 769 impactBuilder |
| 894 .registerTypeUse(new TypeUse.instantiation(backendClasses.typeType)); | 770 .registerTypeUse(new TypeUse.instantiation(backendClasses.typeType)); |
| 895 } | 771 } |
| 896 lookupMapAnalysis.registerConstantKey(constant); | 772 lookupMapAnalysis.registerConstantKey(constant); |
| 897 } | 773 } |
| 898 | 774 |
| 899 void computeImpactForInstantiatedConstantType( | 775 void computeImpactForInstantiatedConstantType( |
| 900 DartType type, WorldImpactBuilder impactBuilder) { | 776 DartType type, WorldImpactBuilder impactBuilder) { |
| 901 if (type is ResolutionInterfaceType) { | 777 if (type is ResolutionInterfaceType) { |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1088 impactBuilder, impacts.assertUnreachable); | 964 impactBuilder, impacts.assertUnreachable); |
| 1089 _registerCheckedModeHelpers(impactBuilder); | 965 _registerCheckedModeHelpers(impactBuilder); |
| 1090 return impactBuilder; | 966 return impactBuilder; |
| 1091 } | 967 } |
| 1092 | 968 |
| 1093 void onResolutionComplete( | 969 void onResolutionComplete( |
| 1094 ClosedWorld closedWorld, ClosedWorldRefiner closedWorldRefiner) { | 970 ClosedWorld closedWorld, ClosedWorldRefiner closedWorldRefiner) { |
| 1095 for (Entity entity in compiler.enqueuer.resolution.processedEntities) { | 971 for (Entity entity in compiler.enqueuer.resolution.processedEntities) { |
| 1096 processAnnotations(entity, closedWorldRefiner); | 972 processAnnotations(entity, closedWorldRefiner); |
| 1097 } | 973 } |
| 1098 computeMembersNeededForReflection(closedWorld); | 974 mirrorsData.computeMembersNeededForReflection(closedWorld); |
| 1099 rti.computeClassesNeedingRti( | 975 rti.computeClassesNeedingRti( |
| 1100 compiler.enqueuer.resolution.worldBuilder, closedWorld); | 976 compiler.enqueuer.resolution.worldBuilder, closedWorld); |
| 1101 _registeredMetadata.clear(); | 977 _registeredMetadata.clear(); |
| 1102 interceptorData.onResolutionComplete(closedWorld); | 978 interceptorData.onResolutionComplete(closedWorld); |
| 1103 } | 979 } |
| 1104 | 980 |
| 1105 void onTypeInferenceComplete() { | 981 void onTypeInferenceComplete() { |
| 1106 noSuchMethodRegistry.onTypeInferenceComplete(); | 982 noSuchMethodRegistry.onTypeInferenceComplete(); |
| 1107 } | 983 } |
| 1108 | 984 |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1396 | 1272 |
| 1397 Element getDartClass(Element element) { | 1273 Element getDartClass(Element element) { |
| 1398 for (ClassElement dartClass in implementationClasses.keys) { | 1274 for (ClassElement dartClass in implementationClasses.keys) { |
| 1399 if (element == implementationClasses[dartClass]) { | 1275 if (element == implementationClasses[dartClass]) { |
| 1400 return dartClass; | 1276 return dartClass; |
| 1401 } | 1277 } |
| 1402 } | 1278 } |
| 1403 return element; | 1279 return element; |
| 1404 } | 1280 } |
| 1405 | 1281 |
| 1406 /** | |
| 1407 * Returns the checked mode helper that will be needed to do a type check/type | |
| 1408 * cast on [type] at runtime. Note that this method is being called both by | |
| 1409 * the resolver with interface types (int, String, ...), and by the SSA | |
| 1410 * backend with implementation types (JSInt, JSString, ...). | |
| 1411 */ | |
| 1412 CheckedModeHelper getCheckedModeHelper(ResolutionDartType type, | |
| 1413 {bool typeCast}) { | |
| 1414 return getCheckedModeHelperInternal(type, | |
| 1415 typeCast: typeCast, nativeCheckOnly: false); | |
| 1416 } | |
| 1417 | |
| 1418 /** | |
| 1419 * Returns the native checked mode helper that will be needed to do a type | |
| 1420 * check/type cast on [type] at runtime. If no native helper exists for | |
| 1421 * [type], [:null:] is returned. | |
| 1422 */ | |
| 1423 CheckedModeHelper getNativeCheckedModeHelper(ResolutionDartType type, | |
| 1424 {bool typeCast}) { | |
| 1425 return getCheckedModeHelperInternal(type, | |
| 1426 typeCast: typeCast, nativeCheckOnly: true); | |
| 1427 } | |
| 1428 | |
| 1429 /** | |
| 1430 * Returns the checked mode helper for the type check/type cast for [type]. If | |
| 1431 * [nativeCheckOnly] is [:true:], only names for native helpers are returned. | |
| 1432 */ | |
| 1433 CheckedModeHelper getCheckedModeHelperInternal(ResolutionDartType type, | |
| 1434 {bool typeCast, bool nativeCheckOnly}) { | |
| 1435 String name = getCheckedModeHelperNameInternal(type, | |
| 1436 typeCast: typeCast, nativeCheckOnly: nativeCheckOnly); | |
| 1437 if (name == null) return null; | |
| 1438 CheckedModeHelper helper = checkedModeHelperByName[name]; | |
| 1439 assert(helper != null); | |
| 1440 return helper; | |
| 1441 } | |
| 1442 | |
| 1443 String getCheckedModeHelperNameInternal(ResolutionDartType type, | |
| 1444 {bool typeCast, bool nativeCheckOnly}) { | |
| 1445 assert(type.kind != ResolutionTypeKind.TYPEDEF); | |
| 1446 if (type.isMalformed) { | |
| 1447 // The same error is thrown for type test and type cast of a malformed | |
| 1448 // type so we only need one check method. | |
| 1449 return 'checkMalformedType'; | |
| 1450 } | |
| 1451 | |
| 1452 if (type.isVoid) { | |
| 1453 assert(!typeCast); // Cannot cast to void. | |
| 1454 if (nativeCheckOnly) return null; | |
| 1455 return 'voidTypeCheck'; | |
| 1456 } | |
| 1457 | |
| 1458 if (type.isTypeVariable) { | |
| 1459 return typeCast | |
| 1460 ? 'subtypeOfRuntimeTypeCast' | |
| 1461 : 'assertSubtypeOfRuntimeType'; | |
| 1462 } | |
| 1463 | |
| 1464 if (type.isFunctionType) return null; | |
| 1465 | |
| 1466 assert(invariant(NO_LOCATION_SPANNABLE, type.isInterfaceType, | |
| 1467 message: "Unexpected type: $type (${type.kind})")); | |
| 1468 ClassElement element = type.element; | |
| 1469 bool nativeCheck = | |
| 1470 nativeCheckOnly || emitter.nativeEmitter.requiresNativeIsCheck(element); | |
| 1471 | |
| 1472 // TODO(13955), TODO(9731). The test for non-primitive types should use an | |
| 1473 // interceptor. The interceptor should be an argument to HTypeConversion so | |
| 1474 // that it can be optimized by standard interceptor optimizations. | |
| 1475 nativeCheck = true; | |
| 1476 | |
| 1477 var suffix = typeCast ? 'TypeCast' : 'TypeCheck'; | |
| 1478 if (element == helpers.jsStringClass || | |
| 1479 element == commonElements.stringClass) { | |
| 1480 if (nativeCheckOnly) return null; | |
| 1481 return 'string$suffix'; | |
| 1482 } | |
| 1483 | |
| 1484 if (element == helpers.jsDoubleClass || | |
| 1485 element == commonElements.doubleClass) { | |
| 1486 if (nativeCheckOnly) return null; | |
| 1487 return 'double$suffix'; | |
| 1488 } | |
| 1489 | |
| 1490 if (element == helpers.jsNumberClass || | |
| 1491 element == commonElements.numClass) { | |
| 1492 if (nativeCheckOnly) return null; | |
| 1493 return 'num$suffix'; | |
| 1494 } | |
| 1495 | |
| 1496 if (element == helpers.jsBoolClass || element == commonElements.boolClass) { | |
| 1497 if (nativeCheckOnly) return null; | |
| 1498 return 'bool$suffix'; | |
| 1499 } | |
| 1500 | |
| 1501 if (element == helpers.jsIntClass || | |
| 1502 element == commonElements.intClass || | |
| 1503 element == helpers.jsUInt32Class || | |
| 1504 element == helpers.jsUInt31Class || | |
| 1505 element == helpers.jsPositiveIntClass) { | |
| 1506 if (nativeCheckOnly) return null; | |
| 1507 return 'int$suffix'; | |
| 1508 } | |
| 1509 | |
| 1510 if (commonElements.isNumberOrStringSupertype(element)) { | |
| 1511 return nativeCheck | |
| 1512 ? 'numberOrStringSuperNative$suffix' | |
| 1513 : 'numberOrStringSuper$suffix'; | |
| 1514 } | |
| 1515 | |
| 1516 if (commonElements.isStringOnlySupertype(element)) { | |
| 1517 return nativeCheck ? 'stringSuperNative$suffix' : 'stringSuper$suffix'; | |
| 1518 } | |
| 1519 | |
| 1520 if ((element == commonElements.listClass || | |
| 1521 element == helpers.jsArrayClass) && | |
| 1522 type.treatAsRaw) { | |
| 1523 if (nativeCheckOnly) return null; | |
| 1524 return 'list$suffix'; | |
| 1525 } | |
| 1526 | |
| 1527 if (commonElements.isListSupertype(element)) { | |
| 1528 return nativeCheck ? 'listSuperNative$suffix' : 'listSuper$suffix'; | |
| 1529 } | |
| 1530 | |
| 1531 if (type.isInterfaceType && !type.treatAsRaw) { | |
| 1532 return typeCast ? 'subtypeCast' : 'assertSubtype'; | |
| 1533 } | |
| 1534 | |
| 1535 if (nativeCheck) { | |
| 1536 // TODO(karlklose): can we get rid of this branch when we use | |
| 1537 // interceptors? | |
| 1538 return 'intercepted$suffix'; | |
| 1539 } else { | |
| 1540 return 'property$suffix'; | |
| 1541 } | |
| 1542 } | |
| 1543 | |
| 1544 void _registerCheckedModeHelpers(WorldImpactBuilder impactBuilder) { | 1282 void _registerCheckedModeHelpers(WorldImpactBuilder impactBuilder) { |
| 1545 // We register all the helpers in the resolution queue. | 1283 // We register all the helpers in the resolution queue. |
| 1546 // TODO(13155): Find a way to register fewer helpers. | 1284 // TODO(13155): Find a way to register fewer helpers. |
| 1547 List<Element> staticUses = <Element>[]; | 1285 List<Element> staticUses = <Element>[]; |
| 1548 for (CheckedModeHelper helper in checkedModeHelpers) { | 1286 for (CheckedModeHelper helper in CheckedModeHelpers.helpers) { |
| 1549 staticUses.add(helper.getStaticUse(compiler).element); | 1287 staticUses.add(helper.getStaticUse(helpers).element); |
| 1550 } | 1288 } |
| 1551 impactTransformer.registerBackendImpact( | 1289 impactTransformer.registerBackendImpact( |
| 1552 impactBuilder, new BackendImpact(globalUses: staticUses)); | 1290 impactBuilder, new BackendImpact(globalUses: staticUses)); |
| 1553 } | 1291 } |
| 1554 | 1292 |
| 1555 /** | 1293 /** |
| 1556 * Returns [:true:] if the checking of [type] is performed directly on the | 1294 * Returns [:true:] if the checking of [type] is performed directly on the |
| 1557 * object and not on an interceptor. | 1295 * object and not on an interceptor. |
| 1558 */ | 1296 */ |
| 1559 bool hasDirectCheckFor(ResolutionDartType type) { | 1297 bool hasDirectCheckFor(ResolutionDartType type) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1578 ClassElement classElement = type.element; | 1316 ClassElement classElement = type.element; |
| 1579 if (interceptorData.isInterceptorClass(classElement)) return false; | 1317 if (interceptorData.isInterceptorClass(classElement)) return false; |
| 1580 return _closedWorld.hasOnlySubclasses(classElement); | 1318 return _closedWorld.hasOnlySubclasses(classElement); |
| 1581 } | 1319 } |
| 1582 | 1320 |
| 1583 /// Called to register that [element] is statically known to be used. Any | 1321 /// Called to register that [element] is statically known to be used. Any |
| 1584 /// backend specific [WorldImpact] of this is returned. | 1322 /// backend specific [WorldImpact] of this is returned. |
| 1585 WorldImpact registerUsedElement(MemberElement element, {bool forResolution}) { | 1323 WorldImpact registerUsedElement(MemberElement element, {bool forResolution}) { |
| 1586 WorldImpactBuilderImpl worldImpact = new WorldImpactBuilderImpl(); | 1324 WorldImpactBuilderImpl worldImpact = new WorldImpactBuilderImpl(); |
| 1587 if (element == helpers.disableTreeShakingMarker) { | 1325 if (element == helpers.disableTreeShakingMarker) { |
| 1588 isTreeShakingDisabled = true; | 1326 mirrorsData.isTreeShakingDisabled = true; |
| 1589 } else if (element == helpers.preserveNamesMarker) { | 1327 } else if (element == helpers.preserveNamesMarker) { |
| 1590 mustPreserveNames = true; | 1328 mirrorsData.mustPreserveNames = true; |
| 1591 } else if (element == helpers.preserveMetadataMarker) { | 1329 } else if (element == helpers.preserveMetadataMarker) { |
| 1592 mustRetainMetadata = true; | 1330 mirrorsData.mustRetainMetadata = true; |
| 1593 } else if (element == helpers.preserveUrisMarker) { | 1331 } else if (element == helpers.preserveUrisMarker) { |
| 1594 if (compiler.options.preserveUris) mustPreserveUris = true; | 1332 if (compiler.options.preserveUris) mustPreserveUris = true; |
| 1595 } else if (element == helpers.preserveLibraryNamesMarker) { | 1333 } else if (element == helpers.preserveLibraryNamesMarker) { |
| 1596 mustRetainLibraryNames = true; | 1334 mirrorsData.mustRetainLibraryNames = true; |
| 1597 } else if (element == helpers.getIsolateAffinityTagMarker) { | 1335 } else if (element == helpers.getIsolateAffinityTagMarker) { |
| 1598 needToInitializeIsolateAffinityTag = true; | 1336 backendUsage.needToInitializeIsolateAffinityTag = true; |
| 1599 } else if (element.isDeferredLoaderGetter) { | 1337 } else if (element.isDeferredLoaderGetter) { |
| 1600 // TODO(sigurdm): Create a function registerLoadLibraryAccess. | 1338 // TODO(sigurdm): Create a function registerLoadLibraryAccess. |
| 1601 if (!isLoadLibraryFunctionResolved) { | 1339 if (!isLoadLibraryFunctionResolved) { |
| 1602 isLoadLibraryFunctionResolved = true; | 1340 isLoadLibraryFunctionResolved = true; |
| 1603 if (forResolution) { | 1341 if (forResolution) { |
| 1604 impactTransformer.registerBackendImpact( | 1342 impactTransformer.registerBackendImpact( |
| 1605 worldImpact, impacts.loadLibrary); | 1343 worldImpact, impacts.loadLibrary); |
| 1606 } | 1344 } |
| 1607 } | 1345 } |
| 1608 } else if (element == helpers.requiresPreambleMarker) { | 1346 } else if (element == helpers.requiresPreambleMarker) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1657 hasFunctionApplySupport = true; | 1395 hasFunctionApplySupport = true; |
| 1658 } | 1396 } |
| 1659 } else { | 1397 } else { |
| 1660 // TODO(sigmund): add other missing dependencies (internals, selectors | 1398 // TODO(sigmund): add other missing dependencies (internals, selectors |
| 1661 // enqueued after allocations). | 1399 // enqueued after allocations). |
| 1662 compiler.dumpInfoTask.registerDependency(element); | 1400 compiler.dumpInfoTask.registerDependency(element); |
| 1663 } | 1401 } |
| 1664 return worldImpact; | 1402 return worldImpact; |
| 1665 } | 1403 } |
| 1666 | 1404 |
| 1667 /// Called when [:const Symbol(name):] is seen. | |
| 1668 void registerConstSymbol(String name) { | |
| 1669 symbolsUsed.add(name); | |
| 1670 if (name.endsWith('=')) { | |
| 1671 symbolsUsed.add(name.substring(0, name.length - 1)); | |
| 1672 } | |
| 1673 } | |
| 1674 | |
| 1675 /// Should [element] (a getter) that would normally not be generated due to | |
| 1676 /// treeshaking be retained for reflection? | |
| 1677 bool shouldRetainGetter(Element element) { | |
| 1678 return isTreeShakingDisabled && isAccessibleByReflection(element); | |
| 1679 } | |
| 1680 | |
| 1681 /// Should [element] (a setter) hat would normally not be generated due to | |
| 1682 /// treeshaking be retained for reflection? | |
| 1683 bool shouldRetainSetter(Element element) { | |
| 1684 return isTreeShakingDisabled && isAccessibleByReflection(element); | |
| 1685 } | |
| 1686 | |
| 1687 /// Should [name] be retained for reflection? | |
| 1688 bool shouldRetainName(String name) { | |
| 1689 if (hasInsufficientMirrorsUsed) return mustPreserveNames; | |
| 1690 if (name == '') return false; | |
| 1691 return symbolsUsed.contains(name); | |
| 1692 } | |
| 1693 | |
| 1694 bool retainMetadataOf(Element element) { | |
| 1695 if (mustRetainMetadata) hasRetainedMetadata = true; | |
| 1696 if (mustRetainMetadata && referencedFromMirrorSystem(element)) { | |
| 1697 for (MetadataAnnotation metadata in element.metadata) { | |
| 1698 metadata.ensureResolved(resolution); | |
| 1699 ConstantValue constant = | |
| 1700 constants.getConstantValueForMetadata(metadata); | |
| 1701 constants.addCompileTimeConstantForEmission(constant); | |
| 1702 } | |
| 1703 return true; | |
| 1704 } | |
| 1705 return false; | |
| 1706 } | |
| 1707 | |
| 1708 /// This method is called immediately after the [library] and its parts have | 1405 /// This method is called immediately after the [library] and its parts have |
| 1709 /// been scanned. | 1406 /// been scanned. |
| 1710 Future onLibraryScanned(LibraryElement library, LibraryLoader loader) { | 1407 Future onLibraryScanned(LibraryElement library, LibraryLoader loader) { |
| 1711 if (!compiler.serialization.isDeserialized(library)) { | 1408 if (!compiler.serialization.isDeserialized(library)) { |
| 1712 if (canLibraryUseNative(library)) { | 1409 if (canLibraryUseNative(library)) { |
| 1713 library.forEachLocalMember((Element element) { | 1410 library.forEachLocalMember((Element element) { |
| 1714 if (element.isClass) { | 1411 if (element.isClass) { |
| 1715 checkNativeAnnotation(compiler, element); | 1412 checkNativeAnnotation(compiler, element); |
| 1716 } | 1413 } |
| 1717 }); | 1414 }); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1777 ..add(helpers.jsInterceptorClass) | 1474 ..add(helpers.jsInterceptorClass) |
| 1778 ..add(helpers.jsNullClass); | 1475 ..add(helpers.jsNullClass); |
| 1779 | 1476 |
| 1780 validateInterceptorImplementsAllObjectMethods(helpers.jsInterceptorClass); | 1477 validateInterceptorImplementsAllObjectMethods(helpers.jsInterceptorClass); |
| 1781 // The null-interceptor must also implement *all* methods. | 1478 // The null-interceptor must also implement *all* methods. |
| 1782 validateInterceptorImplementsAllObjectMethods(helpers.jsNullClass); | 1479 validateInterceptorImplementsAllObjectMethods(helpers.jsNullClass); |
| 1783 | 1480 |
| 1784 return new Future.value(); | 1481 return new Future.value(); |
| 1785 } | 1482 } |
| 1786 | 1483 |
| 1787 /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed | |
| 1788 /// annotations. The arguments corresponds to the unions of the corresponding | |
| 1789 /// fields of the annotations. | |
| 1790 void registerMirrorUsage( | |
| 1791 Set<String> symbols, Set<Element> targets, Set<Element> metaTargets) { | |
| 1792 if (symbols == null && targets == null && metaTargets == null) { | |
| 1793 // The user didn't specify anything, or there are imports of | |
| 1794 // 'dart:mirrors' without @MirrorsUsed. | |
| 1795 hasInsufficientMirrorsUsed = true; | |
| 1796 return; | |
| 1797 } | |
| 1798 if (symbols != null) symbolsUsed.addAll(symbols); | |
| 1799 if (targets != null) { | |
| 1800 for (Element target in targets) { | |
| 1801 if (target.isAbstractField) { | |
| 1802 AbstractFieldElement field = target; | |
| 1803 targetsUsed.add(field.getter); | |
| 1804 targetsUsed.add(field.setter); | |
| 1805 } else { | |
| 1806 targetsUsed.add(target); | |
| 1807 } | |
| 1808 } | |
| 1809 } | |
| 1810 if (metaTargets != null) metaTargetsUsed.addAll(metaTargets); | |
| 1811 } | |
| 1812 | |
| 1813 /** | |
| 1814 * Returns `true` if [element] can be accessed through reflection, that is, | |
| 1815 * is in the set of elements covered by a `MirrorsUsed` annotation. | |
| 1816 * | |
| 1817 * This property is used to tag emitted elements with a marker which is | |
| 1818 * checked by the runtime system to throw an exception if an element is | |
| 1819 * accessed (invoked, get, set) that is not accessible for the reflective | |
| 1820 * system. | |
| 1821 */ | |
| 1822 bool isAccessibleByReflection(Element element) { | |
| 1823 if (element.isClass) { | |
| 1824 element = getDartClass(element); | |
| 1825 } | |
| 1826 return membersNeededForReflection.contains(element); | |
| 1827 } | |
| 1828 | |
| 1829 /// Returns `true` if this member element needs reflection information at | |
| 1830 /// runtime. | |
| 1831 bool isMemberAccessibleByReflection(MemberElement element) { | |
| 1832 return membersNeededForReflection.contains(element); | |
| 1833 } | |
| 1834 | |
| 1835 /// Returns true if this element has to be enqueued due to | |
| 1836 /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if | |
| 1837 /// normal tree shaking is still active ([isTreeShakingDisabled] is false). | |
| 1838 bool requiredByMirrorSystem(Element element) { | |
| 1839 return hasInsufficientMirrorsUsed && isTreeShakingDisabled || | |
| 1840 matchesMirrorsMetaTarget(element) || | |
| 1841 targetsUsed.contains(element); | |
| 1842 } | |
| 1843 | |
| 1844 /// Returns true if this element is covered by a mirrorsUsed annotation. | |
| 1845 /// | |
| 1846 /// Note that it might still be ok to tree shake the element away if no | |
| 1847 /// reflection is used in the program (and thus [isTreeShakingDisabled] is | |
| 1848 /// still false). Therefore _do not_ use this predicate to decide inclusion | |
| 1849 /// in the tree, use [requiredByMirrorSystem] instead. | |
| 1850 bool referencedFromMirrorSystem(Element element, [recursive = true]) { | |
| 1851 Element enclosing = recursive ? element.enclosingElement : null; | |
| 1852 | |
| 1853 return hasInsufficientMirrorsUsed || | |
| 1854 matchesMirrorsMetaTarget(element) || | |
| 1855 targetsUsed.contains(element) || | |
| 1856 (enclosing != null && referencedFromMirrorSystem(enclosing)); | |
| 1857 } | |
| 1858 | |
| 1859 /** | |
| 1860 * Returns `true` if the element is needed because it has an annotation | |
| 1861 * of a type that is used as a meta target for reflection. | |
| 1862 */ | |
| 1863 bool matchesMirrorsMetaTarget(Element element) { | |
| 1864 if (metaTargetsUsed.isEmpty) return false; | |
| 1865 for (MetadataAnnotation metadata in element.metadata) { | |
| 1866 // TODO(kasperl): It would be nice if we didn't have to resolve | |
| 1867 // all metadata but only stuff that potentially would match one | |
| 1868 // of the used meta targets. | |
| 1869 metadata.ensureResolved(resolution); | |
| 1870 ConstantValue value = | |
| 1871 compiler.constants.getConstantValue(metadata.constant); | |
| 1872 if (value == null) continue; | |
| 1873 ResolutionDartType type = value.getType(compiler.commonElements); | |
| 1874 if (metaTargetsUsed.contains(type.element)) return true; | |
| 1875 } | |
| 1876 return false; | |
| 1877 } | |
| 1878 | |
| 1879 /** | |
| 1880 * Visits all classes and computes whether its members are needed for | |
| 1881 * reflection. | |
| 1882 * | |
| 1883 * We have to precompute this set as we cannot easily answer the need for | |
| 1884 * reflection locally when looking at the member: We lack the information by | |
| 1885 * which classes a member is inherited. Called after resolution is complete. | |
| 1886 * | |
| 1887 * We filter out private libraries here, as their elements should not | |
| 1888 * be visible by reflection unless some other interfaces makes them | |
| 1889 * accessible. | |
| 1890 */ | |
| 1891 void computeMembersNeededForReflection(ClosedWorld closedWorld) { | |
| 1892 if (_membersNeededForReflection != null) return; | |
| 1893 if (closedWorld.commonElements.mirrorsLibrary == null) { | |
| 1894 _membersNeededForReflection = const ImmutableEmptySet<Element>(); | |
| 1895 return; | |
| 1896 } | |
| 1897 // Compute a mapping from class to the closures it contains, so we | |
| 1898 // can include the correct ones when including the class. | |
| 1899 Map<ClassElement, List<LocalFunctionElement>> closureMap = | |
| 1900 new Map<ClassElement, List<LocalFunctionElement>>(); | |
| 1901 for (LocalFunctionElement closure | |
| 1902 in compiler.resolutionWorldBuilder.allClosures) { | |
| 1903 closureMap.putIfAbsent(closure.enclosingClass, () => []).add(closure); | |
| 1904 } | |
| 1905 bool foundClosure = false; | |
| 1906 Set<Element> reflectableMembers = new Set<Element>(); | |
| 1907 ResolutionEnqueuer resolution = compiler.enqueuer.resolution; | |
| 1908 for (ClassElement cls | |
| 1909 in resolution.worldBuilder.directlyInstantiatedClasses) { | |
| 1910 // Do not process internal classes. | |
| 1911 if (cls.library.isInternalLibrary || cls.isInjected) continue; | |
| 1912 if (referencedFromMirrorSystem(cls)) { | |
| 1913 Set<Name> memberNames = new Set<Name>(); | |
| 1914 // 1) the class (should be resolved) | |
| 1915 assert(invariant(cls, cls.isResolved)); | |
| 1916 reflectableMembers.add(cls); | |
| 1917 // 2) its constructors (if resolved) | |
| 1918 cls.constructors.forEach((Element constructor) { | |
| 1919 if (resolution.hasBeenProcessed(constructor)) { | |
| 1920 reflectableMembers.add(constructor); | |
| 1921 } | |
| 1922 }); | |
| 1923 // 3) all members, including fields via getter/setters (if resolved) | |
| 1924 cls.forEachClassMember((Member member) { | |
| 1925 MemberElement element = member.element; | |
| 1926 if (resolution.hasBeenProcessed(element)) { | |
| 1927 memberNames.add(member.name); | |
| 1928 reflectableMembers.add(element); | |
| 1929 element.nestedClosures | |
| 1930 .forEach((SynthesizedCallMethodElementX callFunction) { | |
| 1931 reflectableMembers.add(callFunction); | |
| 1932 reflectableMembers.add(callFunction.closureClass); | |
| 1933 }); | |
| 1934 } | |
| 1935 }); | |
| 1936 // 4) all overriding members of subclasses/subtypes (should be resolved) | |
| 1937 if (closedWorld.hasAnyStrictSubtype(cls)) { | |
| 1938 closedWorld.forEachStrictSubtypeOf(cls, (ClassElement subcls) { | |
| 1939 subcls.forEachClassMember((Member member) { | |
| 1940 if (memberNames.contains(member.name)) { | |
| 1941 // TODO(20993): find out why this assertion fails. | |
| 1942 // assert(invariant(member.element, | |
| 1943 // resolution.hasBeenProcessed(member.element))); | |
| 1944 if (resolution.hasBeenProcessed(member.element)) { | |
| 1945 reflectableMembers.add(member.element); | |
| 1946 } | |
| 1947 } | |
| 1948 }); | |
| 1949 }); | |
| 1950 } | |
| 1951 // 5) all its closures | |
| 1952 List<LocalFunctionElement> closures = closureMap[cls]; | |
| 1953 if (closures != null) { | |
| 1954 reflectableMembers.addAll(closures); | |
| 1955 foundClosure = true; | |
| 1956 } | |
| 1957 } else { | |
| 1958 // check members themselves | |
| 1959 cls.constructors.forEach((ConstructorElement element) { | |
| 1960 if (!resolution.hasBeenProcessed(element)) return; | |
| 1961 if (referencedFromMirrorSystem(element, false)) { | |
| 1962 reflectableMembers.add(element); | |
| 1963 } | |
| 1964 }); | |
| 1965 cls.forEachClassMember((Member member) { | |
| 1966 if (!resolution.hasBeenProcessed(member.element)) return; | |
| 1967 if (referencedFromMirrorSystem(member.element, false)) { | |
| 1968 reflectableMembers.add(member.element); | |
| 1969 } | |
| 1970 }); | |
| 1971 // Also add in closures. Those might be reflectable is their enclosing | |
| 1972 // member is. | |
| 1973 List<LocalFunctionElement> closures = closureMap[cls]; | |
| 1974 if (closures != null) { | |
| 1975 for (LocalFunctionElement closure in closures) { | |
| 1976 MemberElement member = closure.memberContext; | |
| 1977 if (referencedFromMirrorSystem(member, false)) { | |
| 1978 reflectableMembers.add(closure); | |
| 1979 foundClosure = true; | |
| 1980 } | |
| 1981 } | |
| 1982 } | |
| 1983 } | |
| 1984 } | |
| 1985 // We also need top-level non-class elements like static functions and | |
| 1986 // global fields. We use the resolution queue to decide which elements are | |
| 1987 // part of the live world. | |
| 1988 for (LibraryElement lib in compiler.libraryLoader.libraries) { | |
| 1989 if (lib.isInternalLibrary) continue; | |
| 1990 lib.forEachLocalMember((Element member) { | |
| 1991 if (!(member.isClass || member.isTypedef) && | |
| 1992 resolution.hasBeenProcessed(member) && | |
| 1993 referencedFromMirrorSystem(member)) { | |
| 1994 reflectableMembers.add(member); | |
| 1995 } | |
| 1996 }); | |
| 1997 } | |
| 1998 // And closures inside top-level elements that do not have a surrounding | |
| 1999 // class. These will be in the [:null:] bucket of the [closureMap]. | |
| 2000 if (closureMap.containsKey(null)) { | |
| 2001 for (Element closure in closureMap[null]) { | |
| 2002 if (referencedFromMirrorSystem(closure)) { | |
| 2003 reflectableMembers.add(closure); | |
| 2004 foundClosure = true; | |
| 2005 } | |
| 2006 } | |
| 2007 } | |
| 2008 // As we do not think about closures as classes, yet, we have to make sure | |
| 2009 // their superclasses are available for reflection manually. | |
| 2010 if (foundClosure) { | |
| 2011 ClassElement cls = helpers.closureClass; | |
| 2012 reflectableMembers.add(cls); | |
| 2013 } | |
| 2014 Set<Element> closurizedMembers = | |
| 2015 compiler.resolutionWorldBuilder.closurizedMembers; | |
| 2016 if (closurizedMembers.any(reflectableMembers.contains)) { | |
| 2017 ClassElement cls = helpers.boundClosureClass; | |
| 2018 reflectableMembers.add(cls); | |
| 2019 } | |
| 2020 // Add typedefs. | |
| 2021 reflectableMembers | |
| 2022 .addAll(closedWorld.allTypedefs.where(referencedFromMirrorSystem)); | |
| 2023 // Register all symbols of reflectable elements | |
| 2024 for (Element element in reflectableMembers) { | |
| 2025 symbolsUsed.add(element.name); | |
| 2026 } | |
| 2027 _membersNeededForReflection = reflectableMembers; | |
| 2028 } | |
| 2029 | |
| 2030 // TODO(20791): compute closure classes after resolution and move this code to | |
| 2031 // [computeMembersNeededForReflection]. | |
| 2032 void maybeMarkClosureAsNeededForReflection( | |
| 2033 ClosureClassElement globalizedElement, | |
| 2034 FunctionElement callFunction, | |
| 2035 FunctionElement function) { | |
| 2036 if (!_membersNeededForReflection.contains(function)) return; | |
| 2037 _membersNeededForReflection.add(callFunction); | |
| 2038 _membersNeededForReflection.add(globalizedElement); | |
| 2039 } | |
| 2040 | |
| 2041 jsAst.Call generateIsJsIndexableCall( | 1484 jsAst.Call generateIsJsIndexableCall( |
| 2042 jsAst.Expression use1, jsAst.Expression use2) { | 1485 jsAst.Expression use1, jsAst.Expression use2) { |
| 2043 String dispatchPropertyName = embeddedNames.DISPATCH_PROPERTY_NAME; | 1486 String dispatchPropertyName = embeddedNames.DISPATCH_PROPERTY_NAME; |
| 2044 jsAst.Expression dispatchProperty = | 1487 jsAst.Expression dispatchProperty = |
| 2045 emitter.generateEmbeddedGlobalAccess(dispatchPropertyName); | 1488 emitter.generateEmbeddedGlobalAccess(dispatchPropertyName); |
| 2046 | 1489 |
| 2047 // We pass the dispatch property record to the isJsIndexable | 1490 // We pass the dispatch property record to the isJsIndexable |
| 2048 // helper rather than reading it inside the helper to increase the | 1491 // helper rather than reading it inside the helper to increase the |
| 2049 // chance of making the dispatch record access monomorphic. | 1492 // chance of making the dispatch record access monomorphic. |
| 2050 jsAst.PropertyAccess record = | 1493 jsAst.PropertyAccess record = |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2065 void addFieldsInContainer(ScopeContainerElement container) { | 1508 void addFieldsInContainer(ScopeContainerElement container) { |
| 2066 container.forEachLocalMember((Element member) { | 1509 container.forEachLocalMember((Element member) { |
| 2067 if (!member.isInstanceMember && member.isField) { | 1510 if (!member.isInstanceMember && member.isField) { |
| 2068 staticFields.add(member); | 1511 staticFields.add(member); |
| 2069 } else if (member.isClass) { | 1512 } else if (member.isClass) { |
| 2070 addFieldsInContainer(member); | 1513 addFieldsInContainer(member); |
| 2071 } | 1514 } |
| 2072 }); | 1515 }); |
| 2073 } | 1516 } |
| 2074 | 1517 |
| 2075 for (Element target in targetsUsed) { | 1518 for (Element target in mirrorsData.targetsUsed) { |
| 2076 if (target == null) continue; | 1519 if (target == null) continue; |
| 2077 if (target.isField) { | 1520 if (target.isField) { |
| 2078 staticFields.add(target); | 1521 staticFields.add(target); |
| 2079 } else if (target.isLibrary || target.isClass) { | 1522 } else if (target.isLibrary || target.isClass) { |
| 2080 addFieldsInContainer(target); | 1523 addFieldsInContainer(target); |
| 2081 } | 1524 } |
| 2082 } | 1525 } |
| 2083 return staticFields; | 1526 return staticFields; |
| 2084 } | 1527 } |
| 2085 | 1528 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2138 if (!enqueuer.queueIsEmpty) return false; | 1581 if (!enqueuer.queueIsEmpty) return false; |
| 2139 | 1582 |
| 2140 if (compiler.options.useKernel && compiler.mainApp != null) { | 1583 if (compiler.options.useKernel && compiler.mainApp != null) { |
| 2141 kernelTask.buildKernelIr(); | 1584 kernelTask.buildKernelIr(); |
| 2142 } | 1585 } |
| 2143 | 1586 |
| 2144 if (!enqueuer.isResolutionQueue && preMirrorsMethodCount == 0) { | 1587 if (!enqueuer.isResolutionQueue && preMirrorsMethodCount == 0) { |
| 2145 preMirrorsMethodCount = generatedCode.length; | 1588 preMirrorsMethodCount = generatedCode.length; |
| 2146 } | 1589 } |
| 2147 | 1590 |
| 2148 if (isTreeShakingDisabled) { | 1591 if (mirrorsData.isTreeShakingDisabled) { |
| 2149 enqueuer.applyImpact(mirrorsAnalysis.computeImpactForReflectiveElements( | 1592 enqueuer.applyImpact(mirrorsAnalysis.computeImpactForReflectiveElements( |
| 2150 recentClasses, | 1593 recentClasses, |
| 2151 enqueuer.processedClasses, | 1594 enqueuer.processedClasses, |
| 2152 compiler.libraryLoader.libraries, | 1595 compiler.libraryLoader.libraries, |
| 2153 forResolution: enqueuer.isResolutionQueue)); | 1596 forResolution: enqueuer.isResolutionQueue)); |
| 2154 } else if (!targetsUsed.isEmpty && enqueuer.isResolutionQueue) { | 1597 } else if (!mirrorsData.targetsUsed.isEmpty && enqueuer.isResolutionQueue) { |
| 2155 // Add all static elements (not classes) that have been requested for | 1598 // Add all static elements (not classes) that have been requested for |
| 2156 // reflection. If there is no mirror-usage these are probably not | 1599 // reflection. If there is no mirror-usage these are probably not |
| 2157 // necessary, but the backend relies on them being resolved. | 1600 // necessary, but the backend relies on them being resolved. |
| 2158 enqueuer.applyImpact(mirrorsAnalysis | 1601 enqueuer.applyImpact(mirrorsAnalysis |
| 2159 .computeImpactForReflectiveStaticFields(_findStaticFieldTargets(), | 1602 .computeImpactForReflectiveStaticFields(_findStaticFieldTargets(), |
| 2160 forResolution: enqueuer.isResolutionQueue)); | 1603 forResolution: enqueuer.isResolutionQueue)); |
| 2161 } | 1604 } |
| 2162 | 1605 |
| 2163 if (mustPreserveNames) reporter.log('Preserving names.'); | 1606 if (mirrorsData.mustPreserveNames) reporter.log('Preserving names.'); |
| 2164 | 1607 |
| 2165 if (mustRetainMetadata) { | 1608 if (mirrorsData.mustRetainMetadata) { |
| 2166 reporter.log('Retaining metadata.'); | 1609 reporter.log('Retaining metadata.'); |
| 2167 | 1610 |
| 2168 compiler.libraryLoader.libraries.forEach(retainMetadataOf); | 1611 compiler.libraryLoader.libraries.forEach(mirrorsData.retainMetadataOf); |
| 2169 | 1612 |
| 2170 StagedWorldImpactBuilder impactBuilder = enqueuer.isResolutionQueue | 1613 StagedWorldImpactBuilder impactBuilder = enqueuer.isResolutionQueue |
| 2171 ? constantImpactsForResolution | 1614 ? constantImpactsForResolution |
| 2172 : constantImpactsForCodegen; | 1615 : constantImpactsForCodegen; |
| 2173 if (enqueuer.isResolutionQueue && !enqueuer.queueIsClosed) { | 1616 if (enqueuer.isResolutionQueue && !enqueuer.queueIsClosed) { |
| 2174 /// Register the constant value of [metadata] as live in resolution. | 1617 /// Register the constant value of [metadata] as live in resolution. |
| 2175 void registerMetadataConstant(MetadataAnnotation metadata) { | 1618 void registerMetadataConstant(MetadataAnnotation metadata) { |
| 2176 ConstantValue constant = | 1619 ConstantValue constant = |
| 2177 constants.getConstantValueForMetadata(metadata); | 1620 constants.getConstantValueForMetadata(metadata); |
| 2178 Dependency dependency = | 1621 Dependency dependency = |
| (...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2760 // factory constructors are registered directly. | 2203 // factory constructors are registered directly. |
| 2761 transformed | 2204 transformed |
| 2762 .registerTypeUse(new TypeUse.instantiation(listLiteralUse.type)); | 2205 .registerTypeUse(new TypeUse.instantiation(listLiteralUse.type)); |
| 2763 ResolutionInterfaceType type = listLiteralUse.type; | 2206 ResolutionInterfaceType type = listLiteralUse.type; |
| 2764 registerRequiredType(type); | 2207 registerRequiredType(type); |
| 2765 } | 2208 } |
| 2766 | 2209 |
| 2767 if (worldImpact.constSymbolNames.isNotEmpty) { | 2210 if (worldImpact.constSymbolNames.isNotEmpty) { |
| 2768 registerBackendImpact(transformed, impacts.constSymbol); | 2211 registerBackendImpact(transformed, impacts.constSymbol); |
| 2769 for (String constSymbolName in worldImpact.constSymbolNames) { | 2212 for (String constSymbolName in worldImpact.constSymbolNames) { |
| 2770 backend.registerConstSymbol(constSymbolName); | 2213 backend.mirrorsData.registerConstSymbol(constSymbolName); |
| 2771 } | 2214 } |
| 2772 } | 2215 } |
| 2773 | 2216 |
| 2774 for (StaticUse staticUse in worldImpact.staticUses) { | 2217 for (StaticUse staticUse in worldImpact.staticUses) { |
| 2775 switch (staticUse.kind) { | 2218 switch (staticUse.kind) { |
| 2776 case StaticUseKind.CLOSURE: | 2219 case StaticUseKind.CLOSURE: |
| 2777 registerBackendImpact(transformed, impacts.closure); | 2220 registerBackendImpact(transformed, impacts.closure); |
| 2778 LocalFunctionElement closure = staticUse.element; | 2221 LocalFunctionElement closure = staticUse.element; |
| 2779 if (closure.type.containsTypeVariables) { | 2222 if (closure.type.containsTypeVariables) { |
| 2780 registerBackendImpact(transformed, impacts.computeSignature); | 2223 registerBackendImpact(transformed, impacts.computeSignature); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2821 | 2264 |
| 2822 WorldImpact createImpactFor(BackendImpact impact) { | 2265 WorldImpact createImpactFor(BackendImpact impact) { |
| 2823 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl(); | 2266 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl(); |
| 2824 registerBackendImpact(impactBuilder, impact); | 2267 registerBackendImpact(impactBuilder, impact); |
| 2825 return impactBuilder; | 2268 return impactBuilder; |
| 2826 } | 2269 } |
| 2827 | 2270 |
| 2828 void registerBackendStaticUse( | 2271 void registerBackendStaticUse( |
| 2829 WorldImpactBuilder worldImpact, MethodElement element, | 2272 WorldImpactBuilder worldImpact, MethodElement element, |
| 2830 {bool isGlobal: false}) { | 2273 {bool isGlobal: false}) { |
| 2831 backend.registerBackendUse(element); | 2274 backend.backendUsage.registerBackendUse(element); |
| 2832 worldImpact.registerStaticUse( | 2275 worldImpact.registerStaticUse( |
| 2833 // TODO(johnniwinther): Store the correct use in impacts. | 2276 // TODO(johnniwinther): Store the correct use in impacts. |
| 2834 new StaticUse.foreignUse(element)); | 2277 new StaticUse.foreignUse(element)); |
| 2835 if (isGlobal) { | 2278 if (isGlobal) { |
| 2836 backend.compiler.globalDependencies.registerDependency(element); | 2279 backend.compiler.globalDependencies.registerDependency(element); |
| 2837 } | 2280 } |
| 2838 } | 2281 } |
| 2839 | 2282 |
| 2840 void registerBackendInstantiation( | 2283 void registerBackendInstantiation( |
| 2841 WorldImpactBuilder worldImpact, ClassElement cls, | 2284 WorldImpactBuilder worldImpact, ClassElement cls, |
| 2842 {bool isGlobal: false}) { | 2285 {bool isGlobal: false}) { |
| 2843 cls.ensureResolved(backend.resolution); | 2286 cls.ensureResolved(backend.resolution); |
| 2844 backend.registerBackendUse(cls); | 2287 backend.backendUsage.registerBackendUse(cls); |
| 2845 worldImpact.registerTypeUse(new TypeUse.instantiation(cls.rawType)); | 2288 worldImpact.registerTypeUse(new TypeUse.instantiation(cls.rawType)); |
| 2846 if (isGlobal) { | 2289 if (isGlobal) { |
| 2847 backend.compiler.globalDependencies.registerDependency(cls); | 2290 backend.compiler.globalDependencies.registerDependency(cls); |
| 2848 } | 2291 } |
| 2849 } | 2292 } |
| 2850 | 2293 |
| 2851 void registerBackendImpact( | 2294 void registerBackendImpact( |
| 2852 WorldImpactBuilder worldImpact, BackendImpact backendImpact) { | 2295 WorldImpactBuilder worldImpact, BackendImpact backendImpact) { |
| 2853 for (Element staticUse in backendImpact.staticUses) { | 2296 for (Element staticUse in backendImpact.staticUses) { |
| 2854 assert(staticUse != null); | 2297 assert(staticUse != null); |
| 2855 registerBackendStaticUse(worldImpact, staticUse); | 2298 registerBackendStaticUse(worldImpact, staticUse); |
| 2856 } | 2299 } |
| 2857 for (Element staticUse in backendImpact.globalUses) { | 2300 for (Element staticUse in backendImpact.globalUses) { |
| 2858 assert(staticUse != null); | 2301 assert(staticUse != null); |
| 2859 registerBackendStaticUse(worldImpact, staticUse, isGlobal: true); | 2302 registerBackendStaticUse(worldImpact, staticUse, isGlobal: true); |
| 2860 } | 2303 } |
| 2861 for (Selector selector in backendImpact.dynamicUses) { | 2304 for (Selector selector in backendImpact.dynamicUses) { |
| 2862 assert(selector != null); | 2305 assert(selector != null); |
| 2863 worldImpact.registerDynamicUse(new DynamicUse(selector, null)); | 2306 worldImpact.registerDynamicUse(new DynamicUse(selector, null)); |
| 2864 } | 2307 } |
| 2865 for (ResolutionInterfaceType instantiatedType | 2308 for (ResolutionInterfaceType instantiatedType |
| 2866 in backendImpact.instantiatedTypes) { | 2309 in backendImpact.instantiatedTypes) { |
| 2867 backend.registerBackendUse(instantiatedType.element); | 2310 backend.backendUsage.registerBackendUse(instantiatedType.element); |
| 2868 worldImpact.registerTypeUse(new TypeUse.instantiation(instantiatedType)); | 2311 worldImpact.registerTypeUse(new TypeUse.instantiation(instantiatedType)); |
| 2869 } | 2312 } |
| 2870 for (ClassElement cls in backendImpact.instantiatedClasses) { | 2313 for (ClassElement cls in backendImpact.instantiatedClasses) { |
| 2871 registerBackendInstantiation(worldImpact, cls); | 2314 registerBackendInstantiation(worldImpact, cls); |
| 2872 } | 2315 } |
| 2873 for (ClassElement cls in backendImpact.globalClasses) { | 2316 for (ClassElement cls in backendImpact.globalClasses) { |
| 2874 registerBackendInstantiation(worldImpact, cls, isGlobal: true); | 2317 registerBackendInstantiation(worldImpact, cls, isGlobal: true); |
| 2875 } | 2318 } |
| 2876 for (BackendImpact otherImpact in backendImpact.otherImpacts) { | 2319 for (BackendImpact otherImpact in backendImpact.otherImpacts) { |
| 2877 registerBackendImpact(worldImpact, otherImpact); | 2320 registerBackendImpact(worldImpact, otherImpact); |
| 2878 } | 2321 } |
| 2879 for (BackendFeature feature in backendImpact.features) { | 2322 for (BackendFeature feature in backendImpact.features) { |
| 2880 switch (feature) { | 2323 switch (feature) { |
| 2881 case BackendFeature.needToInitializeDispatchProperty: | 2324 case BackendFeature.needToInitializeDispatchProperty: |
| 2882 backend.needToInitializeDispatchProperty = true; | 2325 backend.backendUsage.needToInitializeDispatchProperty = true; |
| 2883 break; | 2326 break; |
| 2884 case BackendFeature.needToInitializeIsolateAffinityTag: | 2327 case BackendFeature.needToInitializeIsolateAffinityTag: |
| 2885 backend.needToInitializeIsolateAffinityTag = true; | 2328 backend.backendUsage.needToInitializeIsolateAffinityTag = true; |
| 2886 break; | 2329 break; |
| 2887 } | 2330 } |
| 2888 } | 2331 } |
| 2889 } | 2332 } |
| 2890 | 2333 |
| 2891 /// Register [type] as required for the runtime type information system. | 2334 /// Register [type] as required for the runtime type information system. |
| 2892 void registerRequiredType(ResolutionDartType type) { | 2335 void registerRequiredType(ResolutionDartType type) { |
| 2893 if (!type.isInterfaceType) return; | 2336 if (!type.isInterfaceType) return; |
| 2894 // If [argument] has type variables or is a type variable, this method | 2337 // If [argument] has type variables or is a type variable, this method |
| 2895 // registers a RTI dependency between the class where the type variable is | 2338 // registers a RTI dependency between the class where the type variable is |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2944 registerBackendImpact(transformed, impacts.typeCheck); | 2387 registerBackendImpact(transformed, impacts.typeCheck); |
| 2945 | 2388 |
| 2946 bool inCheckedMode = backend.compiler.options.enableTypeAssertions; | 2389 bool inCheckedMode = backend.compiler.options.enableTypeAssertions; |
| 2947 // [registerIsCheck] is also called for checked mode checks, so we | 2390 // [registerIsCheck] is also called for checked mode checks, so we |
| 2948 // need to register checked mode helpers. | 2391 // need to register checked mode helpers. |
| 2949 if (inCheckedMode) { | 2392 if (inCheckedMode) { |
| 2950 // All helpers are added to resolution queue in enqueueHelpers. These | 2393 // All helpers are added to resolution queue in enqueueHelpers. These |
| 2951 // calls to [enqueue] with the resolution enqueuer serve as assertions | 2394 // calls to [enqueue] with the resolution enqueuer serve as assertions |
| 2952 // that the helper was in fact added. | 2395 // that the helper was in fact added. |
| 2953 // TODO(13155): Find a way to enqueue helpers lazily. | 2396 // TODO(13155): Find a way to enqueue helpers lazily. |
| 2954 CheckedModeHelper helper = | 2397 CheckedModeHelper helper = backend.checkedModeHelpers |
| 2955 backend.getCheckedModeHelper(type, typeCast: false); | 2398 .getCheckedModeHelper(type, typeCast: false); |
| 2956 if (helper != null) { | 2399 if (helper != null) { |
| 2957 StaticUse staticUse = helper.getStaticUse(backend.compiler); | 2400 StaticUse staticUse = helper.getStaticUse(backend.helpers); |
| 2958 transformed.registerStaticUse(staticUse); | 2401 transformed.registerStaticUse(staticUse); |
| 2959 backend.registerBackendUse(staticUse.element); | 2402 backend.backendUsage.registerBackendUse(staticUse.element); |
| 2960 } | 2403 } |
| 2961 // We also need the native variant of the check (for DOM types). | 2404 // We also need the native variant of the check (for DOM types). |
| 2962 helper = backend.getNativeCheckedModeHelper(type, typeCast: false); | 2405 helper = backend.checkedModeHelpers |
| 2406 .getNativeCheckedModeHelper(type, typeCast: false); |
| 2963 if (helper != null) { | 2407 if (helper != null) { |
| 2964 StaticUse staticUse = helper.getStaticUse(backend.compiler); | 2408 StaticUse staticUse = helper.getStaticUse(backend.helpers); |
| 2965 transformed.registerStaticUse(staticUse); | 2409 transformed.registerStaticUse(staticUse); |
| 2966 backend.registerBackendUse(staticUse.element); | 2410 backend.backendUsage.registerBackendUse(staticUse.element); |
| 2967 } | 2411 } |
| 2968 } | 2412 } |
| 2969 if (!type.treatAsRaw || type.containsTypeVariables) { | 2413 if (!type.treatAsRaw || type.containsTypeVariables) { |
| 2970 registerBackendImpact(transformed, impacts.genericIsCheck); | 2414 registerBackendImpact(transformed, impacts.genericIsCheck); |
| 2971 } | 2415 } |
| 2972 if (type.element != null && backend.isNative(type.element)) { | 2416 if (type.element != null && backend.isNative(type.element)) { |
| 2973 // We will neeed to add the "$is" and "$as" properties on the | 2417 // We will neeed to add the "$is" and "$as" properties on the |
| 2974 // JavaScript object prototype, so we make sure | 2418 // JavaScript object prototype, so we make sure |
| 2975 // [:defineProperty:] is compiled. | 2419 // [:defineProperty:] is compiled. |
| 2976 registerBackendImpact(transformed, impacts.nativeTypeCheck); | 2420 registerBackendImpact(transformed, impacts.nativeTypeCheck); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3014 break; | 2458 break; |
| 3015 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: | 2459 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: |
| 3016 case StaticUseKind.CONSTRUCTOR_INVOKE: | 2460 case StaticUseKind.CONSTRUCTOR_INVOKE: |
| 3017 backend.lookupMapAnalysis.registerInstantiatedType(staticUse.type); | 2461 backend.lookupMapAnalysis.registerInstantiatedType(staticUse.type); |
| 3018 break; | 2462 break; |
| 3019 default: | 2463 default: |
| 3020 } | 2464 } |
| 3021 } | 2465 } |
| 3022 | 2466 |
| 3023 for (String name in impact.constSymbols) { | 2467 for (String name in impact.constSymbols) { |
| 3024 backend.registerConstSymbol(name); | 2468 backend.mirrorsData.registerConstSymbol(name); |
| 3025 } | 2469 } |
| 3026 | 2470 |
| 3027 for (Set<ClassElement> classes in impact.specializedGetInterceptors) { | 2471 for (Set<ClassElement> classes in impact.specializedGetInterceptors) { |
| 3028 backend.interceptorData | 2472 backend.interceptorData |
| 3029 .registerSpecializedGetInterceptor(classes, backend.namer); | 2473 .registerSpecializedGetInterceptor(classes, backend.namer); |
| 3030 } | 2474 } |
| 3031 | 2475 |
| 3032 if (impact.usesInterceptor) { | 2476 if (impact.usesInterceptor) { |
| 3033 if (backend.codegenEnqueuer.nativeEnqueuer.hasInstantiatedNativeClasses) { | 2477 if (backend.codegenEnqueuer.nativeEnqueuer.hasInstantiatedNativeClasses) { |
| 3034 registerBackendImpact(transformed, impacts.interceptorUse); | 2478 registerBackendImpact(transformed, impacts.interceptorUse); |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3191 } | 2635 } |
| 3192 | 2636 |
| 3193 @override | 2637 @override |
| 3194 FieldEntity get symbolField => helpers.symbolImplementationField; | 2638 FieldEntity get symbolField => helpers.symbolImplementationField; |
| 3195 | 2639 |
| 3196 @override | 2640 @override |
| 3197 InterfaceType get symbolType { | 2641 InterfaceType get symbolType { |
| 3198 return _env.getRawType(helpers.symbolImplementationClass); | 2642 return _env.getRawType(helpers.symbolImplementationClass); |
| 3199 } | 2643 } |
| 3200 } | 2644 } |
| OLD | NEW |