| 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<ConstantValue>> outputConstantLists = | 26 final Map<OutputUnit, List<ConstantValue>> outputConstantLists = |
| 27 new Map<OutputUnit, List<ConstantValue>>(); | 27 new Map<OutputUnit, List<ConstantValue>>(); |
| 28 final Map<OutputUnit, List<Element>> outputStaticLists = |
| 29 new Map<OutputUnit, List<Element>>(); |
| 30 final Map<OutputUnit, Set<LibraryElement>> outputLibraryLists = |
| 31 new Map<OutputUnit, Set<LibraryElement>>(); |
| 32 |
| 33 /// True, if the output contains a constant list. |
| 34 /// |
| 35 /// This flag is updated in [computeNeededConstants]. |
| 36 bool outputContainsConstantList = false; |
| 37 |
| 28 final List<ClassElement> nativeClasses = <ClassElement>[]; | 38 final List<ClassElement> nativeClasses = <ClassElement>[]; |
| 29 | 39 |
| 30 /// Records if a type variable is read dynamically for type tests. | 40 /// Records if a type variable is read dynamically for type tests. |
| 31 final Set<TypeVariableElement> readTypeVariables = | 41 final Set<TypeVariableElement> readTypeVariables = |
| 32 new Set<TypeVariableElement>(); | 42 new Set<TypeVariableElement>(); |
| 33 | 43 |
| 34 List<TypedefElement> typedefsNeededForReflection; | 44 List<TypedefElement> typedefsNeededForReflection; |
| 35 | 45 |
| 36 JavaScriptBackend get backend => compiler.backend; | 46 JavaScriptBackend get backend => compiler.backend; |
| 37 | 47 |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 } | 166 } |
| 157 } | 167 } |
| 158 typedefsNeededForReflection.forEach(backend.retainMetadataOf); | 168 typedefsNeededForReflection.forEach(backend.retainMetadataOf); |
| 159 } | 169 } |
| 160 | 170 |
| 161 JavaScriptConstantCompiler handler = backend.constants; | 171 JavaScriptConstantCompiler handler = backend.constants; |
| 162 List<ConstantValue> constants = handler.getConstantsForEmission( | 172 List<ConstantValue> constants = handler.getConstantsForEmission( |
| 163 compiler.hasIncrementalSupport ? null : emitter.compareConstants); | 173 compiler.hasIncrementalSupport ? null : emitter.compareConstants); |
| 164 for (ConstantValue constant in constants) { | 174 for (ConstantValue constant in constants) { |
| 165 if (emitter.isConstantInlinedOrAlreadyEmitted(constant)) continue; | 175 if (emitter.isConstantInlinedOrAlreadyEmitted(constant)) continue; |
| 176 |
| 177 if (constant.isList) outputContainsConstantList = true; |
| 178 |
| 166 OutputUnit constantUnit = | 179 OutputUnit constantUnit = |
| 167 compiler.deferredLoadTask.outputUnitForConstant(constant); | 180 compiler.deferredLoadTask.outputUnitForConstant(constant); |
| 168 if (constantUnit == null) { | 181 if (constantUnit == null) { |
| 169 // The back-end introduces some constants, like "InterceptorConstant" or | 182 // The back-end introduces some constants, like "InterceptorConstant" or |
| 170 // some list constants. They are emitted in the main output-unit. | 183 // some list constants. They are emitted in the main output-unit. |
| 171 // TODO(sigurdm): We should track those constants. | 184 // TODO(sigurdm): We should track those constants. |
| 172 constantUnit = compiler.deferredLoadTask.mainOutputUnit; | 185 constantUnit = compiler.deferredLoadTask.mainOutputUnit; |
| 173 } | 186 } |
| 174 outputConstantLists.putIfAbsent( | 187 outputConstantLists.putIfAbsent( |
| 175 constantUnit, () => new List<ConstantValue>()).add(constant); | 188 constantUnit, () => new List<ConstantValue>()).add(constant); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 } | 292 } |
| 280 } else { | 293 } else { |
| 281 outputClassLists.putIfAbsent( | 294 outputClassLists.putIfAbsent( |
| 282 compiler.deferredLoadTask.outputUnitForElement(element), | 295 compiler.deferredLoadTask.outputUnitForElement(element), |
| 283 () => new List<ClassElement>()) | 296 () => new List<ClassElement>()) |
| 284 .add(element); | 297 .add(element); |
| 285 } | 298 } |
| 286 } | 299 } |
| 287 } | 300 } |
| 288 | 301 |
| 302 void computeNeededStatics() { |
| 303 bool isStaticFunction(Element element) => |
| 304 !element.isInstanceMember && !element.isField; |
| 305 |
| 306 Iterable<Element> elements = |
| 307 backend.generatedCode.keys.where(isStaticFunction); |
| 308 |
| 309 for (Element element in Elements.sortedByPosition(elements)) { |
| 310 outputStaticLists.putIfAbsent( |
| 311 compiler.deferredLoadTask.outputUnitForElement(element), |
| 312 () => new List<Element>()) |
| 313 .add(element); |
| 314 } |
| 315 } |
| 316 |
| 317 void computeNeededLibraries() { |
| 318 void addSurroundingLibraryToSet(Element element) { |
| 319 OutputUnit unit = compiler.deferredLoadTask.outputUnitForElement(element); |
| 320 LibraryElement library = element.library; |
| 321 outputLibraryLists.putIfAbsent(unit, () => new Set<LibraryElement>()) |
| 322 .add(library); |
| 323 } |
| 324 |
| 325 backend.generatedCode.keys.forEach(addSurroundingLibraryToSet); |
| 326 neededClasses.forEach(addSurroundingLibraryToSet); |
| 327 } |
| 328 |
| 289 void assembleProgram() { | 329 void assembleProgram() { |
| 290 measure(() { | 330 measure(() { |
| 291 emitter.invalidateCaches(); | 331 emitter.invalidateCaches(); |
| 292 | 332 |
| 293 // Compute the required type checks to know which classes need a | 333 // Compute the required type checks to know which classes need a |
| 294 // 'is$' method. | 334 // 'is$' method. |
| 295 typeTestEmitter.computeRequiredTypeChecks(); | 335 typeTestEmitter.computeRequiredTypeChecks(); |
| 296 | 336 |
| 297 computeNeededDeclarations(); | 337 computeNeededDeclarations(); |
| 298 computeNeededConstants(); | 338 computeNeededConstants(); |
| 339 computeNeededStatics(); |
| 340 computeNeededLibraries(); |
| 341 |
| 299 | 342 |
| 300 Program program; | 343 Program program; |
| 301 if (USE_NEW_EMITTER) { | 344 if (USE_NEW_EMITTER) { |
| 302 program = new ProgramBuilder(compiler, namer, this).buildProgram(); | 345 program = new ProgramBuilder(compiler, namer, this).buildProgram(); |
| 303 } | 346 } |
| 304 emitter.emitProgram(program); | 347 emitter.emitProgram(program); |
| 305 }); | 348 }); |
| 306 } | 349 } |
| 307 } | 350 } |
| 308 | 351 |
| 309 abstract class Emitter { | 352 abstract class Emitter { |
| 310 void emitProgram(Program program); | 353 void emitProgram(Program program); |
| 311 | 354 |
| 312 jsAst.Expression generateEmbeddedGlobalAccess(String global); | 355 jsAst.Expression generateEmbeddedGlobalAccess(String global); |
| 313 jsAst.Expression constantReference(ConstantValue value); | 356 jsAst.Expression constantReference(ConstantValue value); |
| 314 | 357 |
| 315 int compareConstants(ConstantValue a, ConstantValue b); | 358 int compareConstants(ConstantValue a, ConstantValue b); |
| 316 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant); | 359 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant); |
| 317 | 360 |
| 318 void invalidateCaches(); | 361 void invalidateCaches(); |
| 319 } | 362 } |
| OLD | NEW |