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

Side by Side Diff: pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart

Issue 2843283004: Use more entities in program_builder, collector and registry (Closed)
Patch Set: Updated cf. comments. Created 3 years, 7 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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 dart2js.js_emitter.program_builder; 5 library dart2js.js_emitter.program_builder;
6 6
7 import '../../closure.dart' show ClosureTask, ClosureFieldElement; 7 import '../../closure.dart' show ClosureTask, ClosureFieldElement;
8 import '../../common.dart'; 8 import '../../common.dart';
9 import '../../common/names.dart' show Names, Selectors; 9 import '../../common/names.dart' show Names, Selectors;
10 import '../../constants/values.dart' 10 import '../../constants/values.dart'
11 show ConstantValue, InterceptorConstantValue; 11 show ConstantValue, InterceptorConstantValue;
12 import '../../common_elements.dart' show CommonElements; 12 import '../../common_elements.dart' show CommonElements, ElementEnvironment;
13 import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit; 13 import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit;
14 import '../../elements/elements.dart' 14 import '../../elements/elements.dart'
15 show 15 show
16 ClassElement, 16 ClassElement,
17 Element, 17 Element,
18 Elements, 18 Elements,
19 FieldElement, 19 FieldElement,
20 FunctionElement, 20 FunctionElement,
21 FunctionSignature, 21 FunctionSignature,
22 GetterElement, 22 GetterElement,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 ClassStubGenerator, 58 ClassStubGenerator,
59 CodeEmitterTask, 59 CodeEmitterTask,
60 computeMixinClass, 60 computeMixinClass,
61 Emitter, 61 Emitter,
62 InterceptorStubGenerator, 62 InterceptorStubGenerator,
63 MainCallStubGenerator, 63 MainCallStubGenerator,
64 ParameterStubGenerator, 64 ParameterStubGenerator,
65 RuntimeTypeGenerator, 65 RuntimeTypeGenerator,
66 TypeTestProperties; 66 TypeTestProperties;
67 import '../model.dart'; 67 import '../model.dart';
68 import '../sorter.dart';
68 69
69 part 'collector.dart'; 70 part 'collector.dart';
70 part 'field_visitor.dart'; 71 part 'field_visitor.dart';
71 part 'registry.dart'; 72 part 'registry.dart';
72 73
73 /// Builds a self-contained representation of the program that can then be 74 /// Builds a self-contained representation of the program that can then be
74 /// emitted more easily by the individual emitters. 75 /// emitted more easily by the individual emitters.
75 class ProgramBuilder { 76 class ProgramBuilder {
76 final CompilerOptions _options; 77 final CompilerOptions _options;
78 final ElementEnvironment _elementEnvironment;
77 final CommonElements _commonElements; 79 final CommonElements _commonElements;
78 final DartTypes _types; 80 final DartTypes _types;
79 final DeferredLoadTask _deferredLoadTask; 81 final DeferredLoadTask _deferredLoadTask;
80 final ClosureTask _closureToClassMapper; 82 final ClosureTask _closureToClassMapper;
81 final CodegenWorldBuilder _worldBuilder; 83 final CodegenWorldBuilder _worldBuilder;
82 final NativeCodegenEnqueuer _nativeCodegenEnqueuer; 84 final NativeCodegenEnqueuer _nativeCodegenEnqueuer;
83 final BackendUsage _backendUsage; 85 final BackendUsage _backendUsage;
84 final JavaScriptConstantCompiler _constantHandler; 86 final JavaScriptConstantCompiler _constantHandler;
85 final NativeData _nativeData; 87 final NativeData _nativeData;
86 final RuntimeTypesNeed _rtiNeed; 88 final RuntimeTypesNeed _rtiNeed;
(...skipping 21 matching lines...) Expand all
108 final Registry _registry; 110 final Registry _registry;
109 111
110 final FunctionEntity _mainFunction; 112 final FunctionEntity _mainFunction;
111 final bool _isMockCompilation; 113 final bool _isMockCompilation;
112 114
113 /// True if the program should store function types in the metadata. 115 /// True if the program should store function types in the metadata.
114 bool _storeFunctionTypesInMetadata = false; 116 bool _storeFunctionTypesInMetadata = false;
115 117
116 ProgramBuilder( 118 ProgramBuilder(
117 this._options, 119 this._options,
120 this._elementEnvironment,
118 this._commonElements, 121 this._commonElements,
119 this._types, 122 this._types,
120 this._deferredLoadTask, 123 this._deferredLoadTask,
121 this._closureToClassMapper, 124 this._closureToClassMapper,
122 this._worldBuilder, 125 this._worldBuilder,
123 this._nativeCodegenEnqueuer, 126 this._nativeCodegenEnqueuer,
124 this._backendUsage, 127 this._backendUsage,
125 this._constantHandler, 128 this._constantHandler,
126 this._nativeData, 129 this._nativeData,
127 this._rtiNeed, 130 this._rtiNeed,
128 this._mirrorsData, 131 this._mirrorsData,
129 this._interceptorData, 132 this._interceptorData,
130 this._superMemberData, 133 this._superMemberData,
131 this._rtiChecks, 134 this._rtiChecks,
132 this._rtiEncoder, 135 this._rtiEncoder,
133 this._rtiSubstitutions, 136 this._rtiSubstitutions,
134 this._jsInteropAnalysis, 137 this._jsInteropAnalysis,
135 this._oneShotInterceptorData, 138 this._oneShotInterceptorData,
136 this._customElementsCodegenAnalysis, 139 this._customElementsCodegenAnalysis,
137 this._generatedCode, 140 this._generatedCode,
138 this._namer, 141 this._namer,
139 this._task, 142 this._task,
140 this._closedWorld, 143 this._closedWorld,
141 Set<ClassElement> rtiNeededClasses, 144 Set<ClassEntity> rtiNeededClasses,
142 this._mainFunction, 145 this._mainFunction,
143 {bool isMockCompilation}) 146 {bool isMockCompilation})
144 : this._isMockCompilation = isMockCompilation, 147 : this._isMockCompilation = isMockCompilation,
145 this.collector = new Collector( 148 this.collector = new Collector(
146 _options, 149 _options,
147 _commonElements, 150 _commonElements,
148 _deferredLoadTask, 151 _deferredLoadTask,
149 _worldBuilder, 152 _worldBuilder,
150 _namer, 153 _namer,
151 _task.emitter, 154 _task.emitter,
152 _constantHandler, 155 _constantHandler,
153 _nativeData, 156 _nativeData,
154 _interceptorData, 157 _interceptorData,
155 _oneShotInterceptorData, 158 _oneShotInterceptorData,
156 _mirrorsData, 159 _mirrorsData,
157 _closedWorld, 160 _closedWorld,
158 rtiNeededClasses, 161 rtiNeededClasses,
159 _generatedCode), 162 _generatedCode,
160 this._registry = new Registry(_deferredLoadTask); 163 _task.sorter),
164 this._registry = new Registry(_deferredLoadTask, _task.sorter);
161 165
162 /// Mapping from [ClassElement] to constructed [Class]. We need this to 166 /// Mapping from [ClassEntity] to constructed [Class]. We need this to
163 /// update the superclass in the [Class]. 167 /// update the superclass in the [Class].
164 final Map<ClassElement, Class> _classes = <ClassElement, Class>{}; 168 final Map<ClassEntity, Class> _classes = <ClassEntity, Class>{};
165 169
166 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to 170 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to
167 /// generate the deferredLoadingMap (to know which hunks to load). 171 /// generate the deferredLoadingMap (to know which hunks to load).
168 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{}; 172 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{};
169 173
170 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to 174 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to
171 /// update field-initializers to point to the ConstantModel. 175 /// update field-initializers to point to the ConstantModel.
172 final Map<ConstantValue, Constant> _constants = <ConstantValue, Constant>{}; 176 final Map<ConstantValue, Constant> _constants = <ConstantValue, Constant>{};
173 177
174 /// Mapping from names to strings. 178 /// Mapping from names to strings.
175 /// 179 ///
176 /// This mapping is used to support `const Symbol` expressions. 180 /// This mapping is used to support `const Symbol` expressions.
177 /// 181 ///
178 /// This map is filled when building classes. 182 /// This map is filled when building classes.
179 final Map<js.Name, String> _symbolsMap = <js.Name, String>{}; 183 final Map<js.Name, String> _symbolsMap = <js.Name, String>{};
180 184
181 Set<Class> _unneededNativeClasses; 185 Set<Class> _unneededNativeClasses;
182 186
183 Program buildProgram({bool storeFunctionTypesInMetadata: false}) { 187 Program buildProgram({bool storeFunctionTypesInMetadata: false}) {
184 collector.collect(); 188 collector.collect();
185 189
186 this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata; 190 this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata;
187 // Note: In rare cases (mostly tests) output units can be empty. This 191 // Note: In rare cases (mostly tests) output units can be empty. This
188 // happens when the deferred code is dead-code eliminated but we still need 192 // happens when the deferred code is dead-code eliminated but we still need
189 // to check that the library has been loaded. 193 // to check that the library has been loaded.
190 _deferredLoadTask.allOutputUnits.forEach(_registry.registerOutputUnit); 194 _deferredLoadTask.allOutputUnits.forEach(_registry.registerOutputUnit);
191 collector.outputClassLists.forEach(_registry.registerElements); 195 collector.outputClassLists.forEach(_registry.registerClasses);
192 collector.outputStaticLists.forEach(_registry.registerElements); 196 collector.outputStaticLists.forEach(_registry.registerMembers);
193 collector.outputConstantLists.forEach(_registerConstants); 197 collector.outputConstantLists.forEach(_registerConstants);
194 collector.outputStaticNonFinalFieldLists 198 collector.outputStaticNonFinalFieldLists.forEach(_registry.registerMembers);
195 .forEach(_registry.registerElements);
196 199
197 // We always add the current isolate holder. 200 // We always add the current isolate holder.
198 _registerStaticStateHolder(); 201 _registerStaticStateHolder();
199 202
200 // We need to run the native-preparation before we build the output. The 203 // We need to run the native-preparation before we build the output. The
201 // preparation code, in turn needs the classes to be set up. 204 // preparation code, in turn needs the classes to be set up.
202 // We thus build the classes before building their containers. 205 // We thus build the classes before building their containers.
203 collector.outputClassLists 206 collector.outputClassLists
204 .forEach((OutputUnit _, List<ClassElement> classes) { 207 .forEach((OutputUnit _, List<ClassEntity> classes) {
205 classes.forEach(_buildClass); 208 classes.forEach(_buildClass);
206 }); 209 });
207 210
208 // Resolve the superclass references after we've processed all the classes. 211 // Resolve the superclass references after we've processed all the classes.
209 _classes.forEach((ClassElement element, Class c) { 212 _classes.forEach((ClassEntity cls, Class c) {
210 if (element.superclass != null) { 213 ClassEntity superclass = _elementEnvironment.getSuperClass(cls);
211 c.setSuperclass(_classes[element.superclass]); 214 if (superclass != null) {
212 assert(invariant(element, c.superclass != null, 215 c.setSuperclass(_classes[superclass]);
216 assert(invariant(cls, c.superclass != null,
213 message: "No Class for has been created for superclass " 217 message: "No Class for has been created for superclass "
214 "${element.superclass} of $c.")); 218 "${superclass} of $c."));
215 } 219 }
216 if (c is MixinApplication) { 220 if (c is MixinApplication) {
217 c.setMixinClass(_classes[computeMixinClass(element)]); 221 c.setMixinClass(_classes[computeMixinClass(cls)]);
218 assert(c.mixinClass != null); 222 assert(c.mixinClass != null);
219 } 223 }
220 }); 224 });
221 225
222 List<Class> nativeClasses = collector.nativeClassesAndSubclasses 226 List<Class> nativeClasses = collector.nativeClassesAndSubclasses
223 .map((ClassElement classElement) => _classes[classElement]) 227 .map((ClassEntity classElement) => _classes[classElement])
224 .toList(); 228 .toList();
225 229
226 Set<ClassElement> interceptorClassesNeededByConstants = 230 Set<ClassEntity> interceptorClassesNeededByConstants =
227 collector.computeInterceptorsReferencedFromConstants(); 231 collector.computeInterceptorsReferencedFromConstants();
228 Set<ClassElement> classesModifiedByEmitRTISupport = 232 Set<ClassEntity> classesModifiedByEmitRTISupport =
229 _task.typeTestRegistry.computeClassesModifiedByEmitRuntimeTypeSupport(); 233 _task.typeTestRegistry.computeClassesModifiedByEmitRuntimeTypeSupport();
230 234
231 _unneededNativeClasses = _task.nativeEmitter.prepareNativeClasses( 235 _unneededNativeClasses = _task.nativeEmitter.prepareNativeClasses(
232 nativeClasses, 236 nativeClasses,
233 interceptorClassesNeededByConstants, 237 interceptorClassesNeededByConstants,
234 classesModifiedByEmitRTISupport); 238 classesModifiedByEmitRTISupport);
235 239
236 _addJsInteropStubs(_registry.mainLibrariesMap); 240 _addJsInteropStubs(_registry.mainLibrariesMap);
237 241
238 MainFragment mainFragment = _buildMainFragment(_registry.mainLibrariesMap); 242 MainFragment mainFragment = _buildMainFragment(_registry.mainLibrariesMap);
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 List<Constant> _buildConstants(LibrariesMap librariesMap) { 341 List<Constant> _buildConstants(LibrariesMap librariesMap) {
338 List<ConstantValue> constantValues = 342 List<ConstantValue> constantValues =
339 collector.outputConstantLists[librariesMap.outputUnit]; 343 collector.outputConstantLists[librariesMap.outputUnit];
340 if (constantValues == null) return const <Constant>[]; 344 if (constantValues == null) return const <Constant>[];
341 return constantValues 345 return constantValues
342 .map((ConstantValue value) => _constants[value]) 346 .map((ConstantValue value) => _constants[value])
343 .toList(growable: false); 347 .toList(growable: false);
344 } 348 }
345 349
346 List<StaticField> _buildStaticNonFinalFields(LibrariesMap librariesMap) { 350 List<StaticField> _buildStaticNonFinalFields(LibrariesMap librariesMap) {
347 List<VariableElement> staticNonFinalFields = 351 List<FieldEntity> staticNonFinalFields =
348 collector.outputStaticNonFinalFieldLists[librariesMap.outputUnit]; 352 collector.outputStaticNonFinalFieldLists[librariesMap.outputUnit];
349 if (staticNonFinalFields == null) return const <StaticField>[]; 353 if (staticNonFinalFields == null) return const <StaticField>[];
350 354
351 return staticNonFinalFields.map(_buildStaticField).toList(growable: false); 355 return staticNonFinalFields.map(_buildStaticField).toList(growable: false);
352 } 356 }
353 357
354 StaticField _buildStaticField(FieldElement element) { 358 StaticField _buildStaticField(FieldElement element) {
355 ConstantValue initialValue = 359 ConstantValue initialValue =
356 _constantHandler.getConstantValue(element.constant); 360 _constantHandler.getConstantValue(element.constant);
357 // TODO(zarah): The holder should not be registered during building of 361 // TODO(zarah): The holder should not be registered during building of
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 // building a static field. (Note that the static-state holder was 403 // building a static field. (Note that the static-state holder was
400 // already registered earlier, and that we just call the register to get 404 // already registered earlier, and that we just call the register to get
401 // the holder-instance. 405 // the holder-instance.
402 return new StaticField( 406 return new StaticField(
403 element, name, _registerStaticStateHolder(), code, isFinal, isLazy); 407 element, name, _registerStaticStateHolder(), code, isFinal, isLazy);
404 } 408 }
405 409
406 List<Library> _buildLibraries(LibrariesMap librariesMap) { 410 List<Library> _buildLibraries(LibrariesMap librariesMap) {
407 List<Library> libraries = new List<Library>(librariesMap.length); 411 List<Library> libraries = new List<Library>(librariesMap.length);
408 int count = 0; 412 int count = 0;
409 librariesMap.forEach((LibraryElement library, List<Element> elements) { 413 librariesMap.forEach((LibraryEntity library, List<ClassEntity> classes,
410 libraries[count++] = _buildLibrary(library, elements); 414 List<MemberEntity> members) {
415 libraries[count++] = _buildLibrary(library, classes, members);
411 }); 416 });
412 return libraries; 417 return libraries;
413 } 418 }
414 419
415 void _addJsInteropStubs(LibrariesMap librariesMap) { 420 void _addJsInteropStubs(LibrariesMap librariesMap) {
416 if (_classes.containsKey(_commonElements.objectClass)) { 421 if (_classes.containsKey(_commonElements.objectClass)) {
417 var toStringInvocation = _namer.invocationName(Selectors.toString_); 422 var toStringInvocation = _namer.invocationName(Selectors.toString_);
418 // TODO(jacobr): register toString as used so that it is always accessible 423 // TODO(jacobr): register toString as used so that it is always accessible
419 // from JavaScript. 424 // from JavaScript.
420 _classes[_commonElements.objectClass].callStubs.add(_buildStubMethod( 425 _classes[_commonElements.objectClass].callStubs.add(_buildStubMethod(
421 new StringBackedName("toString"), 426 new StringBackedName("toString"),
422 js.js('function() { return this.#(this) }', toStringInvocation))); 427 js.js('function() { return this.#(this) }', toStringInvocation)));
423 } 428 }
424 429
425 // We add all members from classes marked with isJsInterop to the base 430 // We add all members from classes marked with isJsInterop to the base
426 // Interceptor class with implementations that directly call the 431 // Interceptor class with implementations that directly call the
427 // corresponding JavaScript member. We do not attempt to bind this when 432 // corresponding JavaScript member. We do not attempt to bind this when
428 // tearing off JavaScript methods as we cannot distinguish between calling 433 // tearing off JavaScript methods as we cannot distinguish between calling
429 // a regular getter that returns a JavaScript function and tearing off 434 // a regular getter that returns a JavaScript function and tearing off
430 // a method in the case where there exist multiple JavaScript classes 435 // a method in the case where there exist multiple JavaScript classes
431 // that conflict on whether the member is a getter or a method. 436 // that conflict on whether the member is a getter or a method.
432 var interceptorClass = _classes[_commonElements.jsJavaScriptObjectClass]; 437 var interceptorClass = _classes[_commonElements.jsJavaScriptObjectClass];
433 var stubNames = new Set<String>(); 438 var stubNames = new Set<String>();
434 librariesMap.forEach((LibraryElement library, List<Element> elements) { 439 librariesMap
435 for (Element e in elements) { 440 .forEach((LibraryEntity library, List<ClassEntity> classElements, _) {
436 if (e is ClassElement && _nativeData.isJsInteropClass(e)) { 441 for (ClassElement e in classElements) {
442 if (_nativeData.isJsInteropClass(e)) {
437 e.declaration.forEachMember((_, Element member) { 443 e.declaration.forEachMember((_, Element member) {
438 var jsName = _nativeData.computeUnescapedJSInteropName(member.name); 444 var jsName = _nativeData.computeUnescapedJSInteropName(member.name);
439 if (!member.isInstanceMember) return; 445 if (!member.isInstanceMember) return;
440 if (member.isGetter || member.isField || member.isFunction) { 446 if (member.isGetter || member.isField || member.isFunction) {
441 var selectors = 447 var selectors =
442 _worldBuilder.getterInvocationsByName(member.name); 448 _worldBuilder.getterInvocationsByName(member.name);
443 if (selectors != null && !selectors.isEmpty) { 449 if (selectors != null && !selectors.isEmpty) {
444 for (var selector in selectors.keys) { 450 for (var selector in selectors.keys) {
445 var stubName = _namer.invocationName(selector); 451 var stubName = _namer.invocationName(selector);
446 if (stubNames.add(stubName.key)) { 452 if (stubNames.add(stubName.key)) {
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 } 549 }
544 } 550 }
545 }); 551 });
546 } 552 }
547 } 553 }
548 }); 554 });
549 } 555 }
550 556
551 // Note that a library-element may have multiple [Library]s, if it is split 557 // Note that a library-element may have multiple [Library]s, if it is split
552 // into multiple output units. 558 // into multiple output units.
553 Library _buildLibrary(LibraryElement library, List<Element> elements) { 559 Library _buildLibrary(LibraryElement library, List<ClassEntity> classElements,
560 List<MemberEntity> memberElements) {
554 String uri = library.canonicalUri.toString(); 561 String uri = library.canonicalUri.toString();
555 562
556 List<StaticMethod> statics = elements 563 List<StaticMethod> statics = memberElements
557 .where((e) => e is FunctionElement) 564 .where((e) => e is MethodElement)
558 .map(_buildStaticMethod) 565 .map(_buildStaticMethod)
559 .toList(); 566 .toList();
560 567
561 if (library == _commonElements.interceptorsLibrary) { 568 if (library == _commonElements.interceptorsLibrary) {
562 statics.addAll(_generateGetInterceptorMethods()); 569 statics.addAll(_generateGetInterceptorMethods());
563 statics.addAll(_generateOneShotInterceptors()); 570 statics.addAll(_generateOneShotInterceptors());
564 } 571 }
565 572
566 List<Class> classes = elements 573 List<Class> classes = classElements
567 .where((e) => e is ClassElement)
568 .map((ClassElement classElement) => _classes[classElement]) 574 .map((ClassElement classElement) => _classes[classElement])
569 .where((Class cls) => 575 .where((Class cls) =>
570 !cls.isNative || !_unneededNativeClasses.contains(cls)) 576 !cls.isNative || !_unneededNativeClasses.contains(cls))
571 .toList(growable: false); 577 .toList(growable: false);
572 578
573 bool visitStatics = true; 579 bool visitStatics = true;
574 List<Field> staticFieldsForReflection = 580 List<Field> staticFieldsForReflection =
575 _buildFields(library, visitStatics: visitStatics); 581 _buildFields(library, visitStatics: visitStatics);
576 582
577 return new Library( 583 return new Library(
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after
1096 Constant constant = new Constant(name, holder, constantValue); 1102 Constant constant = new Constant(name, holder, constantValue);
1097 _constants[constantValue] = constant; 1103 _constants[constantValue] = constant;
1098 } 1104 }
1099 } 1105 }
1100 1106
1101 Holder _registerStaticStateHolder() { 1107 Holder _registerStaticStateHolder() {
1102 return _registry.registerHolder(_namer.staticStateHolder, 1108 return _registry.registerHolder(_namer.staticStateHolder,
1103 isStaticStateHolder: true); 1109 isStaticStateHolder: true);
1104 } 1110 }
1105 } 1111 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698