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

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

Issue 1227643003: dart2js: Move most of the code_emitter_task code into the program-builder. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Upload Created 5 years, 5 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) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of dart2js.js_emitter; 5 part of dart2js.js_emitter.program_builder;
6
7 const USE_LAZY_EMITTER = const bool.fromEnvironment("dart2js.use.lazy.emitter");
8 6
9 /** 7 /**
10 * Generates the code for all used classes in the program. Static fields (even 8 * Generates the code for all used classes in the program. Static fields (even
11 * in classes) are ignored, since they can be treated as non-class elements. 9 * in classes) are ignored, since they can be treated as non-class elements.
12 * 10 *
13 * The code for the containing (used) methods must exist in the `universe`. 11 * The code for the containing (used) methods must exist in the `universe`.
14 */ 12 */
15 class CodeEmitterTask extends CompilerTask { 13 class Collector {
16 // TODO(floitsch): the code-emitter task should not need a namer. 14 // TODO(floitsch): the code-emitter task should not need a namer.
17 final Namer namer; 15 final Namer namer;
18 final TypeTestRegistry typeTestRegistry; 16 final Compiler compiler;
19 NativeEmitter nativeEmitter; 17 final Set<ClassElement> rtiNeededClasses;
20 MetadataCollector metadataCollector; 18 final Emitter emitter;
21 OldEmitter oldEmitter; 19 // TODO(floitsch): remove this field.
22 Emitter emitter; 20 // The field is untyped, because we don't want to import the full emitter
21 // class.
22 final oldEmitter;
23 23
24 final Set<ClassElement> neededClasses = new Set<ClassElement>(); 24 final Set<ClassElement> neededClasses = new Set<ClassElement>();
25 Set<ClassElement> classesOnlyNeededForRti; 25 Set<ClassElement> classesOnlyNeededForRti;
26 final Map<OutputUnit, List<ClassElement>> outputClassLists = 26 final Map<OutputUnit, List<ClassElement>> outputClassLists =
27 new Map<OutputUnit, List<ClassElement>>(); 27 new Map<OutputUnit, List<ClassElement>>();
28 final Map<OutputUnit, List<ConstantValue>> outputConstantLists = 28 final Map<OutputUnit, List<ConstantValue>> outputConstantLists =
29 new Map<OutputUnit, List<ConstantValue>>(); 29 new Map<OutputUnit, List<ConstantValue>>();
30 final Map<OutputUnit, List<Element>> outputStaticLists = 30 final Map<OutputUnit, List<Element>> outputStaticLists =
31 new Map<OutputUnit, List<Element>>(); 31 new Map<OutputUnit, List<Element>>();
32 final Map<OutputUnit, List<VariableElement>> outputStaticNonFinalFieldLists = 32 final Map<OutputUnit, List<VariableElement>> outputStaticNonFinalFieldLists =
33 new Map<OutputUnit, List<VariableElement>>(); 33 new Map<OutputUnit, List<VariableElement>>();
34 final Map<OutputUnit, Set<LibraryElement>> outputLibraryLists = 34 final Map<OutputUnit, Set<LibraryElement>> outputLibraryLists =
35 new Map<OutputUnit, Set<LibraryElement>>(); 35 new Map<OutputUnit, Set<LibraryElement>>();
36 36
37 /// True, if the output contains a constant list. 37 /// True, if the output contains a constant list.
38 /// 38 ///
39 /// This flag is updated in [computeNeededConstants]. 39 /// This flag is updated in [computeNeededConstants].
40 bool outputContainsConstantList = false; 40 bool outputContainsConstantList = false;
41 41
42 final List<ClassElement> nativeClassesAndSubclasses = <ClassElement>[]; 42 final List<ClassElement> nativeClassesAndSubclasses = <ClassElement>[];
43 43
44 /// Records if a type variable is read dynamically for type tests.
45 final Set<TypeVariableElement> readTypeVariables =
46 new Set<TypeVariableElement>();
47
48 List<TypedefElement> typedefsNeededForReflection; 44 List<TypedefElement> typedefsNeededForReflection;
49 45
50 JavaScriptBackend get backend => compiler.backend; 46 JavaScriptBackend get backend => compiler.backend;
51 47
52 CodeEmitterTask(Compiler compiler, Namer namer, bool generateSourceMap) 48 Collector(this.compiler, this.namer, this.rtiNeededClasses,
53 : super(compiler), 49 this.emitter, this.oldEmitter);
54 this.namer = namer,
55 this.typeTestRegistry = new TypeTestRegistry(compiler) {
56 nativeEmitter = new NativeEmitter(this);
57 oldEmitter = new OldEmitter(compiler, namer, generateSourceMap, this);
58 emitter = USE_LAZY_EMITTER
59 ? new lazy_js_emitter.Emitter(compiler, namer, nativeEmitter)
60 : oldEmitter;
61 metadataCollector = new MetadataCollector(compiler, emitter);
62 }
63
64 String get name => 'Code emitter';
65
66 /// Returns the closure expression of a static function.
67 jsAst.Expression isolateStaticClosureAccess(FunctionElement element) {
68 return emitter.isolateStaticClosureAccess(element);
69 }
70
71 /// Returns the JS function that must be invoked to get the value of the
72 /// lazily initialized static.
73 jsAst.Expression isolateLazyInitializerAccess(FieldElement element) {
74 return emitter.isolateLazyInitializerAccess(element);
75 }
76
77 /// Returns the JS code for accessing the embedded [global].
78 jsAst.Expression generateEmbeddedGlobalAccess(String global) {
79 return emitter.generateEmbeddedGlobalAccess(global);
80 }
81
82 /// Returns the JS code for accessing the given [constant].
83 jsAst.Expression constantReference(ConstantValue constant) {
84 return emitter.constantReference(constant);
85 }
86
87 jsAst.Expression staticFieldAccess(FieldElement e) {
88 return emitter.staticFieldAccess(e);
89 }
90
91 /// Returns the JS function representing the given function.
92 ///
93 /// The function must be invoked and can not be used as closure.
94 jsAst.Expression staticFunctionAccess(FunctionElement e) {
95 return emitter.staticFunctionAccess(e);
96 }
97
98 /// Returns the JS constructor of the given element.
99 ///
100 /// The returned expression must only be used in a JS `new` expression.
101 jsAst.Expression constructorAccess(ClassElement e) {
102 return emitter.constructorAccess(e);
103 }
104
105 /// Returns the JS prototype of the given class [e].
106 jsAst.Expression prototypeAccess(ClassElement e,
107 {bool hasBeenInstantiated: false}) {
108 return emitter.prototypeAccess(e, hasBeenInstantiated);
109 }
110
111 /// Returns the JS prototype of the given interceptor class [e].
112 jsAst.Expression interceptorPrototypeAccess(ClassElement e) {
113 return jsAst.js('#.prototype', interceptorClassAccess(e));
114 }
115
116 /// Returns the JS constructor of the given interceptor class [e].
117 jsAst.Expression interceptorClassAccess(ClassElement e) {
118 return emitter.interceptorClassAccess(e);
119 }
120
121 /// Returns the JS expression representing the type [e].
122 ///
123 /// The given type [e] might be a Typedef.
124 jsAst.Expression typeAccess(Element e) {
125 return emitter.typeAccess(e);
126 }
127
128 /// Returns the JS template for the given [builtin].
129 jsAst.Template builtinTemplateFor(JsBuiltin builtin) {
130 return emitter.templateForBuiltin(builtin);
131 }
132
133 void registerReadTypeVariable(TypeVariableElement element) {
134 readTypeVariables.add(element);
135 }
136 50
137 Set<ClassElement> computeInterceptorsReferencedFromConstants() { 51 Set<ClassElement> computeInterceptorsReferencedFromConstants() {
138 Set<ClassElement> classes = new Set<ClassElement>(); 52 Set<ClassElement> classes = new Set<ClassElement>();
139 JavaScriptConstantCompiler handler = backend.constants; 53 JavaScriptConstantCompiler handler = backend.constants;
140 List<ConstantValue> constants = handler.getConstantsForEmission(); 54 List<ConstantValue> constants = handler.getConstantsForEmission();
141 for (ConstantValue constant in constants) { 55 for (ConstantValue constant in constants) {
142 if (constant is InterceptorConstantValue) { 56 if (constant is InterceptorConstantValue) {
143 InterceptorConstantValue interceptorConstant = constant; 57 InterceptorConstantValue interceptorConstant = constant;
144 classes.add(interceptorConstant.dispatchedType.element); 58 classes.add(interceptorConstant.dispatchedType.element);
145 } 59 }
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 backend.retainMetadataOf); 124 backend.retainMetadataOf);
211 } 125 }
212 } 126 }
213 } 127 }
214 for (ClassElement cls in neededClasses) { 128 for (ClassElement cls in neededClasses) {
215 final onlyForRti = classesOnlyNeededForRti.contains(cls); 129 final onlyForRti = classesOnlyNeededForRti.contains(cls);
216 if (!onlyForRti) { 130 if (!onlyForRti) {
217 backend.retainMetadataOf(cls); 131 backend.retainMetadataOf(cls);
218 oldEmitter.classEmitter.visitFields(cls, false, 132 oldEmitter.classEmitter.visitFields(cls, false,
219 (Element member, 133 (Element member,
220 jsAst.Name name, 134 js.Name name,
221 jsAst.Name accessorName, 135 js.Name accessorName,
222 bool needsGetter, 136 bool needsGetter,
223 bool needsSetter, 137 bool needsSetter,
224 bool needsCheckedSetter) { 138 bool needsCheckedSetter) {
225 bool needsAccessor = needsGetter || needsSetter; 139 bool needsAccessor = needsGetter || needsSetter;
226 if (needsAccessor && backend.isAccessibleByReflection(member)) { 140 if (needsAccessor && backend.isAccessibleByReflection(member)) {
227 backend.retainMetadataOf(member); 141 backend.retainMetadataOf(member);
228 } 142 }
229 }); 143 });
230 } 144 }
231 } 145 }
(...skipping 15 matching lines...) Expand all
247 // some list constants. They are emitted in the main output-unit. 161 // some list constants. They are emitted in the main output-unit.
248 // TODO(sigurdm): We should track those constants. 162 // TODO(sigurdm): We should track those constants.
249 constantUnit = compiler.deferredLoadTask.mainOutputUnit; 163 constantUnit = compiler.deferredLoadTask.mainOutputUnit;
250 } 164 }
251 outputConstantLists.putIfAbsent( 165 outputConstantLists.putIfAbsent(
252 constantUnit, () => new List<ConstantValue>()).add(constant); 166 constantUnit, () => new List<ConstantValue>()).add(constant);
253 } 167 }
254 } 168 }
255 169
256 /// Compute all the classes and typedefs that must be emitted. 170 /// Compute all the classes and typedefs that must be emitted.
257 void computeNeededDeclarations(Set<ClassElement> rtiNeededClasses) { 171 void computeNeededDeclarations() {
258 // Compute needed typedefs. 172 // Compute needed typedefs.
259 typedefsNeededForReflection = Elements.sortedByPosition( 173 typedefsNeededForReflection = Elements.sortedByPosition(
260 compiler.world.allTypedefs 174 compiler.world.allTypedefs
261 .where(backend.isAccessibleByReflection) 175 .where(backend.isAccessibleByReflection)
262 .toList()); 176 .toList());
263 177
264 // Compute needed classes. 178 // Compute needed classes.
265 Set<ClassElement> instantiatedClasses = 179 Set<ClassElement> instantiatedClasses =
266 compiler.codegenWorld.directlyInstantiatedClasses 180 compiler.codegenWorld.directlyInstantiatedClasses
267 .where(computeClassFilter()).toSet(); 181 .where(computeClassFilter()).toSet();
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 } 272 }
359 } 273 }
360 274
361 void computeNeededStaticNonFinalFields() { 275 void computeNeededStaticNonFinalFields() {
362 JavaScriptConstantCompiler handler = backend.constants; 276 JavaScriptConstantCompiler handler = backend.constants;
363 Iterable<VariableElement> staticNonFinalFields = handler 277 Iterable<VariableElement> staticNonFinalFields = handler
364 .getStaticNonFinalFieldsForEmission() 278 .getStaticNonFinalFieldsForEmission()
365 .where(compiler.codegenWorld.allReferencedStaticFields.contains); 279 .where(compiler.codegenWorld.allReferencedStaticFields.contains);
366 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { 280 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) {
367 List<VariableElement> list = outputStaticNonFinalFieldLists.putIfAbsent( 281 List<VariableElement> list = outputStaticNonFinalFieldLists.putIfAbsent(
368 compiler.deferredLoadTask.outputUnitForElement(element), 282 compiler.deferredLoadTask.outputUnitForElement(element),
369 () => new List<VariableElement>()); 283 () => new List<VariableElement>());
370 list.add(element); 284 list.add(element);
371 } 285 }
372 } 286 }
373 287
374 void computeNeededLibraries() { 288 void computeNeededLibraries() {
375 void addSurroundingLibraryToSet(Element element) { 289 void addSurroundingLibraryToSet(Element element) {
376 OutputUnit unit = compiler.deferredLoadTask.outputUnitForElement(element); 290 OutputUnit unit = compiler.deferredLoadTask.outputUnitForElement(element);
377 LibraryElement library = element.library; 291 LibraryElement library = element.library;
378 outputLibraryLists.putIfAbsent(unit, () => new Set<LibraryElement>()) 292 outputLibraryLists.putIfAbsent(unit, () => new Set<LibraryElement>())
379 .add(library); 293 .add(library);
380 } 294 }
381 295
382 backend.generatedCode.keys.forEach(addSurroundingLibraryToSet); 296 backend.generatedCode.keys.forEach(addSurroundingLibraryToSet);
383 neededClasses.forEach(addSurroundingLibraryToSet); 297 neededClasses.forEach(addSurroundingLibraryToSet);
384 } 298 }
385 299
386 void computeAllNeededEntities() { 300 void collect() {
387 // Compute the required type checks to know which classes need a 301 computeNeededDeclarations();
388 // 'is$' method.
389 typeTestRegistry.computeRequiredTypeChecks();
390 // Compute the classes needed by RTI.
391 Set<ClassElement> rtiClasses = typeTestRegistry.computeRtiNeededClasses();
392
393 computeNeededDeclarations(rtiClasses);
394 computeNeededConstants(); 302 computeNeededConstants();
395 computeNeededStatics(); 303 computeNeededStatics();
396 computeNeededStaticNonFinalFields(); 304 computeNeededStaticNonFinalFields();
397 computeNeededLibraries(); 305 computeNeededLibraries();
398 } 306 }
399 307 }
400 int assembleProgram() {
401 return measure(() {
402 emitter.invalidateCaches();
403
404 computeAllNeededEntities();
405
406 ProgramBuilder programBuilder = new ProgramBuilder(compiler, namer, this);
407 return emitter.emitProgram(programBuilder);
408 });
409 }
410 }
411
412 abstract class Emitter {
413 /// Uses the [programBuilder] to generate a model of the program, emits
414 /// the program, and returns the size of the generated output.
415 int emitProgram(ProgramBuilder programBuilder);
416
417 /// Returns the JS function that must be invoked to get the value of the
418 /// lazily initialized static.
419 jsAst.Expression isolateLazyInitializerAccess(FieldElement element);
420
421 /// Returns the closure expression of a static function.
422 jsAst.Expression isolateStaticClosureAccess(FunctionElement element);
423
424 /// Returns the JS code for accessing the embedded [global].
425 jsAst.Expression generateEmbeddedGlobalAccess(String global);
426
427 /// Returns the JS function representing the given function.
428 ///
429 /// The function must be invoked and can not be used as closure.
430 jsAst.Expression staticFunctionAccess(FunctionElement element);
431
432 jsAst.Expression staticFieldAccess(FieldElement element);
433
434 /// Returns the JS constructor of the given element.
435 ///
436 /// The returned expression must only be used in a JS `new` expression.
437 jsAst.Expression constructorAccess(ClassElement e);
438
439 /// Returns the JS prototype of the given class [e].
440 jsAst.Expression prototypeAccess(ClassElement e, bool hasBeenInstantiated);
441
442 /// Returns the JS constructor of the given interceptor class [e].
443 jsAst.Expression interceptorClassAccess(ClassElement e);
444
445 /// Returns the JS expression representing the type [e].
446 jsAst.Expression typeAccess(Element e);
447
448 /// Returns the JS expression representing a function that returns 'null'
449 jsAst.Expression generateFunctionThatReturnsNull();
450
451 int compareConstants(ConstantValue a, ConstantValue b);
452 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant);
453
454 /// Returns the JS code for accessing the given [constant].
455 jsAst.Expression constantReference(ConstantValue constant);
456
457 /// Returns the JS template for the given [builtin].
458 jsAst.Template templateForBuiltin(JsBuiltin builtin);
459
460 void invalidateCaches();
461 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698