| OLD | NEW |
| 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_NEW_EMITTER = const bool.fromEnvironment("dart2js.use.new.emitter"); | 7 const USE_NEW_EMITTER = const bool.fromEnvironment("dart2js.use.new.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 TypeTestEmitter typeTestEmitter = new TypeTestEmitter(); | 18 final TypeTestEmitter typeTestEmitter = new TypeTestEmitter(); |
| 19 NativeEmitter nativeEmitter; | 19 NativeEmitter nativeEmitter; |
| 20 OldEmitter oldEmitter; | 20 OldEmitter oldEmitter; |
| 21 Emitter emitter; | 21 Emitter emitter; |
| 22 | 22 |
| 23 final Set<ClassElement> neededClasses = new Set<ClassElement>(); | 23 final Set<ClassElement> neededClasses = new Set<ClassElement>(); |
| 24 final Map<OutputUnit, List<ClassElement>> outputClassLists = | 24 final Map<OutputUnit, List<ClassElement>> outputClassLists = |
| 25 new Map<OutputUnit, List<ClassElement>>(); | 25 new Map<OutputUnit, List<ClassElement>>(); |
| 26 final Map<OutputUnit, List<Constant>> outputConstantLists = | 26 final Map<OutputUnit, List<ConstantValue>> outputConstantLists = |
| 27 new Map<OutputUnit, List<Constant>>(); | 27 new Map<OutputUnit, List<ConstantValue>>(); |
| 28 final List<ClassElement> nativeClasses = <ClassElement>[]; | 28 final List<ClassElement> nativeClasses = <ClassElement>[]; |
| 29 | 29 |
| 30 /// Records if a type variable is read dynamically for type tests. | 30 /// Records if a type variable is read dynamically for type tests. |
| 31 final Set<TypeVariableElement> readTypeVariables = | 31 final Set<TypeVariableElement> readTypeVariables = |
| 32 new Set<TypeVariableElement>(); | 32 new Set<TypeVariableElement>(); |
| 33 | 33 |
| 34 // TODO(ngeoffray): remove this field. | 34 // TODO(ngeoffray): remove this field. |
| 35 Set<ClassElement> instantiatedClasses; | 35 Set<ClassElement> instantiatedClasses; |
| 36 List<TypedefElement> typedefsNeededForReflection; | 36 List<TypedefElement> typedefsNeededForReflection; |
| 37 | 37 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 49 // TODO(18886): Remove this call (and the show in the import) once the | 49 // TODO(18886): Remove this call (and the show in the import) once the |
| 50 // memory-leak in the VM is fixed. | 50 // memory-leak in the VM is fixed. |
| 51 templateManager.clear(); | 51 templateManager.clear(); |
| 52 } | 52 } |
| 53 | 53 |
| 54 | 54 |
| 55 jsAst.Expression generateEmbeddedGlobalAccess(String global) { | 55 jsAst.Expression generateEmbeddedGlobalAccess(String global) { |
| 56 return emitter.generateEmbeddedGlobalAccess(global); | 56 return emitter.generateEmbeddedGlobalAccess(global); |
| 57 } | 57 } |
| 58 | 58 |
| 59 jsAst.Expression constantReference(Constant value) { | 59 jsAst.Expression constantReference(ConstantValue value) { |
| 60 return emitter.constantReference(value); | 60 return emitter.constantReference(value); |
| 61 } | 61 } |
| 62 | 62 |
| 63 Set<ClassElement> interceptorsReferencedFromConstants() { | 63 Set<ClassElement> interceptorsReferencedFromConstants() { |
| 64 Set<ClassElement> classes = new Set<ClassElement>(); | 64 Set<ClassElement> classes = new Set<ClassElement>(); |
| 65 JavaScriptConstantCompiler handler = backend.constants; | 65 JavaScriptConstantCompiler handler = backend.constants; |
| 66 List<Constant> constants = handler.getConstantsForEmission(); | 66 List<ConstantValue> constants = handler.getConstantsForEmission(); |
| 67 for (Constant constant in constants) { | 67 for (ConstantValue constant in constants) { |
| 68 if (constant is InterceptorConstant) { | 68 if (constant is InterceptorConstantValue) { |
| 69 InterceptorConstant interceptorConstant = constant; | 69 InterceptorConstantValue interceptorConstant = constant; |
| 70 classes.add(interceptorConstant.dispatchedType.element); | 70 classes.add(interceptorConstant.dispatchedType.element); |
| 71 } | 71 } |
| 72 } | 72 } |
| 73 return classes; | 73 return classes; |
| 74 } | 74 } |
| 75 | 75 |
| 76 /** | 76 /** |
| 77 * Return a function that returns true if its argument is a class | 77 * Return a function that returns true if its argument is a class |
| 78 * that needs to be emitted. | 78 * that needs to be emitted. |
| 79 */ | 79 */ |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 unneededClasses.add(backend.jsPositiveIntClass); | 114 unneededClasses.add(backend.jsPositiveIntClass); |
| 115 | 115 |
| 116 return (ClassElement cls) => !unneededClasses.contains(cls); | 116 return (ClassElement cls) => !unneededClasses.contains(cls); |
| 117 } | 117 } |
| 118 | 118 |
| 119 /** | 119 /** |
| 120 * Compute all the constants that must be emitted. | 120 * Compute all the constants that must be emitted. |
| 121 */ | 121 */ |
| 122 void computeNeededConstants() { | 122 void computeNeededConstants() { |
| 123 JavaScriptConstantCompiler handler = backend.constants; | 123 JavaScriptConstantCompiler handler = backend.constants; |
| 124 List<Constant> constants = handler.getConstantsForEmission( | 124 List<ConstantValue> constants = handler.getConstantsForEmission( |
| 125 compiler.hasIncrementalSupport ? null : emitter.compareConstants); | 125 compiler.hasIncrementalSupport ? null : emitter.compareConstants); |
| 126 for (Constant constant in constants) { | 126 for (ConstantValue constant in constants) { |
| 127 if (emitter.isConstantInlinedOrAlreadyEmitted(constant)) continue; | 127 if (emitter.isConstantInlinedOrAlreadyEmitted(constant)) continue; |
| 128 OutputUnit constantUnit = | 128 OutputUnit constantUnit = |
| 129 compiler.deferredLoadTask.outputUnitForConstant(constant); | 129 compiler.deferredLoadTask.outputUnitForConstant(constant); |
| 130 if (constantUnit == null) { | 130 if (constantUnit == null) { |
| 131 // The back-end introduces some constants, like "InterceptorConstant" or | 131 // The back-end introduces some constants, like "InterceptorConstant" or |
| 132 // some list constants. They are emitted in the main output-unit. | 132 // some list constants. They are emitted in the main output-unit. |
| 133 // TODO(sigurdm): We should track those constants. | 133 // TODO(sigurdm): We should track those constants. |
| 134 constantUnit = compiler.deferredLoadTask.mainOutputUnit; | 134 constantUnit = compiler.deferredLoadTask.mainOutputUnit; |
| 135 } | 135 } |
| 136 outputConstantLists.putIfAbsent(constantUnit, () => new List<Constant>()) | 136 outputConstantLists.putIfAbsent(constantUnit, () => new List<ConstantValue
>()) |
| 137 .add(constant); | 137 .add(constant); |
| 138 } | 138 } |
| 139 } | 139 } |
| 140 | 140 |
| 141 /// Compute all the classes and typedefs that must be emitted. | 141 /// Compute all the classes and typedefs that must be emitted. |
| 142 void computeNeededDeclarations() { | 142 void computeNeededDeclarations() { |
| 143 // Compute needed typedefs. | 143 // Compute needed typedefs. |
| 144 typedefsNeededForReflection = Elements.sortedByPosition( | 144 typedefsNeededForReflection = Elements.sortedByPosition( |
| 145 compiler.world.allTypedefs | 145 compiler.world.allTypedefs |
| 146 .where(backend.isAccessibleByReflection) | 146 .where(backend.isAccessibleByReflection) |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 | 269 |
| 270 void registerReadTypeVariable(TypeVariableElement element) { | 270 void registerReadTypeVariable(TypeVariableElement element) { |
| 271 readTypeVariables.add(element); | 271 readTypeVariables.add(element); |
| 272 } | 272 } |
| 273 } | 273 } |
| 274 | 274 |
| 275 abstract class Emitter { | 275 abstract class Emitter { |
| 276 void emitProgram(); | 276 void emitProgram(); |
| 277 | 277 |
| 278 jsAst.Expression generateEmbeddedGlobalAccess(String global); | 278 jsAst.Expression generateEmbeddedGlobalAccess(String global); |
| 279 jsAst.Expression constantReference(Constant value); | 279 jsAst.Expression constantReference(ConstantValue value); |
| 280 | 280 |
| 281 int compareConstants(Constant a, Constant b); | 281 int compareConstants(ConstantValue a, ConstantValue b); |
| 282 bool isConstantInlinedOrAlreadyEmitted(Constant constant); | 282 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant); |
| 283 | 283 |
| 284 void invalidateCaches(); | 284 void invalidateCaches(); |
| 285 } | 285 } |
| OLD | NEW |