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

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

Issue 2688413003: Extract BackendUsage, MirrorsData, and CheckedModeHelpers from Backend. (Closed)
Patch Set: Cleanup Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/deferred_load.dart ('k') | pkg/compiler/lib/src/js_backend/backend_helpers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698