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

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

Issue 2685573002: Replace Backend with JavaScriptBackend. (Closed)
Patch Set: 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
11 import '../closure.dart'; 11 import '../closure.dart';
12 import '../common.dart'; 12 import '../common.dart';
13 import '../common/backend_api.dart' 13 import '../common/backend_api.dart'
14 show 14 show BackendClasses, ImpactTransformer, ForeignResolver, NativeRegistry;
15 Backend,
16 BackendClasses,
17 ImpactTransformer,
18 ForeignResolver,
19 NativeRegistry;
20 import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem; 15 import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem;
21 import '../common/names.dart' show Identifiers, Uris; 16 import '../common/names.dart' show Identifiers, Uris;
22 import '../common/resolution.dart' show Frontend, Resolution, ResolutionImpact; 17 import '../common/resolution.dart'
18 show Frontend, Resolution, ResolutionImpact, Target;
23 import '../common/tasks.dart' show CompilerTask; 19 import '../common/tasks.dart' show CompilerTask;
24 import '../compiler.dart' show Compiler; 20 import '../compiler.dart' show Compiler;
25 import '../constants/constant_system.dart'; 21 import '../constants/constant_system.dart';
26 import '../constants/expressions.dart'; 22 import '../constants/expressions.dart';
27 import '../constants/values.dart'; 23 import '../constants/values.dart';
28 import '../core_types.dart' show CommonElements; 24 import '../core_types.dart' show CommonElements;
29 import '../deferred_load.dart' show DeferredLoadTask; 25 import '../deferred_load.dart' show DeferredLoadTask;
30 import '../dump_info.dart' show DumpInfoTask; 26 import '../dump_info.dart' show DumpInfoTask;
31 import '../elements/elements.dart'; 27 import '../elements/elements.dart';
32 import '../elements/entities.dart'; 28 import '../elements/entities.dart';
33 import '../elements/resolution_types.dart'; 29 import '../elements/resolution_types.dart';
34 import '../elements/types.dart'; 30 import '../elements/types.dart';
35 import '../enqueue.dart' 31 import '../enqueue.dart'
36 show Enqueuer, ResolutionEnqueuer, TreeShakingEnqueuerStrategy; 32 show Enqueuer, EnqueueTask, ResolutionEnqueuer, TreeShakingEnqueuerStrategy;
37 import '../io/position_information.dart' show PositionSourceInformationStrategy; 33 import '../io/position_information.dart' show PositionSourceInformationStrategy;
38 import '../io/source_information.dart' show SourceInformationStrategy; 34 import '../io/source_information.dart' show SourceInformationStrategy;
39 import '../io/start_end_information.dart' 35 import '../io/start_end_information.dart'
40 show StartEndSourceInformationStrategy; 36 show StartEndSourceInformationStrategy;
41 import '../js/js.dart' as jsAst; 37 import '../js/js.dart' as jsAst;
42 import '../js/js.dart' show js; 38 import '../js/js.dart' show js;
43 import '../js/js_source_mapping.dart' show JavaScriptSourceInformationStrategy; 39 import '../js/js_source_mapping.dart' show JavaScriptSourceInformationStrategy;
44 import '../js/rewrite_async.dart'; 40 import '../js/rewrite_async.dart';
45 import '../js_emitter/js_emitter.dart' show CodeEmitterTask; 41 import '../js_emitter/js_emitter.dart' show CodeEmitterTask;
46 import '../library_loader.dart' show LibraryLoader, LoadedLibraries; 42 import '../library_loader.dart' show LibraryLoader, LoadedLibraries;
47 import '../native/native.dart' as native; 43 import '../native/native.dart' as native;
44 import '../patch_parser.dart'
45 show checkNativeAnnotation, checkJsInteropAnnotation;
48 import '../ssa/ssa.dart' show SsaFunctionCompiler; 46 import '../ssa/ssa.dart' show SsaFunctionCompiler;
49 import '../tracer.dart'; 47 import '../tracer.dart';
50 import '../tree/tree.dart'; 48 import '../tree/tree.dart';
51 import '../types/types.dart'; 49 import '../types/types.dart';
52 import '../universe/call_structure.dart' show CallStructure; 50 import '../universe/call_structure.dart' show CallStructure;
53 import '../universe/feature.dart'; 51 import '../universe/feature.dart';
54 import '../universe/selector.dart' show Selector; 52 import '../universe/selector.dart' show Selector;
55 import '../universe/world_builder.dart'; 53 import '../universe/world_builder.dart';
56 import '../universe/use.dart' 54 import '../universe/use.dart'
57 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; 55 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind;
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 } 295 }
298 } 296 }
299 297
300 enum SyntheticConstantKind { 298 enum SyntheticConstantKind {
301 DUMMY_INTERCEPTOR, 299 DUMMY_INTERCEPTOR,
302 EMPTY_VALUE, 300 EMPTY_VALUE,
303 TYPEVARIABLE_REFERENCE, // Reference to a type in reflection data. 301 TYPEVARIABLE_REFERENCE, // Reference to a type in reflection data.
304 NAME 302 NAME
305 } 303 }
306 304
307 class JavaScriptBackend extends Backend { 305 class JavaScriptBackend extends Target {
306 final Compiler compiler;
307
308 String get patchVersion => emitter.patchVersion; 308 String get patchVersion => emitter.patchVersion;
309 309
310 /// Returns true if the backend supports reflection.
310 bool get supportsReflection => emitter.supportsReflection; 311 bool get supportsReflection => emitter.supportsReflection;
311 312
312 final Annotations annotations; 313 final Annotations annotations;
313 314
314 /// Set of classes that need to be considered for reflection although not 315 /// Set of classes that need to be considered for reflection although not
315 /// otherwise visible during resolution. 316 /// otherwise visible during resolution.
316 Iterable<ClassElement> get classesRequiredForReflection { 317 Iterable<ClassElement> get classesRequiredForReflection {
317 // TODO(herhut): Clean this up when classes needed for rti are tracked. 318 // TODO(herhut): Clean this up when classes needed for rti are tracked.
318 return [helpers.closureClass, helpers.jsIndexableClass]; 319 return [helpers.closureClass, helpers.jsIndexableClass];
319 } 320 }
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 524
524 /// Support for classifying `noSuchMethod` implementations. 525 /// Support for classifying `noSuchMethod` implementations.
525 NoSuchMethodRegistry noSuchMethodRegistry; 526 NoSuchMethodRegistry noSuchMethodRegistry;
526 527
527 /// Resolution and codegen support for computing reflectable elements. 528 /// Resolution and codegen support for computing reflectable elements.
528 MirrorsAnalysis mirrorsAnalysis; 529 MirrorsAnalysis mirrorsAnalysis;
529 530
530 /// Builds kernel representation for the program. 531 /// Builds kernel representation for the program.
531 KernelTask kernelTask; 532 KernelTask kernelTask;
532 533
534 /// The compiler task responsible for the compilation of constants for both
535 /// the frontend and the backend.
533 JavaScriptConstantTask constantCompilerTask; 536 JavaScriptConstantTask constantCompilerTask;
534 537
538 /// Backend transformation methods for the world impacts.
535 JavaScriptImpactTransformer impactTransformer; 539 JavaScriptImpactTransformer impactTransformer;
536 540
537 PatchResolverTask patchResolverTask; 541 PatchResolverTask patchResolverTask;
538 542
543 /// Whether or not `noSuchMethod` support has been enabled.
539 bool enabledNoSuchMethod = false; 544 bool enabledNoSuchMethod = false;
540 bool _noSuchMethodEnabledForCodegen = false; 545 bool _noSuchMethodEnabledForCodegen = false;
541 546
547 /// The strategy used for collecting and emitting source information.
542 SourceInformationStrategy sourceInformationStrategy; 548 SourceInformationStrategy sourceInformationStrategy;
543 549
550 /// Interface for serialization of backend specific data.
544 JavaScriptBackendSerialization serialization; 551 JavaScriptBackendSerialization serialization;
545 552
546 StagedWorldImpactBuilder constantImpactsForResolution = 553 StagedWorldImpactBuilder constantImpactsForResolution =
547 new StagedWorldImpactBuilder(); 554 new StagedWorldImpactBuilder();
548 555
549 StagedWorldImpactBuilder constantImpactsForCodegen = 556 StagedWorldImpactBuilder constantImpactsForCodegen =
550 new StagedWorldImpactBuilder(); 557 new StagedWorldImpactBuilder();
551 558
552 final NativeData nativeData = new NativeData(); 559 final NativeData nativeData = new NativeData();
553 560
554 BackendHelpers helpers; 561 BackendHelpers helpers;
555 final BackendImpacts impacts; 562 final BackendImpacts impacts;
563
564 /// Common classes used by the backend.
556 BackendClasses backendClasses; 565 BackendClasses backendClasses;
557 566
567 /// Backend access to the front-end.
558 final JSFrontendAccess frontend; 568 final JSFrontendAccess frontend;
559 569
560 Tracer tracer; 570 Tracer tracer;
561 571
562 JavaScriptBackend(Compiler compiler, 572 JavaScriptBackend(Compiler compiler,
563 {bool generateSourceMap: true, 573 {bool generateSourceMap: true,
564 bool useStartupEmitter: false, 574 bool useStartupEmitter: false,
565 bool useNewSourceInfo: false, 575 bool useNewSourceInfo: false,
566 bool useKernel: false}) 576 bool useKernel: false})
567 : oneShotInterceptors = new Map<jsAst.Name, Selector>(), 577 : oneShotInterceptors = new Map<jsAst.Name, Selector>(),
568 interceptedElements = new Map<String, Set<Element>>(), 578 interceptedElements = new Map<String, Set<Element>>(),
569 rti = new _RuntimeTypes(compiler), 579 rti = new _RuntimeTypes(compiler),
570 rtiEncoder = new _RuntimeTypesEncoder(compiler), 580 rtiEncoder = new _RuntimeTypesEncoder(compiler),
571 specializedGetInterceptors = new Map<jsAst.Name, Set<ClassElement>>(), 581 specializedGetInterceptors = new Map<jsAst.Name, Set<ClassElement>>(),
572 annotations = new Annotations(compiler), 582 annotations = new Annotations(compiler),
573 this.sourceInformationStrategy = generateSourceMap 583 this.sourceInformationStrategy = generateSourceMap
574 ? (useNewSourceInfo 584 ? (useNewSourceInfo
575 ? new PositionSourceInformationStrategy() 585 ? new PositionSourceInformationStrategy()
576 : const StartEndSourceInformationStrategy()) 586 : const StartEndSourceInformationStrategy())
577 : const JavaScriptSourceInformationStrategy(), 587 : const JavaScriptSourceInformationStrategy(),
578 impacts = new BackendImpacts(compiler), 588 impacts = new BackendImpacts(compiler),
579 frontend = new JSFrontendAccess(compiler), 589 frontend = new JSFrontendAccess(compiler),
580 super(compiler) { 590 this.compiler = compiler {
581 helpers = 591 helpers =
582 new BackendHelpers(compiler.elementEnvironment, this, commonElements); 592 new BackendHelpers(compiler.elementEnvironment, this, commonElements);
583 emitter = 593 emitter =
584 new CodeEmitterTask(compiler, generateSourceMap, useStartupEmitter); 594 new CodeEmitterTask(compiler, generateSourceMap, useStartupEmitter);
585 typeVariableHandler = new TypeVariableHandler(compiler); 595 typeVariableHandler = new TypeVariableHandler(compiler);
586 customElementsAnalysis = new CustomElementsAnalysis(this); 596 customElementsAnalysis = new CustomElementsAnalysis(this);
587 lookupMapAnalysis = new LookupMapAnalysis(this, reporter); 597 lookupMapAnalysis = new LookupMapAnalysis(this, reporter);
588 jsInteropAnalysis = new JsInteropAnalysis(this); 598 jsInteropAnalysis = new JsInteropAnalysis(this);
589 mirrorsAnalysis = new MirrorsAnalysis(this, compiler.resolution); 599 mirrorsAnalysis = new MirrorsAnalysis(this, compiler.resolution);
590 600
591 noSuchMethodRegistry = new NoSuchMethodRegistry(this); 601 noSuchMethodRegistry = new NoSuchMethodRegistry(this);
592 kernelTask = new KernelTask(compiler); 602 kernelTask = new KernelTask(compiler);
593 constantCompilerTask = new JavaScriptConstantTask(compiler); 603 constantCompilerTask = new JavaScriptConstantTask(compiler);
594 impactTransformer = new JavaScriptImpactTransformer(this); 604 impactTransformer = new JavaScriptImpactTransformer(this);
595 patchResolverTask = new PatchResolverTask(compiler); 605 patchResolverTask = new PatchResolverTask(compiler);
596 functionCompiler = 606 functionCompiler =
597 new SsaFunctionCompiler(this, sourceInformationStrategy, useKernel); 607 new SsaFunctionCompiler(this, sourceInformationStrategy, useKernel);
598 serialization = new JavaScriptBackendSerialization(this); 608 serialization = new JavaScriptBackendSerialization(this);
599 backendClasses = new JavaScriptBackendClasses(helpers); 609 backendClasses = new JavaScriptBackendClasses(helpers);
600 } 610 }
601 611
612 /// The [ConstantSystem] used to interpret compile-time constants for this
613 /// backend.
602 ConstantSystem get constantSystem => constants.constantSystem; 614 ConstantSystem get constantSystem => constants.constantSystem;
603 615
604 DiagnosticReporter get reporter => compiler.reporter; 616 DiagnosticReporter get reporter => compiler.reporter;
605 617
606 CommonElements get commonElements => compiler.commonElements; 618 CommonElements get commonElements => compiler.commonElements;
607 619
608 Resolution get resolution => compiler.resolution; 620 Resolution get resolution => compiler.resolution;
609 621
610 /// Returns constant environment for the JavaScript interpretation of the 622 /// Returns constant environment for the JavaScript interpretation of the
611 /// constants. 623 /// constants.
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
668 // add both to the list of helpers. 680 // add both to the list of helpers.
669 helpersUsed.add(element.implementation); 681 helpersUsed.add(element.implementation);
670 } 682 }
671 return element; 683 return element;
672 } 684 }
673 685
674 bool _isValidBackendUse(Element element) { 686 bool _isValidBackendUse(Element element) {
675 assert(invariant(element, element.isDeclaration, message: "")); 687 assert(invariant(element, element.isDeclaration, message: ""));
676 if (element is ConstructorElement && 688 if (element is ConstructorElement &&
677 (element == helpers.streamIteratorConstructor || 689 (element == helpers.streamIteratorConstructor ||
678 compiler.commonElements.isSymbolConstructor(element) || 690 compiler.commonElements.isSymbolConstructor(element) ||
679 helpers.isSymbolValidatedConstructor(element) || 691 helpers.isSymbolValidatedConstructor(element) ||
680 element == helpers.syncCompleterConstructor)) { 692 element == helpers.syncCompleterConstructor)) {
681 // TODO(johnniwinther): These are valid but we could be more precise. 693 // TODO(johnniwinther): These are valid but we could be more precise.
682 return true; 694 return true;
683 } else if (element == commonElements.symbolClass || 695 } else if (element == commonElements.symbolClass ||
684 element == helpers.objectNoSuchMethod) { 696 element == helpers.objectNoSuchMethod) {
685 // TODO(johnniwinther): These are valid but we could be more precise. 697 // TODO(johnniwinther): These are valid but we could be more precise.
686 return true; 698 return true;
687 } else if (element.implementationLibrary.isPatch || 699 } else if (element.implementationLibrary.isPatch ||
688 // Needed to detect deserialized injected elements, that is 700 // Needed to detect deserialized injected elements, that is
689 // element declared in patch files. 701 // element declared in patch files.
690 (element.library.isPlatformLibrary && 702 (element.library.isPlatformLibrary &&
691 element.sourcePosition.uri.path 703 element.sourcePosition.uri.path
692 .contains('_internal/js_runtime/lib/')) || 704 .contains('_internal/js_runtime/lib/')) ||
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 if (element.isField) { 739 if (element.isField) {
728 if (Elements.isStaticOrTopLevel(element) && 740 if (Elements.isStaticOrTopLevel(element) &&
729 (element.isFinal || element.isConst)) { 741 (element.isFinal || element.isConst)) {
730 return false; 742 return false;
731 } 743 }
732 } 744 }
733 745
734 return isAccessibleByReflection(element.declaration); 746 return isAccessibleByReflection(element.declaration);
735 } 747 }
736 748
749 /// Returns true if global optimizations such as type inferencing
750 /// can apply to this element. One category of elements that do not
751 /// apply is runtime helpers that the backend calls, but the
752 /// optimizations don't see those calls.
737 bool canBeUsedForGlobalOptimizations(Element element) { 753 bool canBeUsedForGlobalOptimizations(Element element) {
738 return !usedByBackend(element) && !invokedReflectively(element); 754 return !usedByBackend(element) && !invokedReflectively(element);
739 } 755 }
740 756
741 bool isInterceptorClass(ClassElement element) { 757 bool isInterceptorClass(ClassElement element) {
742 if (element == null) return false; 758 if (element == null) return false;
743 if (isNativeOrExtendsNative(element)) return true; 759 if (isNativeOrExtendsNative(element)) return true;
744 if (interceptedClasses.contains(element)) return true; 760 if (interceptedClasses.contains(element)) return true;
745 if (classesMixedIntoInterceptedClasses.contains(element)) return true; 761 if (classesMixedIntoInterceptedClasses.contains(element)) return true;
746 return false; 762 return false;
(...skipping 27 matching lines...) Expand all
774 return !selector.isGetter; 790 return !selector.isGetter;
775 } 791 }
776 792
777 /** 793 /**
778 * Returns `true` if [member] is called from a subclass via `super`. 794 * Returns `true` if [member] is called from a subclass via `super`.
779 */ 795 */
780 bool isAliasedSuperMember(FunctionElement member) { 796 bool isAliasedSuperMember(FunctionElement member) {
781 return aliasedSuperMembers.contains(member); 797 return aliasedSuperMembers.contains(member);
782 } 798 }
783 799
784 /// Returns `true` if [element] is part of JsInterop. 800 /// Returns `true` if [element] is implemented via typed JavaScript interop.
785 @override 801 @override
786 bool isJsInterop(Element element) => nativeData.isJsInterop(element); 802 bool isJsInterop(Element element) => nativeData.isJsInterop(element);
787 803
788 /// Returns `true` if [element] is a JsInterop class. 804 /// Returns `true` if [element] is a JsInterop class.
789 bool isJsInteropClass(ClassElement element) => isJsInterop(element); 805 bool isJsInteropClass(ClassElement element) => isJsInterop(element);
790 806
791 /// Returns `true` if [element] is a JsInterop method. 807 /// Returns `true` if [element] is a JsInterop method.
792 bool isJsInteropMethod(MethodElement element) => isJsInterop(element); 808 bool isJsInteropMethod(MethodElement element) => isJsInterop(element);
793 809
794 /// Whether [element] corresponds to a native JavaScript construct either 810 /// Whether [element] corresponds to a native JavaScript construct either
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
1049 jsAst.Name name = namer.nameForGetInterceptor(classes); 1065 jsAst.Name name = namer.nameForGetInterceptor(classes);
1050 if (classes.contains(helpers.jsInterceptorClass)) { 1066 if (classes.contains(helpers.jsInterceptorClass)) {
1051 // We can't use a specialized [getInterceptorMethod], so we make 1067 // We can't use a specialized [getInterceptorMethod], so we make
1052 // sure we emit the one with all checks. 1068 // sure we emit the one with all checks.
1053 specializedGetInterceptors[name] = interceptedClasses; 1069 specializedGetInterceptors[name] = interceptedClasses;
1054 } else { 1070 } else {
1055 specializedGetInterceptors[name] = classes; 1071 specializedGetInterceptors[name] = classes;
1056 } 1072 }
1057 } 1073 }
1058 1074
1075 /// Called during codegen when [constant] has been used.
1059 void computeImpactForCompileTimeConstant(ConstantValue constant, 1076 void computeImpactForCompileTimeConstant(ConstantValue constant,
1060 WorldImpactBuilder impactBuilder, bool isForResolution) { 1077 WorldImpactBuilder impactBuilder, bool isForResolution) {
1061 computeImpactForCompileTimeConstantInternal( 1078 computeImpactForCompileTimeConstantInternal(
1062 constant, impactBuilder, isForResolution); 1079 constant, impactBuilder, isForResolution);
1063 1080
1064 if (!isForResolution && lookupMapAnalysis.isLookupMap(constant)) { 1081 if (!isForResolution && lookupMapAnalysis.isLookupMap(constant)) {
1065 // Note: internally, this registration will temporarily remove the 1082 // Note: internally, this registration will temporarily remove the
1066 // constant dependencies and add them later on-demand. 1083 // constant dependencies and add them later on-demand.
1067 lookupMapAnalysis.registerLookupMapReference(constant); 1084 lookupMapAnalysis.registerLookupMapReference(constant);
1068 } 1085 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1121 // constant emitter will generate a call to the createRuntimeType 1138 // constant emitter will generate a call to the createRuntimeType
1122 // helper so we register a use of that. 1139 // helper so we register a use of that.
1123 impactBuilder.registerStaticUse(new StaticUse.staticInvoke( 1140 impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
1124 // TODO(johnniwinther): Find the right [CallStructure]. 1141 // TODO(johnniwinther): Find the right [CallStructure].
1125 helpers.createRuntimeType, 1142 helpers.createRuntimeType,
1126 null)); 1143 null));
1127 } 1144 }
1128 } 1145 }
1129 } 1146 }
1130 1147
1148 /// Called to notify to the backend that a class is being instantiated. Any
1149 /// backend specific [WorldImpact] of this is returned.
1131 WorldImpact registerInstantiatedClass(ClassElement cls, 1150 WorldImpact registerInstantiatedClass(ClassElement cls,
1132 {bool forResolution}) { 1151 {bool forResolution}) {
1133 return _processClass(cls, forResolution: forResolution); 1152 return _processClass(cls, forResolution: forResolution);
1134 } 1153 }
1135 1154
1155 /// Called to notify to the backend that a class is implemented by an
1156 /// instantiated class. Any backend specific [WorldImpact] of this is
1157 /// returned.
1136 WorldImpact registerImplementedClass(ClassElement cls, {bool forResolution}) { 1158 WorldImpact registerImplementedClass(ClassElement cls, {bool forResolution}) {
1137 return _processClass(cls, forResolution: forResolution); 1159 return _processClass(cls, forResolution: forResolution);
1138 } 1160 }
1139 1161
1140 WorldImpact _processClass(ClassElement cls, {bool forResolution}) { 1162 WorldImpact _processClass(ClassElement cls, {bool forResolution}) {
1141 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl(); 1163 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
1142 if (!cls.typeVariables.isEmpty) { 1164 if (!cls.typeVariables.isEmpty) {
1143 typeVariableHandler.registerClassWithTypeVariables(cls, 1165 typeVariableHandler.registerClassWithTypeVariables(cls,
1144 forResolution: forResolution); 1166 forResolution: forResolution);
1145 } 1167 }
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
1258 1280
1259 customElementsAnalysis.registerInstantiatedClass(cls, 1281 customElementsAnalysis.registerInstantiatedClass(cls,
1260 forResolution: forResolution); 1282 forResolution: forResolution);
1261 if (!forResolution) { 1283 if (!forResolution) {
1262 lookupMapAnalysis.registerInstantiatedClass(cls); 1284 lookupMapAnalysis.registerInstantiatedClass(cls);
1263 } 1285 }
1264 1286
1265 return impactBuilder; 1287 return impactBuilder;
1266 } 1288 }
1267 1289
1290 /// Called to instruct to the backend register [type] as instantiated on
1291 /// [enqueuer].
1268 void registerInstantiatedType(ResolutionInterfaceType type) { 1292 void registerInstantiatedType(ResolutionInterfaceType type) {
1269 lookupMapAnalysis.registerInstantiatedType(type); 1293 lookupMapAnalysis.registerInstantiatedType(type);
1270 } 1294 }
1271 1295
1272 @override 1296 /// Compute the [WorldImpact] for backend helper methods.
1273 WorldImpact computeHelpersImpact() { 1297 WorldImpact computeHelpersImpact() {
1274 assert(helpers.interceptorsLibrary != null); 1298 assert(helpers.interceptorsLibrary != null);
1275 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl(); 1299 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
1276 // TODO(ngeoffray): Not enqueuing those two classes currently make 1300 // TODO(ngeoffray): Not enqueuing those two classes currently make
1277 // the compiler potentially crash. However, any reasonable program 1301 // the compiler potentially crash. However, any reasonable program
1278 // will instantiate those two classes. 1302 // will instantiate those two classes.
1279 addInterceptors(helpers.jsBoolClass, impactBuilder, forResolution: true); 1303 addInterceptors(helpers.jsBoolClass, impactBuilder, forResolution: true);
1280 addInterceptors(helpers.jsNullClass, impactBuilder, forResolution: true); 1304 addInterceptors(helpers.jsNullClass, impactBuilder, forResolution: true);
1281 if (compiler.options.enableTypeAssertions) { 1305 if (compiler.options.enableTypeAssertions) {
1282 impactTransformer.registerBackendImpact( 1306 impactTransformer.registerBackendImpact(
1283 impactBuilder, impacts.enableTypeAssertions); 1307 impactBuilder, impacts.enableTypeAssertions);
1284 } 1308 }
1285 1309
1286 if (TRACE_CALLS) { 1310 if (TRACE_CALLS) {
1287 impactTransformer.registerBackendImpact( 1311 impactTransformer.registerBackendImpact(
1288 impactBuilder, impacts.traceHelper); 1312 impactBuilder, impacts.traceHelper);
1289 } 1313 }
1290 impactTransformer.registerBackendImpact( 1314 impactTransformer.registerBackendImpact(
1291 impactBuilder, impacts.assertUnreachable); 1315 impactBuilder, impacts.assertUnreachable);
1292 _registerCheckedModeHelpers(impactBuilder); 1316 _registerCheckedModeHelpers(impactBuilder);
1293 return impactBuilder; 1317 return impactBuilder;
1294 } 1318 }
1295 1319
1296 onResolutionComplete( 1320 void onResolutionComplete(
1297 ClosedWorld closedWorld, ClosedWorldRefiner closedWorldRefiner) { 1321 ClosedWorld closedWorld, ClosedWorldRefiner closedWorldRefiner) {
1298 for (Entity entity in compiler.enqueuer.resolution.processedEntities) { 1322 for (Entity entity in compiler.enqueuer.resolution.processedEntities) {
1299 processAnnotations(entity, closedWorldRefiner); 1323 processAnnotations(entity, closedWorldRefiner);
1300 } 1324 }
1301 computeMembersNeededForReflection(closedWorld); 1325 computeMembersNeededForReflection(closedWorld);
1302 rti.computeClassesNeedingRti( 1326 rti.computeClassesNeedingRti(
1303 compiler.enqueuer.resolution.worldBuilder, closedWorld); 1327 compiler.enqueuer.resolution.worldBuilder, closedWorld);
1304 _registeredMetadata.clear(); 1328 _registeredMetadata.clear();
1305 } 1329 }
1306 1330
1307 onTypeInferenceComplete() { 1331 void onTypeInferenceComplete() {
1308 super.onTypeInferenceComplete();
1309 noSuchMethodRegistry.onTypeInferenceComplete(); 1332 noSuchMethodRegistry.onTypeInferenceComplete();
1310 } 1333 }
1311 1334
1312 /// Called to register that an instantiated generic class has a call method. 1335 /// Called to register that an instantiated generic class has a call method.
1313 /// Any backend specific [WorldImpact] of this is returned. 1336 /// Any backend specific [WorldImpact] of this is returned.
1314 /// 1337 ///
1315 /// Note: The [callMethod] is registered even thought it doesn't reference 1338 /// Note: The [callMethod] is registered even thought it doesn't reference
1316 /// the type variables. 1339 /// the type variables.
1317 WorldImpact registerCallMethodWithFreeTypeVariables(Element callMethod, 1340 WorldImpact registerCallMethodWithFreeTypeVariables(Element callMethod,
1318 {bool forResolution}) { 1341 {bool forResolution}) {
1319 if (forResolution || methodNeedsRti(callMethod)) { 1342 if (forResolution || methodNeedsRti(callMethod)) {
1320 return _registerComputeSignature(); 1343 return _registerComputeSignature();
1321 } 1344 }
1322 return const WorldImpact(); 1345 return const WorldImpact();
1323 } 1346 }
1324 1347
1348 /// Called to instruct the backend to register that a closure exists for a
1349 /// function on an instantiated generic class. Any backend specific
1350 /// [WorldImpact] of this is returned.
1325 WorldImpact registerClosureWithFreeTypeVariables(Element closure, 1351 WorldImpact registerClosureWithFreeTypeVariables(Element closure,
1326 {bool forResolution}) { 1352 {bool forResolution}) {
1327 if (forResolution || methodNeedsRti(closure)) { 1353 if (forResolution || methodNeedsRti(closure)) {
1328 return _registerComputeSignature(); 1354 return _registerComputeSignature();
1329 } 1355 }
1330 return const WorldImpact(); 1356 return const WorldImpact();
1331 } 1357 }
1332 1358
1359 /// Called to register that a member has been closurized. Any backend specific
1360 /// [WorldImpact] of this is returned.
1333 WorldImpact registerBoundClosure() { 1361 WorldImpact registerBoundClosure() {
1334 return impactTransformer.createImpactFor(impacts.memberClosure); 1362 return impactTransformer.createImpactFor(impacts.memberClosure);
1335 } 1363 }
1336 1364
1365 /// Called to register that a static function has been closurized. Any backend
1366 /// specific [WorldImpact] of this is returned.
1337 WorldImpact registerGetOfStaticFunction() { 1367 WorldImpact registerGetOfStaticFunction() {
1338 return impactTransformer.createImpactFor(impacts.staticClosure); 1368 return impactTransformer.createImpactFor(impacts.staticClosure);
1339 } 1369 }
1340 1370
1341 WorldImpact _registerComputeSignature() { 1371 WorldImpact _registerComputeSignature() {
1342 return impactTransformer.createImpactFor(impacts.computeSignature); 1372 return impactTransformer.createImpactFor(impacts.computeSignature);
1343 } 1373 }
1344 1374
1345 /// Called to register that the `runtimeType` property has been accessed. Any 1375 /// Called to register that the `runtimeType` property has been accessed. Any
1346 /// backend specific [WorldImpact] of this is returned. 1376 /// backend specific [WorldImpact] of this is returned.
1347 WorldImpact registerRuntimeType() { 1377 WorldImpact registerRuntimeType() {
1348 return impactTransformer.createImpactFor(impacts.runtimeTypeSupport); 1378 return impactTransformer.createImpactFor(impacts.runtimeTypeSupport);
1349 } 1379 }
1350 1380
1381 /// Register a runtime type variable bound tests between [typeArgument] and
1382 /// [bound].
1351 void registerTypeVariableBoundsSubtypeCheck( 1383 void registerTypeVariableBoundsSubtypeCheck(
1352 ResolutionDartType typeArgument, ResolutionDartType bound) { 1384 ResolutionDartType typeArgument, ResolutionDartType bound) {
1353 rti.registerTypeVariableBoundsSubtypeCheck(typeArgument, bound); 1385 rti.registerTypeVariableBoundsSubtypeCheck(typeArgument, bound);
1354 } 1386 }
1355 1387
1388 /// Returns the [WorldImpact] of enabling deferred loading.
1356 WorldImpact computeDeferredLoadingImpact() { 1389 WorldImpact computeDeferredLoadingImpact() {
1357 return impactTransformer.createImpactFor(impacts.deferredLoading); 1390 return impactTransformer.createImpactFor(impacts.deferredLoading);
1358 } 1391 }
1359 1392
1360 /// Called to register a `noSuchMethod` implementation. 1393 /// Called to register a `noSuchMethod` implementation.
1361 void registerNoSuchMethod(MethodElement noSuchMethod) { 1394 void registerNoSuchMethod(MethodElement noSuchMethod) {
1362 noSuchMethodRegistry.registerNoSuchMethod(noSuchMethod); 1395 noSuchMethodRegistry.registerNoSuchMethod(noSuchMethod);
1363 } 1396 }
1364 1397
1365 /// Called when resolving a call to a foreign function. 1398 /// Called when resolving a call to a foreign function.
(...skipping 27 matching lines...) Expand all
1393 node, MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); 1426 node, MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
1394 } 1427 }
1395 // No native behavior for this call. 1428 // No native behavior for this call.
1396 return null; 1429 return null;
1397 } 1430 }
1398 1431
1399 WorldImpact computeNoSuchMethodImpact() { 1432 WorldImpact computeNoSuchMethodImpact() {
1400 return impactTransformer.createImpactFor(impacts.noSuchMethodSupport); 1433 return impactTransformer.createImpactFor(impacts.noSuchMethodSupport);
1401 } 1434 }
1402 1435
1436 /// Called to enable support for isolates. Any backend specific [WorldImpact]
1437 /// of this is returned.
1403 WorldImpact enableIsolateSupport({bool forResolution}) { 1438 WorldImpact enableIsolateSupport({bool forResolution}) {
1404 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl(); 1439 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
1405 // TODO(floitsch): We should also ensure that the class IsolateMessage is 1440 // TODO(floitsch): We should also ensure that the class IsolateMessage is
1406 // instantiated. Currently, just enabling isolate support works. 1441 // instantiated. Currently, just enabling isolate support works.
1407 if (compiler.mainFunction != null) { 1442 if (compiler.mainFunction != null) {
1408 // The JavaScript backend implements [Isolate.spawn] by looking up 1443 // The JavaScript backend implements [Isolate.spawn] by looking up
1409 // top-level functions by name. So all top-level function tear-off 1444 // top-level functions by name. So all top-level function tear-off
1410 // closures have a private name field. 1445 // closures have a private name field.
1411 // 1446 //
1412 // The JavaScript backend of [Isolate.spawnUri] uses the same internal 1447 // The JavaScript backend of [Isolate.spawnUri] uses the same internal
(...skipping 24 matching lines...) Expand all
1437 1472
1438 bool isComplexNoSuchMethod(FunctionElement element) => 1473 bool isComplexNoSuchMethod(FunctionElement element) =>
1439 noSuchMethodRegistry.isComplex(element); 1474 noSuchMethodRegistry.isComplex(element);
1440 1475
1441 bool methodNeedsRti(FunctionElement function) { 1476 bool methodNeedsRti(FunctionElement function) {
1442 return rti.methodsNeedingRti.contains(function) || hasRuntimeTypeSupport; 1477 return rti.methodsNeedingRti.contains(function) || hasRuntimeTypeSupport;
1443 } 1478 }
1444 1479
1445 CodegenEnqueuer get codegenEnqueuer => compiler.enqueuer.codegen; 1480 CodegenEnqueuer get codegenEnqueuer => compiler.enqueuer.codegen;
1446 1481
1482 /// Creates an [Enqueuer] for code generation specific to this backend.
1447 CodegenEnqueuer createCodegenEnqueuer(CompilerTask task, Compiler compiler) { 1483 CodegenEnqueuer createCodegenEnqueuer(CompilerTask task, Compiler compiler) {
1448 return new CodegenEnqueuer( 1484 return new CodegenEnqueuer(
1449 task, this, compiler.options, const TreeShakingEnqueuerStrategy()); 1485 task, this, compiler.options, const TreeShakingEnqueuerStrategy());
1450 } 1486 }
1451 1487
1452 WorldImpact codegen(CodegenWorkItem work) { 1488 WorldImpact codegen(CodegenWorkItem work) {
1453 Element element = work.element; 1489 Element element = work.element;
1454 if (compiler.elementHasCompileTimeError(element)) { 1490 if (compiler.elementHasCompileTimeError(element)) {
1455 DiagnosticMessage message = 1491 DiagnosticMessage message =
1456 // If there's more than one error, the first is probably most 1492 // If there's more than one error, the first is probably most
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1541 /** 1577 /**
1542 * Unit test hook that returns code of an element as a String. 1578 * Unit test hook that returns code of an element as a String.
1543 * 1579 *
1544 * Invariant: [element] must be a declaration element. 1580 * Invariant: [element] must be a declaration element.
1545 */ 1581 */
1546 String getGeneratedCode(Element element) { 1582 String getGeneratedCode(Element element) {
1547 assert(invariant(element, element.isDeclaration)); 1583 assert(invariant(element, element.isDeclaration));
1548 return jsAst.prettyPrint(generatedCode[element], compiler); 1584 return jsAst.prettyPrint(generatedCode[element], compiler);
1549 } 1585 }
1550 1586
1587 /// Generates the output and returns the total size of the generated code.
1551 int assembleProgram(ClosedWorld closedWorld) { 1588 int assembleProgram(ClosedWorld closedWorld) {
1552 int programSize = emitter.assembleProgram(namer, closedWorld); 1589 int programSize = emitter.assembleProgram(namer, closedWorld);
1553 noSuchMethodRegistry.emitDiagnostic(); 1590 noSuchMethodRegistry.emitDiagnostic();
1554 int totalMethodCount = generatedCode.length; 1591 int totalMethodCount = generatedCode.length;
1555 if (totalMethodCount != preMirrorsMethodCount) { 1592 if (totalMethodCount != preMirrorsMethodCount) {
1556 int mirrorCount = totalMethodCount - preMirrorsMethodCount; 1593 int mirrorCount = totalMethodCount - preMirrorsMethodCount;
1557 double percentage = (mirrorCount / totalMethodCount) * 100; 1594 double percentage = (mirrorCount / totalMethodCount) * 100;
1558 DiagnosticMessage hint = 1595 DiagnosticMessage hint =
1559 reporter.createMessage(compiler.mainApp, MessageKind.MIRROR_BLOAT, { 1596 reporter.createMessage(compiler.mainApp, MessageKind.MIRROR_BLOAT, {
1560 'count': mirrorCount, 1597 'count': mirrorCount,
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
1762 bool mayGenerateInstanceofCheck(ResolutionDartType type) { 1799 bool mayGenerateInstanceofCheck(ResolutionDartType type) {
1763 // We can use an instanceof check for raw types that have no subclass that 1800 // We can use an instanceof check for raw types that have no subclass that
1764 // is mixed-in or in an implements clause. 1801 // is mixed-in or in an implements clause.
1765 1802
1766 if (!type.isRaw) return false; 1803 if (!type.isRaw) return false;
1767 ClassElement classElement = type.element; 1804 ClassElement classElement = type.element;
1768 if (isInterceptorClass(classElement)) return false; 1805 if (isInterceptorClass(classElement)) return false;
1769 return _closedWorld.hasOnlySubclasses(classElement); 1806 return _closedWorld.hasOnlySubclasses(classElement);
1770 } 1807 }
1771 1808
1809 /// Called to register that [element] is statically known to be used. Any
1810 /// backend specific [WorldImpact] of this is returned.
1772 WorldImpact registerUsedElement(MemberElement element, {bool forResolution}) { 1811 WorldImpact registerUsedElement(MemberElement element, {bool forResolution}) {
1773 WorldImpactBuilderImpl worldImpact = new WorldImpactBuilderImpl(); 1812 WorldImpactBuilderImpl worldImpact = new WorldImpactBuilderImpl();
1774 if (element == helpers.disableTreeShakingMarker) { 1813 if (element == helpers.disableTreeShakingMarker) {
1775 isTreeShakingDisabled = true; 1814 isTreeShakingDisabled = true;
1776 } else if (element == helpers.preserveNamesMarker) { 1815 } else if (element == helpers.preserveNamesMarker) {
1777 mustPreserveNames = true; 1816 mustPreserveNames = true;
1778 } else if (element == helpers.preserveMetadataMarker) { 1817 } else if (element == helpers.preserveMetadataMarker) {
1779 mustRetainMetadata = true; 1818 mustRetainMetadata = true;
1780 } else if (element == helpers.preserveUrisMarker) { 1819 } else if (element == helpers.preserveUrisMarker) {
1781 if (compiler.options.preserveUris) mustPreserveUris = true; 1820 if (compiler.options.preserveUris) mustPreserveUris = true;
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1885 metadata.ensureResolved(resolution); 1924 metadata.ensureResolved(resolution);
1886 ConstantValue constant = 1925 ConstantValue constant =
1887 constants.getConstantValueForMetadata(metadata); 1926 constants.getConstantValueForMetadata(metadata);
1888 constants.addCompileTimeConstantForEmission(constant); 1927 constants.addCompileTimeConstantForEmission(constant);
1889 } 1928 }
1890 return true; 1929 return true;
1891 } 1930 }
1892 return false; 1931 return false;
1893 } 1932 }
1894 1933
1934 /// This method is called immediately after the [library] and its parts have
1935 /// been scanned.
1895 Future onLibraryScanned(LibraryElement library, LibraryLoader loader) { 1936 Future onLibraryScanned(LibraryElement library, LibraryLoader loader) {
1896 return super.onLibraryScanned(library, loader).then((_) { 1937 // TODO(johnniwinther): Move this to [JavaScriptBackend].
Siggi Cherem (dart-lang) 2017/02/08 00:10:03 remove TODO?
Johnni Winther 2017/02/08 09:46:35 Done.
1897 if (library.isPlatformLibrary && 1938 if (!compiler.serialization.isDeserialized(library)) {
1898 // Don't patch library currently disallowed. 1939 if (canLibraryUseNative(library)) {
1899 !library.isSynthesized && 1940 library.forEachLocalMember((Element element) {
1900 !library.isPatched && 1941 if (element.isClass) {
1901 // Don't patch deserialized libraries. 1942 checkNativeAnnotation(compiler, element);
1902 !compiler.serialization.isDeserialized(library)) { 1943 }
1903 // Apply patch, if any. 1944 });
1904 Uri patchUri = compiler.resolvePatchUri(library.canonicalUri.path); 1945 }
1905 if (patchUri != null) { 1946 checkJsInteropAnnotation(compiler, library);
1906 return compiler.patchParser.patchLibrary(loader, patchUri, library); 1947 library.forEachLocalMember((Element element) {
1948 checkJsInteropAnnotation(compiler, element);
1949 if (element.isClass && isJsInterop(element)) {
1950 ClassElement classElement = element;
1951 classElement.forEachMember((_, memberElement) {
1952 checkJsInteropAnnotation(compiler, memberElement);
1953 });
1907 } 1954 }
1955 });
1956 }
1957 if (library.isPlatformLibrary &&
1958 // Don't patch library currently disallowed.
1959 !library.isSynthesized &&
1960 !library.isPatched &&
1961 // Don't patch deserialized libraries.
1962 !compiler.serialization.isDeserialized(library)) {
1963 // Apply patch, if any.
1964 Uri patchUri = compiler.resolvePatchUri(library.canonicalUri.path);
1965 if (patchUri != null) {
1966 return compiler.patchParser.patchLibrary(loader, patchUri, library);
1908 } 1967 }
1909 }).then((_) { 1968 }
1910 Uri uri = library.canonicalUri; 1969 Uri uri = library.canonicalUri;
1911 if (uri == Uris.dart_html) { 1970 if (uri == Uris.dart_html) {
1912 htmlLibraryIsLoaded = true; 1971 htmlLibraryIsLoaded = true;
1913 } else if (uri == LookupMapAnalysis.PACKAGE_LOOKUP_MAP) { 1972 } else if (uri == LookupMapAnalysis.PACKAGE_LOOKUP_MAP) {
1914 lookupMapAnalysis.init(library); 1973 lookupMapAnalysis.init(library);
1915 } 1974 }
1916 annotations.onLibraryScanned(library); 1975 annotations.onLibraryScanned(library);
1917 }); 1976 return new Future.value();
1918 } 1977 }
1919 1978
1979 /// This method is called when all new libraries loaded through
1980 /// [LibraryLoader.loadLibrary] has been loaded and their imports/exports
1981 /// have been computed.
1920 Future onLibrariesLoaded(LoadedLibraries loadedLibraries) { 1982 Future onLibrariesLoaded(LoadedLibraries loadedLibraries) {
1921 if (!loadedLibraries.containsLibrary(Uris.dart_core)) { 1983 if (!loadedLibraries.containsLibrary(Uris.dart_core)) {
1922 return new Future.value(); 1984 return new Future.value();
1923 } 1985 }
1924 1986
1925 helpers.onLibrariesLoaded(loadedLibraries); 1987 helpers.onLibrariesLoaded(loadedLibraries);
1926 1988
1927 implementationClasses = <ClassElement, ClassElement>{}; 1989 implementationClasses = <ClassElement, ClassElement>{};
1928 implementationClasses[commonElements.intClass] = helpers.jsIntClass; 1990 implementationClasses[commonElements.intClass] = helpers.jsIntClass;
1929 implementationClasses[commonElements.boolClass] = helpers.jsBoolClass; 1991 implementationClasses[commonElements.boolClass] = helpers.jsBoolClass;
(...skipping 12 matching lines...) Expand all
1942 ..add(helpers.jsInterceptorClass) 2004 ..add(helpers.jsInterceptorClass)
1943 ..add(helpers.jsNullClass); 2005 ..add(helpers.jsNullClass);
1944 2006
1945 validateInterceptorImplementsAllObjectMethods(helpers.jsInterceptorClass); 2007 validateInterceptorImplementsAllObjectMethods(helpers.jsInterceptorClass);
1946 // The null-interceptor must also implement *all* methods. 2008 // The null-interceptor must also implement *all* methods.
1947 validateInterceptorImplementsAllObjectMethods(helpers.jsNullClass); 2009 validateInterceptorImplementsAllObjectMethods(helpers.jsNullClass);
1948 2010
1949 return new Future.value(); 2011 return new Future.value();
1950 } 2012 }
1951 2013
2014 /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed
2015 /// annotations. The arguments corresponds to the unions of the corresponding
2016 /// fields of the annotations.
1952 void registerMirrorUsage( 2017 void registerMirrorUsage(
1953 Set<String> symbols, Set<Element> targets, Set<Element> metaTargets) { 2018 Set<String> symbols, Set<Element> targets, Set<Element> metaTargets) {
1954 if (symbols == null && targets == null && metaTargets == null) { 2019 if (symbols == null && targets == null && metaTargets == null) {
1955 // The user didn't specify anything, or there are imports of 2020 // The user didn't specify anything, or there are imports of
1956 // 'dart:mirrors' without @MirrorsUsed. 2021 // 'dart:mirrors' without @MirrorsUsed.
1957 hasInsufficientMirrorsUsed = true; 2022 hasInsufficientMirrorsUsed = true;
1958 return; 2023 return;
1959 } 2024 }
1960 if (symbols != null) symbolsUsed.addAll(symbols); 2025 if (symbols != null) symbolsUsed.addAll(symbols);
1961 if (targets != null) { 2026 if (targets != null) {
(...skipping 19 matching lines...) Expand all
1981 * accessed (invoked, get, set) that is not accessible for the reflective 2046 * accessed (invoked, get, set) that is not accessible for the reflective
1982 * system. 2047 * system.
1983 */ 2048 */
1984 bool isAccessibleByReflection(Element element) { 2049 bool isAccessibleByReflection(Element element) {
1985 if (element.isClass) { 2050 if (element.isClass) {
1986 element = getDartClass(element); 2051 element = getDartClass(element);
1987 } 2052 }
1988 return membersNeededForReflection.contains(element); 2053 return membersNeededForReflection.contains(element);
1989 } 2054 }
1990 2055
2056 /// Returns `true` if this member element needs reflection information at
2057 /// runtime.
1991 bool isMemberAccessibleByReflection(MemberElement element) { 2058 bool isMemberAccessibleByReflection(MemberElement element) {
1992 return membersNeededForReflection.contains(element); 2059 return membersNeededForReflection.contains(element);
1993 } 2060 }
1994 2061
1995 /** 2062 /// Returns true if this element has to be enqueued due to
1996 * Returns true if the element has to be resolved due to a mirrorsUsed 2063 /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if
1997 * annotation. If we have insufficient mirrors used annotations, we only 2064 /// normal tree shaking is still active ([isTreeShakingDisabled] is false).
1998 * keep additional elements if treeshaking has been disabled.
1999 */
2000 bool requiredByMirrorSystem(Element element) { 2065 bool requiredByMirrorSystem(Element element) {
2001 return hasInsufficientMirrorsUsed && isTreeShakingDisabled || 2066 return hasInsufficientMirrorsUsed && isTreeShakingDisabled ||
2002 matchesMirrorsMetaTarget(element) || 2067 matchesMirrorsMetaTarget(element) ||
2003 targetsUsed.contains(element); 2068 targetsUsed.contains(element);
2004 } 2069 }
2005 2070
2006 /** 2071 /// Returns true if this element is covered by a mirrorsUsed annotation.
2007 * Returns true if the element matches a mirrorsUsed annotation. If 2072 ///
2008 * we have insufficient mirrorsUsed information, this returns true for 2073 /// Note that it might still be ok to tree shake the element away if no
2009 * all elements, as they might all be potentially referenced. 2074 /// reflection is used in the program (and thus [isTreeShakingDisabled] is
2010 */ 2075 /// still false). Therefore _do not_ use this predicate to decide inclusion
2076 /// in the tree, use [requiredByMirrorSystem] instead.
2011 bool referencedFromMirrorSystem(Element element, [recursive = true]) { 2077 bool referencedFromMirrorSystem(Element element, [recursive = true]) {
2012 Element enclosing = recursive ? element.enclosingElement : null; 2078 Element enclosing = recursive ? element.enclosingElement : null;
2013 2079
2014 return hasInsufficientMirrorsUsed || 2080 return hasInsufficientMirrorsUsed ||
2015 matchesMirrorsMetaTarget(element) || 2081 matchesMirrorsMetaTarget(element) ||
2016 targetsUsed.contains(element) || 2082 targetsUsed.contains(element) ||
2017 (enclosing != null && referencedFromMirrorSystem(enclosing)); 2083 (enclosing != null && referencedFromMirrorSystem(enclosing));
2018 } 2084 }
2019 2085
2020 /** 2086 /**
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
2237 if (target == null) continue; 2303 if (target == null) continue;
2238 if (target.isField) { 2304 if (target.isField) {
2239 staticFields.add(target); 2305 staticFields.add(target);
2240 } else if (target.isLibrary || target.isClass) { 2306 } else if (target.isLibrary || target.isClass) {
2241 addFieldsInContainer(target); 2307 addFieldsInContainer(target);
2242 } 2308 }
2243 } 2309 }
2244 return staticFields; 2310 return staticFields;
2245 } 2311 }
2246 2312
2247 /// Called when [enqueuer] is empty, but before it is closed. 2313 /// Called when [enqueuer]'s queue is empty, but before it is closed.
2314 ///
2315 /// This is used, for example, by the JS backend to enqueue additional
2316 /// elements needed for reflection. [recentClasses] is a collection of
2317 /// all classes seen for the first time by the [enqueuer] since the last call
2318 /// to [onQueueEmpty].
2319 ///
2320 /// A return value of [:true:] indicates that [recentClasses] has been
2321 /// processed and its elements do not need to be seen in the next round. When
2322 /// [:false:] is returned, [onQueueEmpty] will be called again once the
2323 /// resolution queue has drained and [recentClasses] will be a superset of the
2324 /// current value.
2325 ///
2326 /// There is no guarantee that a class is only present once in
2327 /// [recentClasses], but every class seen by the [enqueuer] will be present in
2328 /// [recentClasses] at least once.
2248 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses) { 2329 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses) {
2249 // Add elements used synthetically, that is, through features rather than 2330 // Add elements used synthetically, that is, through features rather than
2250 // syntax, for instance custom elements. 2331 // syntax, for instance custom elements.
2251 // 2332 //
2252 // Return early if any elements are added to avoid counting the elements as 2333 // Return early if any elements are added to avoid counting the elements as
2253 // due to mirrors. 2334 // due to mirrors.
2254 enqueuer.applyImpact(customElementsAnalysis.flush( 2335 enqueuer.applyImpact(customElementsAnalysis.flush(
2255 forResolution: enqueuer.isResolutionQueue)); 2336 forResolution: enqueuer.isResolutionQueue));
2256 enqueuer.applyImpact( 2337 enqueuer.applyImpact(
2257 lookupMapAnalysis.flush(forResolution: enqueuer.isResolutionQueue)); 2338 lookupMapAnalysis.flush(forResolution: enqueuer.isResolutionQueue));
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
2378 } 2459 }
2379 } else { 2460 } else {
2380 processLibraryMetadata(element.library); 2461 processLibraryMetadata(element.library);
2381 } 2462 }
2382 } 2463 }
2383 } 2464 }
2384 2465
2385 entities.forEach(processElementMetadata); 2466 entities.forEach(processElementMetadata);
2386 } 2467 }
2387 2468
2469 /// Called after the queue is closed. [onQueueEmpty] may be called multiple
2470 /// times, but [onQueueClosed] is only called once.
2388 void onQueueClosed() { 2471 void onQueueClosed() {
2389 lookupMapAnalysis.onQueueClosed(); 2472 lookupMapAnalysis.onQueueClosed();
2390 jsInteropAnalysis.onQueueClosed(); 2473 jsInteropAnalysis.onQueueClosed();
2391 } 2474 }
2392 2475
2393 // TODO(johnniwinther): Create a CodegenPhase object for the backend to hold 2476 // TODO(johnniwinther): Create a CodegenPhase object for the backend to hold
2394 // data only available during code generation. 2477 // data only available during code generation.
2395 ClosedWorld _closedWorldCache; 2478 ClosedWorld _closedWorldCache;
2396 ClosedWorld get _closedWorld { 2479 ClosedWorld get _closedWorld {
2397 assert(invariant(NO_LOCATION_SPANNABLE, _closedWorldCache != null, 2480 assert(invariant(NO_LOCATION_SPANNABLE, _closedWorldCache != null,
2398 message: "ClosedWorld has not be set yet.")); 2481 message: "ClosedWorld has not be set yet."));
2399 return _closedWorldCache; 2482 return _closedWorldCache;
2400 } 2483 }
2401 2484
2402 void set _closedWorld(ClosedWorld value) { 2485 void set _closedWorld(ClosedWorld value) {
2403 _closedWorldCache = value; 2486 _closedWorldCache = value;
2404 } 2487 }
2405 2488
2489 /// Called when the compiler starts running the codegen enqueuer. The
2490 /// [WorldImpact] of enabled backend features is returned.
2406 WorldImpact onCodegenStart(ClosedWorld closedWorld) { 2491 WorldImpact onCodegenStart(ClosedWorld closedWorld) {
2407 _closedWorld = closedWorld; 2492 _closedWorld = closedWorld;
2408 _namer = determineNamer(_closedWorld, compiler.codegenWorldBuilder); 2493 _namer = determineNamer(_closedWorld, compiler.codegenWorldBuilder);
2409 tracer = new Tracer(_closedWorld, namer, compiler.outputProvider); 2494 tracer = new Tracer(_closedWorld, namer, compiler.outputProvider);
2410 emitter.createEmitter(_namer, _closedWorld); 2495 emitter.createEmitter(_namer, _closedWorld);
2411 lookupMapAnalysis.onCodegenStart(); 2496 lookupMapAnalysis.onCodegenStart();
2412 if (hasIsolateSupport) { 2497 if (hasIsolateSupport) {
2413 return enableIsolateSupport(forResolution: false); 2498 return enableIsolateSupport(forResolution: false);
2414 } 2499 }
2415 return const WorldImpact(); 2500 return const WorldImpact();
2416 } 2501 }
2417 2502
2503 /// Called when code generation has been completed.
2418 void onCodegenEnd() { 2504 void onCodegenEnd() {
2419 sourceInformationStrategy.onComplete(); 2505 sourceInformationStrategy.onComplete();
2420 tracer.close(); 2506 tracer.close();
2421 } 2507 }
2422 2508
2509 // Does this element belong in the output
2510 bool shouldOutput(Element element) => true;
2511
2512 /// Returns `true` if the `native` pseudo keyword is supported for [library].
2513 bool canLibraryUseNative(LibraryElement library) {
2514 return native.maybeEnableNative(compiler, library);
2515 }
2516
2517 @override
2518 bool isTargetSpecificLibrary(LibraryElement library) {
2519 Uri canonicalUri = library.canonicalUri;
2520 if (canonicalUri == BackendHelpers.DART_JS_HELPER ||
2521 canonicalUri == BackendHelpers.DART_INTERCEPTORS) {
2522 return true;
2523 }
2524 return false;
2525 }
2526
2423 /// Process backend specific annotations. 2527 /// Process backend specific annotations.
2424 void processAnnotations( 2528 void processAnnotations(
2425 Element element, ClosedWorldRefiner closedWorldRefiner) { 2529 Element element, ClosedWorldRefiner closedWorldRefiner) {
2426 if (element.isMalformed) { 2530 if (element.isMalformed) {
2427 // Elements that are marked as malformed during parsing or resolution 2531 // Elements that are marked as malformed during parsing or resolution
2428 // might be registered here. These should just be ignored. 2532 // might be registered here. These should just be ignored.
2429 return; 2533 return;
2430 } 2534 }
2431 2535
2432 Element implementation = element.implementation; 2536 Element implementation = element.implementation;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
2499 "@NoSideEffects() should always be combined with @NoInline."); 2603 "@NoSideEffects() should always be combined with @NoInline.");
2500 } 2604 }
2501 } 2605 }
2502 2606
2503 MethodElement helperForBadMain() => helpers.badMain; 2607 MethodElement helperForBadMain() => helpers.badMain;
2504 2608
2505 MethodElement helperForMissingMain() => helpers.missingMain; 2609 MethodElement helperForMissingMain() => helpers.missingMain;
2506 2610
2507 MethodElement helperForMainArity() => helpers.mainHasTooManyParameters; 2611 MethodElement helperForMainArity() => helpers.mainHasTooManyParameters;
2508 2612
2509 @override 2613 /// Computes the [WorldImpact] of calling [mainMethod] as the entry point.
2510 WorldImpact computeMainImpact(MethodElement mainMethod, 2614 WorldImpact computeMainImpact(MethodElement mainMethod,
2511 {bool forResolution}) { 2615 {bool forResolution}) {
2512 WorldImpactBuilderImpl mainImpact = new WorldImpactBuilderImpl(); 2616 WorldImpactBuilderImpl mainImpact = new WorldImpactBuilderImpl();
2513 if (mainMethod.parameters.isNotEmpty) { 2617 if (mainMethod.parameters.isNotEmpty) {
2514 impactTransformer.registerBackendImpact( 2618 impactTransformer.registerBackendImpact(
2515 mainImpact, impacts.mainWithArguments); 2619 mainImpact, impacts.mainWithArguments);
2516 mainImpact.registerStaticUse( 2620 mainImpact.registerStaticUse(
2517 new StaticUse.staticInvoke(mainMethod, CallStructure.TWO_ARGS)); 2621 new StaticUse.staticInvoke(mainMethod, CallStructure.TWO_ARGS));
2518 // If the main method takes arguments, this compilation could be the 2622 // If the main method takes arguments, this compilation could be the
2519 // target of Isolate.spawnUri. Strictly speaking, that can happen also if 2623 // target of Isolate.spawnUri. Strictly speaking, that can happen also if
(...skipping 13 matching lines...) Expand all
2533 String deferredPartFileName(String name, {bool addExtension: true}) { 2637 String deferredPartFileName(String name, {bool addExtension: true}) {
2534 assert(name != ""); 2638 assert(name != "");
2535 String outPath = compiler.options.outputUri != null 2639 String outPath = compiler.options.outputUri != null
2536 ? compiler.options.outputUri.path 2640 ? compiler.options.outputUri.path
2537 : "out"; 2641 : "out";
2538 String outName = outPath.substring(outPath.lastIndexOf('/') + 1); 2642 String outName = outPath.substring(outPath.lastIndexOf('/') + 1);
2539 String extension = addExtension ? ".part.js" : ""; 2643 String extension = addExtension ? ".part.js" : "";
2540 return "${outName}_$name$extension"; 2644 return "${outName}_$name$extension";
2541 } 2645 }
2542 2646
2543 @override 2647 /// Enable deferred loading. Returns `true` if the backend supports deferred
2648 /// loading.
2544 bool enableDeferredLoadingIfSupported(Spannable node) => true; 2649 bool enableDeferredLoadingIfSupported(Spannable node) => true;
2545 2650
2546 @override 2651 /// Enable compilation of code with compile time errors. Returns `true` if
2652 /// supported by the backend.
2547 bool enableCodegenWithErrorsIfSupported(Spannable node) => true; 2653 bool enableCodegenWithErrorsIfSupported(Spannable node) => true;
2548 2654
2549 jsAst.Expression rewriteAsync( 2655 jsAst.Expression rewriteAsync(
2550 FunctionElement element, jsAst.Expression code) { 2656 FunctionElement element, jsAst.Expression code) {
2551 AsyncRewriterBase rewriter = null; 2657 AsyncRewriterBase rewriter = null;
2552 jsAst.Name name = namer.methodPropertyName(element); 2658 jsAst.Name name = namer.methodPropertyName(element);
2553 switch (element.asyncMarker) { 2659 switch (element.asyncMarker) {
2554 case AsyncMarker.ASYNC: 2660 case AsyncMarker.ASYNC:
2555 rewriter = new AsyncRewriter(reporter, element, 2661 rewriter = new AsyncRewriter(reporter, element,
2556 asyncHelper: emitter.staticFunctionAccess(helpers.asyncHelper), 2662 asyncHelper: emitter.staticFunctionAccess(helpers.asyncHelper),
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
2603 "core": "_internal/js_runtime/lib/core_patch.dart", 2709 "core": "_internal/js_runtime/lib/core_patch.dart",
2604 "developer": "_internal/js_runtime/lib/developer_patch.dart", 2710 "developer": "_internal/js_runtime/lib/developer_patch.dart",
2605 "io": "_internal/js_runtime/lib/io_patch.dart", 2711 "io": "_internal/js_runtime/lib/io_patch.dart",
2606 "isolate": "_internal/js_runtime/lib/isolate_patch.dart", 2712 "isolate": "_internal/js_runtime/lib/isolate_patch.dart",
2607 "math": "_internal/js_runtime/lib/math_patch.dart", 2713 "math": "_internal/js_runtime/lib/math_patch.dart",
2608 "mirrors": "_internal/js_runtime/lib/mirrors_patch.dart", 2714 "mirrors": "_internal/js_runtime/lib/mirrors_patch.dart",
2609 "typed_data": "_internal/js_runtime/lib/typed_data_patch.dart", 2715 "typed_data": "_internal/js_runtime/lib/typed_data_patch.dart",
2610 "_internal": "_internal/js_runtime/lib/internal_patch.dart" 2716 "_internal": "_internal/js_runtime/lib/internal_patch.dart"
2611 }; 2717 };
2612 2718
2613 @override 2719 /// Returns the location of the patch-file associated with [libraryName]
2720 /// resolved from [plaformConfigUri].
2721 ///
2722 /// Returns null if there is none.
2614 Uri resolvePatchUri(String libraryName, Uri platformConfigUri) { 2723 Uri resolvePatchUri(String libraryName, Uri platformConfigUri) {
2615 String patchLocation = _patchLocations[libraryName]; 2724 String patchLocation = _patchLocations[libraryName];
2616 if (patchLocation == null) return null; 2725 if (patchLocation == null) return null;
2617 return platformConfigUri.resolve(patchLocation); 2726 return platformConfigUri.resolve(patchLocation);
2618 } 2727 }
2619 2728
2620 @override 2729 /// Creates an impact strategy to use for compilation.
2621 ImpactStrategy createImpactStrategy( 2730 ImpactStrategy createImpactStrategy(
2622 {bool supportDeferredLoad: true, 2731 {bool supportDeferredLoad: true,
2623 bool supportDumpInfo: true, 2732 bool supportDumpInfo: true,
2624 bool supportSerialization: true}) { 2733 bool supportSerialization: true}) {
2625 return new JavaScriptImpactStrategy(resolution, compiler.dumpInfoTask, 2734 return new JavaScriptImpactStrategy(resolution, compiler.dumpInfoTask,
2626 supportDeferredLoad: supportDeferredLoad, 2735 supportDeferredLoad: supportDeferredLoad,
2627 supportDumpInfo: supportDumpInfo, 2736 supportDumpInfo: supportDumpInfo,
2628 supportSerialization: supportSerialization); 2737 supportSerialization: supportSerialization);
2629 } 2738 }
2739
2740 EnqueueTask makeEnqueuer() => new EnqueueTask(compiler);
2630 } 2741 }
2631 2742
2632 class JSFrontendAccess implements Frontend { 2743 class JSFrontendAccess implements Frontend {
2633 final Compiler compiler; 2744 final Compiler compiler;
2634 2745
2635 JSFrontendAccess(this.compiler); 2746 JSFrontendAccess(this.compiler);
2636 2747
2637 Resolution get resolution => compiler.resolution; 2748 Resolution get resolution => compiler.resolution;
2638 2749
2639 @override 2750 @override
(...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after
3281 @override 3392 @override
3282 bool isNativeClass(ClassElement element) { 3393 bool isNativeClass(ClassElement element) {
3283 return helpers.backend.isNative(element); 3394 return helpers.backend.isNative(element);
3284 } 3395 }
3285 3396
3286 @override 3397 @override
3287 bool isNativeMember(MemberElement element) { 3398 bool isNativeMember(MemberElement element) {
3288 return helpers.backend.isNative(element); 3399 return helpers.backend.isNative(element);
3289 } 3400 }
3290 } 3401 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698