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