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

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

Issue 1214723010: dart2js: Make it more obvious how rti-only needed classes work. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Address comment. 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
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 part of dart2js.js_emitter; 5 part of dart2js.js_emitter;
6 6
7 const USE_LAZY_EMITTER = const bool.fromEnvironment("dart2js.use.lazy.emitter"); 7 const USE_LAZY_EMITTER = const bool.fromEnvironment("dart2js.use.lazy.emitter");
8 8
9 /** 9 /**
10 * Generates the code for all used classes in the program. Static fields (even 10 * 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. 11 * in classes) are ignored, since they can be treated as non-class elements.
12 * 12 *
13 * The code for the containing (used) methods must exist in the `universe`. 13 * The code for the containing (used) methods must exist in the `universe`.
14 */ 14 */
15 class CodeEmitterTask extends CompilerTask { 15 class CodeEmitterTask extends CompilerTask {
16 // TODO(floitsch): the code-emitter task should not need a namer. 16 // TODO(floitsch): the code-emitter task should not need a namer.
17 final Namer namer; 17 final Namer namer;
18 final TypeTestRegistry typeTestRegistry; 18 final TypeTestRegistry typeTestRegistry;
19 NativeEmitter nativeEmitter; 19 NativeEmitter nativeEmitter;
20 MetadataCollector metadataCollector; 20 MetadataCollector metadataCollector;
21 OldEmitter oldEmitter; 21 OldEmitter oldEmitter;
22 Emitter emitter; 22 Emitter emitter;
23 23
24 final Set<ClassElement> neededClasses = new Set<ClassElement>(); 24 final Set<ClassElement> neededClasses = new Set<ClassElement>();
25 Set<ClassElement> classesOnlyNeededForRti;
25 final Map<OutputUnit, List<ClassElement>> outputClassLists = 26 final Map<OutputUnit, List<ClassElement>> outputClassLists =
26 new Map<OutputUnit, List<ClassElement>>(); 27 new Map<OutputUnit, List<ClassElement>>();
27 final Map<OutputUnit, List<ConstantValue>> outputConstantLists = 28 final Map<OutputUnit, List<ConstantValue>> outputConstantLists =
28 new Map<OutputUnit, List<ConstantValue>>(); 29 new Map<OutputUnit, List<ConstantValue>>();
29 final Map<OutputUnit, List<Element>> outputStaticLists = 30 final Map<OutputUnit, List<Element>> outputStaticLists =
30 new Map<OutputUnit, List<Element>>(); 31 new Map<OutputUnit, List<Element>>();
31 final Map<OutputUnit, List<VariableElement>> outputStaticNonFinalFieldLists = 32 final Map<OutputUnit, List<VariableElement>> outputStaticNonFinalFieldLists =
32 new Map<OutputUnit, List<VariableElement>>(); 33 new Map<OutputUnit, List<VariableElement>>();
33 final Map<OutputUnit, Set<LibraryElement>> outputLibraryLists = 34 final Map<OutputUnit, Set<LibraryElement>> outputLibraryLists =
34 new Map<OutputUnit, Set<LibraryElement>>(); 35 new Map<OutputUnit, Set<LibraryElement>>();
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 if (shouldRetainMetadata && 205 if (shouldRetainMetadata &&
205 (element.isFunction || element.isConstructor || 206 (element.isFunction || element.isConstructor ||
206 element.isSetter)) { 207 element.isSetter)) {
207 FunctionElement function = element; 208 FunctionElement function = element;
208 function.functionSignature.forEachParameter( 209 function.functionSignature.forEachParameter(
209 backend.retainMetadataOf); 210 backend.retainMetadataOf);
210 } 211 }
211 } 212 }
212 } 213 }
213 for (ClassElement cls in neededClasses) { 214 for (ClassElement cls in neededClasses) {
214 final onlyForRti = typeTestRegistry.rtiNeededClasses.contains(cls); 215 final onlyForRti = classesOnlyNeededForRti.contains(cls);
215 if (!onlyForRti) { 216 if (!onlyForRti) {
216 backend.retainMetadataOf(cls); 217 backend.retainMetadataOf(cls);
217 oldEmitter.classEmitter.visitFields(cls, false, 218 oldEmitter.classEmitter.visitFields(cls, false,
218 (Element member, 219 (Element member,
219 jsAst.Name name, 220 jsAst.Name name,
220 jsAst.Name accessorName, 221 jsAst.Name accessorName,
221 bool needsGetter, 222 bool needsGetter,
222 bool needsSetter, 223 bool needsSetter,
223 bool needsCheckedSetter) { 224 bool needsCheckedSetter) {
224 bool needsAccessor = needsGetter || needsSetter; 225 bool needsAccessor = needsGetter || needsSetter;
(...skipping 21 matching lines...) Expand all
246 // some list constants. They are emitted in the main output-unit. 247 // some list constants. They are emitted in the main output-unit.
247 // TODO(sigurdm): We should track those constants. 248 // TODO(sigurdm): We should track those constants.
248 constantUnit = compiler.deferredLoadTask.mainOutputUnit; 249 constantUnit = compiler.deferredLoadTask.mainOutputUnit;
249 } 250 }
250 outputConstantLists.putIfAbsent( 251 outputConstantLists.putIfAbsent(
251 constantUnit, () => new List<ConstantValue>()).add(constant); 252 constantUnit, () => new List<ConstantValue>()).add(constant);
252 } 253 }
253 } 254 }
254 255
255 /// Compute all the classes and typedefs that must be emitted. 256 /// Compute all the classes and typedefs that must be emitted.
256 void computeNeededDeclarations() { 257 void computeNeededDeclarations(Set<ClassElement> rtiNeededClasses) {
257 // Compute needed typedefs. 258 // Compute needed typedefs.
258 typedefsNeededForReflection = Elements.sortedByPosition( 259 typedefsNeededForReflection = Elements.sortedByPosition(
259 compiler.world.allTypedefs 260 compiler.world.allTypedefs
260 .where(backend.isAccessibleByReflection) 261 .where(backend.isAccessibleByReflection)
261 .toList()); 262 .toList());
262 263
263 // Compute needed classes. 264 // Compute needed classes.
264 Set<ClassElement> instantiatedClasses = 265 Set<ClassElement> instantiatedClasses =
265 compiler.codegenWorld.directlyInstantiatedClasses 266 compiler.codegenWorld.directlyInstantiatedClasses
266 .where(computeClassFilter()).toSet(); 267 .where(computeClassFilter()).toSet();
(...skipping 23 matching lines...) Expand all
290 .toSet(); 291 .toSet();
291 neededClasses.addAll(mixinClasses); 292 neededClasses.addAll(mixinClasses);
292 293
293 // 3. Find all classes needed for rti. 294 // 3. Find all classes needed for rti.
294 // It is important that this is the penultimate step, at this point, 295 // It is important that this is the penultimate step, at this point,
295 // neededClasses must only contain classes that have been resolved and 296 // neededClasses must only contain classes that have been resolved and
296 // codegen'd. The rtiNeededClasses may contain additional classes, but 297 // codegen'd. The rtiNeededClasses may contain additional classes, but
297 // these are thought to not have been instantiated, so we neeed to be able 298 // these are thought to not have been instantiated, so we neeed to be able
298 // to identify them later and make sure we only emit "empty shells" without 299 // to identify them later and make sure we only emit "empty shells" without
299 // fields, etc. 300 // fields, etc.
300 typeTestRegistry.computeRtiNeededClasses(); 301 classesOnlyNeededForRti = rtiNeededClasses.difference(neededClasses);
301 302
302 // TODO(floitsch): either change the name, or get the rti-classes 303 neededClasses.addAll(classesOnlyNeededForRti);
303 // differently.
304 typeTestRegistry.rtiNeededClasses.removeAll(neededClasses);
305 // rtiNeededClasses now contains only the "empty shells".
306 neededClasses.addAll(typeTestRegistry.rtiNeededClasses);
307 304
308 // TODO(18175, floitsch): remove once issue 18175 is fixed. 305 // TODO(18175, floitsch): remove once issue 18175 is fixed.
309 if (neededClasses.contains(backend.jsIntClass)) { 306 if (neededClasses.contains(backend.jsIntClass)) {
310 neededClasses.add(compiler.intClass); 307 neededClasses.add(compiler.intClass);
311 } 308 }
312 if (neededClasses.contains(backend.jsDoubleClass)) { 309 if (neededClasses.contains(backend.jsDoubleClass)) {
313 neededClasses.add(compiler.doubleClass); 310 neededClasses.add(compiler.doubleClass);
314 } 311 }
315 if (neededClasses.contains(backend.jsNumberClass)) { 312 if (neededClasses.contains(backend.jsNumberClass)) {
316 neededClasses.add(compiler.numClass); 313 neededClasses.add(compiler.numClass);
317 } 314 }
318 if (neededClasses.contains(backend.jsStringClass)) { 315 if (neededClasses.contains(backend.jsStringClass)) {
319 neededClasses.add(compiler.stringClass); 316 neededClasses.add(compiler.stringClass);
320 } 317 }
321 if (neededClasses.contains(backend.jsBoolClass)) { 318 if (neededClasses.contains(backend.jsBoolClass)) {
322 neededClasses.add(compiler.boolClass); 319 neededClasses.add(compiler.boolClass);
323 } 320 }
324 if (neededClasses.contains(backend.jsArrayClass)) { 321 if (neededClasses.contains(backend.jsArrayClass)) {
325 neededClasses.add(compiler.listClass); 322 neededClasses.add(compiler.listClass);
326 } 323 }
327 324
328 // 4. Finally, sort the classes. 325 // 4. Finally, sort the classes.
329 List<ClassElement> sortedClasses = Elements.sortedByPosition(neededClasses); 326 List<ClassElement> sortedClasses = Elements.sortedByPosition(neededClasses);
330 327
331 for (ClassElement element in sortedClasses) { 328 for (ClassElement element in sortedClasses) {
332 if (Elements.isNativeOrExtendsNative(element) && 329 if (Elements.isNativeOrExtendsNative(element) &&
333 !typeTestRegistry.rtiNeededClasses.contains(element)) { 330 !classesOnlyNeededForRti.contains(element)) {
334 // For now, native classes and related classes cannot be deferred. 331 // For now, native classes and related classes cannot be deferred.
335 nativeClassesAndSubclasses.add(element); 332 nativeClassesAndSubclasses.add(element);
336 assert(invariant(element, 333 assert(invariant(element,
337 !compiler.deferredLoadTask.isDeferred(element))); 334 !compiler.deferredLoadTask.isDeferred(element)));
338 outputClassLists.putIfAbsent(compiler.deferredLoadTask.mainOutputUnit, 335 outputClassLists.putIfAbsent(compiler.deferredLoadTask.mainOutputUnit,
339 () => new List<ClassElement>()).add(element); 336 () => new List<ClassElement>()).add(element);
340 } else { 337 } else {
341 outputClassLists.putIfAbsent( 338 outputClassLists.putIfAbsent(
342 compiler.deferredLoadTask.outputUnitForElement(element), 339 compiler.deferredLoadTask.outputUnitForElement(element),
343 () => new List<ClassElement>()) 340 () => new List<ClassElement>())
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 } 380 }
384 381
385 backend.generatedCode.keys.forEach(addSurroundingLibraryToSet); 382 backend.generatedCode.keys.forEach(addSurroundingLibraryToSet);
386 neededClasses.forEach(addSurroundingLibraryToSet); 383 neededClasses.forEach(addSurroundingLibraryToSet);
387 } 384 }
388 385
389 void computeAllNeededEntities() { 386 void computeAllNeededEntities() {
390 // Compute the required type checks to know which classes need a 387 // Compute the required type checks to know which classes need a
391 // 'is$' method. 388 // 'is$' method.
392 typeTestRegistry.computeRequiredTypeChecks(); 389 typeTestRegistry.computeRequiredTypeChecks();
390 // Compute the classes needed by RTI.
391 Set<ClassElement> rtiClasses = typeTestRegistry.computeRtiNeededClasses();
393 392
394 computeNeededDeclarations(); 393 computeNeededDeclarations(rtiClasses);
395 computeNeededConstants(); 394 computeNeededConstants();
396 computeNeededStatics(); 395 computeNeededStatics();
397 computeNeededStaticNonFinalFields(); 396 computeNeededStaticNonFinalFields();
398 computeNeededLibraries(); 397 computeNeededLibraries();
399 } 398 }
400 399
401 int assembleProgram() { 400 int assembleProgram() {
402 return measure(() { 401 return measure(() {
403 emitter.invalidateCaches(); 402 emitter.invalidateCaches();
404 403
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant); 452 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant);
454 453
455 /// Returns the JS code for accessing the given [constant]. 454 /// Returns the JS code for accessing the given [constant].
456 jsAst.Expression constantReference(ConstantValue constant); 455 jsAst.Expression constantReference(ConstantValue constant);
457 456
458 /// Returns the JS template for the given [builtin]. 457 /// Returns the JS template for the given [builtin].
459 jsAst.Template templateForBuiltin(JsBuiltin builtin); 458 jsAst.Template templateForBuiltin(JsBuiltin builtin);
460 459
461 void invalidateCaches(); 460 void invalidateCaches();
462 } 461 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698