| 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 library dart2js.js_emitter.code_emitter_task; | 5 library dart2js.js_emitter.code_emitter_task; |
| 6 | 6 |
| 7 import 'package:js_runtime/shared/embedded_names.dart' show JsBuiltin; | 7 import 'package:js_runtime/shared/embedded_names.dart' show JsBuiltin; |
| 8 | 8 |
| 9 import '../common.dart'; | 9 import '../common.dart'; |
| 10 import '../common/tasks.dart' show CompilerTask; | 10 import '../common/tasks.dart' show CompilerTask; |
| 11 import '../compiler.dart' show Compiler; | 11 import '../compiler.dart' show Compiler; |
| 12 import '../constants/values.dart'; | 12 import '../constants/values.dart'; |
| 13 import '../elements/elements.dart' | 13 import '../elements/elements.dart' show Entity; |
| 14 show | 14 import '../elements/entities.dart'; |
| 15 ClassElement, | |
| 16 Entity, | |
| 17 FieldElement, | |
| 18 FunctionElement, | |
| 19 MethodElement, | |
| 20 TypeVariableElement; | |
| 21 import '../js/js.dart' as jsAst; | 15 import '../js/js.dart' as jsAst; |
| 22 import '../js_backend/js_backend.dart' show JavaScriptBackend, Namer; | 16 import '../js_backend/js_backend.dart' show JavaScriptBackend, Namer; |
| 23 import '../world.dart' show ClosedWorld; | 17 import '../world.dart' show ClosedWorld; |
| 24 import 'full_emitter/emitter.dart' as full_js_emitter; | 18 import 'full_emitter/emitter.dart' as full_js_emitter; |
| 25 import 'lazy_emitter/emitter.dart' as lazy_js_emitter; | 19 import 'lazy_emitter/emitter.dart' as lazy_js_emitter; |
| 26 import 'program_builder/program_builder.dart'; | 20 import 'program_builder/program_builder.dart'; |
| 27 import 'startup_emitter/emitter.dart' as startup_js_emitter; | 21 import 'startup_emitter/emitter.dart' as startup_js_emitter; |
| 28 | 22 |
| 29 import 'metadata_collector.dart' show MetadataCollector; | 23 import 'metadata_collector.dart' show MetadataCollector; |
| 30 import 'native_emitter.dart' show NativeEmitter; | 24 import 'native_emitter.dart' show NativeEmitter; |
| 31 import 'type_test_registry.dart' show TypeTestRegistry; | 25 import 'type_test_registry.dart' show TypeTestRegistry; |
| 32 | 26 |
| 33 const USE_LAZY_EMITTER = const bool.fromEnvironment("dart2js.use.lazy.emitter"); | 27 const USE_LAZY_EMITTER = const bool.fromEnvironment("dart2js.use.lazy.emitter"); |
| 34 | 28 |
| 35 /** | 29 /** |
| 36 * Generates the code for all used classes in the program. Static fields (even | 30 * Generates the code for all used classes in the program. Static fields (even |
| 37 * in classes) are ignored, since they can be treated as non-class elements. | 31 * in classes) are ignored, since they can be treated as non-class elements. |
| 38 * | 32 * |
| 39 * The code for the containing (used) methods must exist in the `universe`. | 33 * The code for the containing (used) methods must exist in the `universe`. |
| 40 */ | 34 */ |
| 41 class CodeEmitterTask extends CompilerTask { | 35 class CodeEmitterTask extends CompilerTask { |
| 42 TypeTestRegistry typeTestRegistry; | 36 TypeTestRegistry typeTestRegistry; |
| 43 NativeEmitter nativeEmitter; | 37 NativeEmitter nativeEmitter; |
| 44 MetadataCollector metadataCollector; | 38 MetadataCollector metadataCollector; |
| 45 EmitterFactory _emitterFactory; | 39 EmitterFactory _emitterFactory; |
| 46 Emitter _emitter; | 40 Emitter _emitter; |
| 47 final Compiler compiler; | 41 final Compiler compiler; |
| 48 | 42 |
| 49 /// Records if a type variable is read dynamically for type tests. | 43 /// Records if a type variable is read dynamically for type tests. |
| 50 final Set<TypeVariableElement> readTypeVariables = | 44 final Set<TypeVariableEntity> readTypeVariables = |
| 51 new Set<TypeVariableElement>(); | 45 new Set<TypeVariableEntity>(); |
| 52 | 46 |
| 53 JavaScriptBackend get backend => compiler.backend; | 47 JavaScriptBackend get backend => compiler.backend; |
| 54 | 48 |
| 55 @deprecated | 49 @deprecated |
| 56 // This field should be removed. It's currently only needed for dump-info and | 50 // This field should be removed. It's currently only needed for dump-info and |
| 57 // tests. | 51 // tests. |
| 58 // The field is set after the program has been emitted. | 52 // The field is set after the program has been emitted. |
| 59 /// Contains a list of all classes that are emitted. | 53 /// Contains a list of all classes that are emitted. |
| 60 Set<ClassElement> neededClasses; | 54 Set<ClassEntity> neededClasses; |
| 61 | 55 |
| 62 CodeEmitterTask( | 56 CodeEmitterTask( |
| 63 Compiler compiler, bool generateSourceMap, bool useStartupEmitter) | 57 Compiler compiler, bool generateSourceMap, bool useStartupEmitter) |
| 64 : compiler = compiler, | 58 : compiler = compiler, |
| 65 super(compiler.measurer) { | 59 super(compiler.measurer) { |
| 66 nativeEmitter = new NativeEmitter(this); | 60 nativeEmitter = new NativeEmitter(this); |
| 67 if (USE_LAZY_EMITTER) { | 61 if (USE_LAZY_EMITTER) { |
| 68 _emitterFactory = new lazy_js_emitter.EmitterFactory(); | 62 _emitterFactory = new lazy_js_emitter.EmitterFactory(); |
| 69 } else if (useStartupEmitter) { | 63 } else if (useStartupEmitter) { |
| 70 _emitterFactory = new startup_js_emitter.EmitterFactory( | 64 _emitterFactory = new startup_js_emitter.EmitterFactory( |
| (...skipping 13 matching lines...) Expand all Loading... |
| 84 String get name => 'Code emitter'; | 78 String get name => 'Code emitter'; |
| 85 | 79 |
| 86 /// Returns the string that is used to find library patches that are | 80 /// Returns the string that is used to find library patches that are |
| 87 /// specialized for the emitter. | 81 /// specialized for the emitter. |
| 88 String get patchVersion => _emitterFactory.patchVersion; | 82 String get patchVersion => _emitterFactory.patchVersion; |
| 89 | 83 |
| 90 /// Returns true, if the emitter supports reflection. | 84 /// Returns true, if the emitter supports reflection. |
| 91 bool get supportsReflection => _emitterFactory.supportsReflection; | 85 bool get supportsReflection => _emitterFactory.supportsReflection; |
| 92 | 86 |
| 93 /// Returns the closure expression of a static function. | 87 /// Returns the closure expression of a static function. |
| 94 jsAst.Expression isolateStaticClosureAccess(MethodElement element) { | 88 jsAst.Expression isolateStaticClosureAccess(FunctionEntity element) { |
| 95 return emitter.isolateStaticClosureAccess(element); | 89 return emitter.isolateStaticClosureAccess(element); |
| 96 } | 90 } |
| 97 | 91 |
| 98 /// Returns the JS function that must be invoked to get the value of the | 92 /// Returns the JS function that must be invoked to get the value of the |
| 99 /// lazily initialized static. | 93 /// lazily initialized static. |
| 100 jsAst.Expression isolateLazyInitializerAccess(FieldElement element) { | 94 jsAst.Expression isolateLazyInitializerAccess(FieldEntity element) { |
| 101 return emitter.isolateLazyInitializerAccess(element); | 95 return emitter.isolateLazyInitializerAccess(element); |
| 102 } | 96 } |
| 103 | 97 |
| 104 /// Returns the JS code for accessing the embedded [global]. | 98 /// Returns the JS code for accessing the embedded [global]. |
| 105 jsAst.Expression generateEmbeddedGlobalAccess(String global) { | 99 jsAst.Expression generateEmbeddedGlobalAccess(String global) { |
| 106 return emitter.generateEmbeddedGlobalAccess(global); | 100 return emitter.generateEmbeddedGlobalAccess(global); |
| 107 } | 101 } |
| 108 | 102 |
| 109 /// Returns the JS code for accessing the given [constant]. | 103 /// Returns the JS code for accessing the given [constant]. |
| 110 jsAst.Expression constantReference(ConstantValue constant) { | 104 jsAst.Expression constantReference(ConstantValue constant) { |
| 111 return emitter.constantReference(constant); | 105 return emitter.constantReference(constant); |
| 112 } | 106 } |
| 113 | 107 |
| 114 jsAst.Expression staticFieldAccess(FieldElement e) { | 108 jsAst.Expression staticFieldAccess(FieldEntity e) { |
| 115 return emitter.staticFieldAccess(e); | 109 return emitter.staticFieldAccess(e); |
| 116 } | 110 } |
| 117 | 111 |
| 118 /// Returns the JS function representing the given function. | 112 /// Returns the JS function representing the given function. |
| 119 /// | 113 /// |
| 120 /// The function must be invoked and can not be used as closure. | 114 /// The function must be invoked and can not be used as closure. |
| 121 jsAst.Expression staticFunctionAccess(MethodElement e) { | 115 jsAst.Expression staticFunctionAccess(FunctionEntity e) { |
| 122 return emitter.staticFunctionAccess(e); | 116 return emitter.staticFunctionAccess(e); |
| 123 } | 117 } |
| 124 | 118 |
| 125 /// Returns the JS constructor of the given element. | 119 /// Returns the JS constructor of the given element. |
| 126 /// | 120 /// |
| 127 /// The returned expression must only be used in a JS `new` expression. | 121 /// The returned expression must only be used in a JS `new` expression. |
| 128 jsAst.Expression constructorAccess(ClassElement e) { | 122 jsAst.Expression constructorAccess(ClassEntity e) { |
| 129 return emitter.constructorAccess(e); | 123 return emitter.constructorAccess(e); |
| 130 } | 124 } |
| 131 | 125 |
| 132 /// Returns the JS prototype of the given class [e]. | 126 /// Returns the JS prototype of the given class [e]. |
| 133 jsAst.Expression prototypeAccess(ClassElement e, | 127 jsAst.Expression prototypeAccess(ClassEntity e, |
| 134 {bool hasBeenInstantiated: false}) { | 128 {bool hasBeenInstantiated: false}) { |
| 135 return emitter.prototypeAccess(e, hasBeenInstantiated); | 129 return emitter.prototypeAccess(e, hasBeenInstantiated); |
| 136 } | 130 } |
| 137 | 131 |
| 138 /// Returns the JS prototype of the given interceptor class [e]. | 132 /// Returns the JS prototype of the given interceptor class [e]. |
| 139 jsAst.Expression interceptorPrototypeAccess(ClassElement e) { | 133 jsAst.Expression interceptorPrototypeAccess(ClassEntity e) { |
| 140 return jsAst.js('#.prototype', interceptorClassAccess(e)); | 134 return jsAst.js('#.prototype', interceptorClassAccess(e)); |
| 141 } | 135 } |
| 142 | 136 |
| 143 /// Returns the JS constructor of the given interceptor class [e]. | 137 /// Returns the JS constructor of the given interceptor class [e]. |
| 144 jsAst.Expression interceptorClassAccess(ClassElement e) { | 138 jsAst.Expression interceptorClassAccess(ClassEntity e) { |
| 145 return emitter.interceptorClassAccess(e); | 139 return emitter.interceptorClassAccess(e); |
| 146 } | 140 } |
| 147 | 141 |
| 148 /// Returns the JS expression representing the type [e]. | 142 /// Returns the JS expression representing the type [e]. |
| 149 /// | 143 /// |
| 150 /// The given type [e] might be a Typedef. | 144 /// The given type [e] might be a Typedef. |
| 151 jsAst.Expression typeAccess(Entity e) { | 145 jsAst.Expression typeAccess(Entity e) { |
| 152 return emitter.typeAccess(e); | 146 return emitter.typeAccess(e); |
| 153 } | 147 } |
| 154 | 148 |
| 155 /// Returns the JS template for the given [builtin]. | 149 /// Returns the JS template for the given [builtin]. |
| 156 jsAst.Template builtinTemplateFor(JsBuiltin builtin) { | 150 jsAst.Template builtinTemplateFor(JsBuiltin builtin) { |
| 157 return emitter.templateForBuiltin(builtin); | 151 return emitter.templateForBuiltin(builtin); |
| 158 } | 152 } |
| 159 | 153 |
| 160 void registerReadTypeVariable(TypeVariableElement element) { | 154 void registerReadTypeVariable(TypeVariableEntity element) { |
| 161 readTypeVariables.add(element); | 155 readTypeVariables.add(element); |
| 162 } | 156 } |
| 163 | 157 |
| 164 Set<ClassElement> _finalizeRti() { | 158 Set<ClassEntity> _finalizeRti() { |
| 165 // Compute the required type checks to know which classes need a | 159 // Compute the required type checks to know which classes need a |
| 166 // 'is$' method. | 160 // 'is$' method. |
| 167 typeTestRegistry.computeRequiredTypeChecks(); | 161 typeTestRegistry.computeRequiredTypeChecks(); |
| 168 // Compute the classes needed by RTI. | 162 // Compute the classes needed by RTI. |
| 169 return typeTestRegistry.computeRtiNeededClasses(); | 163 return typeTestRegistry.computeRtiNeededClasses(); |
| 170 } | 164 } |
| 171 | 165 |
| 172 /// Creates the [Emitter] for this task. | 166 /// Creates the [Emitter] for this task. |
| 173 void createEmitter(Namer namer, ClosedWorld closedWorld) { | 167 void createEmitter(Namer namer, ClosedWorld closedWorld) { |
| 174 measure(() { | 168 measure(() { |
| 175 _emitter = _emitterFactory.createEmitter(this, namer, closedWorld); | 169 _emitter = _emitterFactory.createEmitter(this, namer, closedWorld); |
| 176 metadataCollector = new MetadataCollector(compiler, _emitter); | 170 metadataCollector = new MetadataCollector(compiler, _emitter); |
| 177 typeTestRegistry = new TypeTestRegistry(compiler, closedWorld); | 171 typeTestRegistry = new TypeTestRegistry(compiler, closedWorld); |
| 178 }); | 172 }); |
| 179 } | 173 } |
| 180 | 174 |
| 181 int assembleProgram(Namer namer, ClosedWorld closedWorld) { | 175 int assembleProgram(Namer namer, ClosedWorld closedWorld) { |
| 182 return measure(() { | 176 return measure(() { |
| 183 emitter.invalidateCaches(); | 177 emitter.invalidateCaches(); |
| 184 | 178 |
| 185 Set<ClassElement> rtiNeededClasses = _finalizeRti(); | 179 Set<ClassEntity> rtiNeededClasses = _finalizeRti(); |
| 186 ProgramBuilder programBuilder = new ProgramBuilder( | 180 ProgramBuilder programBuilder = new ProgramBuilder( |
| 187 compiler, namer, this, emitter, closedWorld, rtiNeededClasses); | 181 compiler, namer, this, emitter, closedWorld, rtiNeededClasses); |
| 188 int size = emitter.emitProgram(programBuilder); | 182 int size = emitter.emitProgram(programBuilder); |
| 189 // TODO(floitsch): we shouldn't need the `neededClasses` anymore. | 183 // TODO(floitsch): we shouldn't need the `neededClasses` anymore. |
| 190 neededClasses = programBuilder.collector.neededClasses; | 184 neededClasses = programBuilder.collector.neededClasses; |
| 191 return size; | 185 return size; |
| 192 }); | 186 }); |
| 193 } | 187 } |
| 194 } | 188 } |
| 195 | 189 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 206 CodeEmitterTask task, Namer namer, ClosedWorld closedWorld); | 200 CodeEmitterTask task, Namer namer, ClosedWorld closedWorld); |
| 207 } | 201 } |
| 208 | 202 |
| 209 abstract class Emitter { | 203 abstract class Emitter { |
| 210 /// Uses the [programBuilder] to generate a model of the program, emits | 204 /// Uses the [programBuilder] to generate a model of the program, emits |
| 211 /// the program, and returns the size of the generated output. | 205 /// the program, and returns the size of the generated output. |
| 212 int emitProgram(ProgramBuilder programBuilder); | 206 int emitProgram(ProgramBuilder programBuilder); |
| 213 | 207 |
| 214 /// Returns the JS function that must be invoked to get the value of the | 208 /// Returns the JS function that must be invoked to get the value of the |
| 215 /// lazily initialized static. | 209 /// lazily initialized static. |
| 216 jsAst.Expression isolateLazyInitializerAccess(FieldElement element); | 210 jsAst.Expression isolateLazyInitializerAccess(FieldEntity element); |
| 217 | 211 |
| 218 /// Returns the closure expression of a static function. | 212 /// Returns the closure expression of a static function. |
| 219 jsAst.Expression isolateStaticClosureAccess(FunctionElement element); | 213 jsAst.Expression isolateStaticClosureAccess(FunctionEntity element); |
| 220 | 214 |
| 221 /// Returns the JS code for accessing the embedded [global]. | 215 /// Returns the JS code for accessing the embedded [global]. |
| 222 jsAst.Expression generateEmbeddedGlobalAccess(String global); | 216 jsAst.Expression generateEmbeddedGlobalAccess(String global); |
| 223 | 217 |
| 224 /// Returns the JS function representing the given function. | 218 /// Returns the JS function representing the given function. |
| 225 /// | 219 /// |
| 226 /// The function must be invoked and can not be used as closure. | 220 /// The function must be invoked and can not be used as closure. |
| 227 jsAst.Expression staticFunctionAccess(FunctionElement element); | 221 jsAst.Expression staticFunctionAccess(FunctionEntity element); |
| 228 | 222 |
| 229 jsAst.Expression staticFieldAccess(FieldElement element); | 223 jsAst.Expression staticFieldAccess(FieldEntity element); |
| 230 | 224 |
| 231 /// Returns the JS constructor of the given element. | 225 /// Returns the JS constructor of the given element. |
| 232 /// | 226 /// |
| 233 /// The returned expression must only be used in a JS `new` expression. | 227 /// The returned expression must only be used in a JS `new` expression. |
| 234 jsAst.Expression constructorAccess(ClassElement e); | 228 jsAst.Expression constructorAccess(ClassEntity e); |
| 235 | 229 |
| 236 /// Returns the JS prototype of the given class [e]. | 230 /// Returns the JS prototype of the given class [e]. |
| 237 jsAst.Expression prototypeAccess(ClassElement e, bool hasBeenInstantiated); | 231 jsAst.Expression prototypeAccess(ClassEntity e, bool hasBeenInstantiated); |
| 238 | 232 |
| 239 /// Returns the JS constructor of the given interceptor class [e]. | 233 /// Returns the JS constructor of the given interceptor class [e]. |
| 240 jsAst.Expression interceptorClassAccess(ClassElement e); | 234 jsAst.Expression interceptorClassAccess(ClassEntity e); |
| 241 | 235 |
| 242 /// Returns the JS expression representing the type [e]. | 236 /// Returns the JS expression representing the type [e]. |
| 243 jsAst.Expression typeAccess(Entity e); | 237 jsAst.Expression typeAccess(Entity e); |
| 244 | 238 |
| 245 /// Returns the JS expression representing a function that returns 'null' | 239 /// Returns the JS expression representing a function that returns 'null' |
| 246 jsAst.Expression generateFunctionThatReturnsNull(); | 240 jsAst.Expression generateFunctionThatReturnsNull(); |
| 247 | 241 |
| 248 int compareConstants(ConstantValue a, ConstantValue b); | 242 int compareConstants(ConstantValue a, ConstantValue b); |
| 249 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant); | 243 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant); |
| 250 | 244 |
| 251 /// Returns the JS code for accessing the given [constant]. | 245 /// Returns the JS code for accessing the given [constant]. |
| 252 jsAst.Expression constantReference(ConstantValue constant); | 246 jsAst.Expression constantReference(ConstantValue constant); |
| 253 | 247 |
| 254 /// Returns the JS template for the given [builtin]. | 248 /// Returns the JS template for the given [builtin]. |
| 255 jsAst.Template templateForBuiltin(JsBuiltin builtin); | 249 jsAst.Template templateForBuiltin(JsBuiltin builtin); |
| 256 | 250 |
| 257 void invalidateCaches(); | 251 void invalidateCaches(); |
| 258 } | 252 } |
| OLD | NEW |