| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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.program_builder; | 5 library dart2js.js_emitter.program_builder; |
| 6 | 6 |
| 7 import 'js_emitter.dart' show computeMixinClass; | 7 import 'js_emitter.dart' show computeMixinClass; |
| 8 import 'model.dart'; | 8 import 'model.dart'; |
| 9 | 9 |
| 10 import '../common.dart'; | 10 import '../common.dart'; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 final Map<ClassElement, Class> _classes = <ClassElement, Class>{}; | 51 final Map<ClassElement, Class> _classes = <ClassElement, Class>{}; |
| 52 | 52 |
| 53 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to | 53 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to |
| 54 /// generate the deferredLoadingMap (to know which hunks to load). | 54 /// generate the deferredLoadingMap (to know which hunks to load). |
| 55 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{}; | 55 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{}; |
| 56 | 56 |
| 57 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to | 57 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to |
| 58 /// update field-initializers to point to the ConstantModel. | 58 /// update field-initializers to point to the ConstantModel. |
| 59 final Map<ConstantValue, Constant> _constants = <ConstantValue, Constant>{}; | 59 final Map<ConstantValue, Constant> _constants = <ConstantValue, Constant>{}; |
| 60 | 60 |
| 61 Set<Class> _unneededNativeClasses; |
| 62 |
| 61 Program buildProgram({bool storeFunctionTypesInMetadata: false}) { | 63 Program buildProgram({bool storeFunctionTypesInMetadata: false}) { |
| 62 this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata; | 64 this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata; |
| 63 // Note: In rare cases (mostly tests) output units can be empty. This | 65 // Note: In rare cases (mostly tests) output units can be empty. This |
| 64 // happens when the deferred code is dead-code eliminated but we still need | 66 // happens when the deferred code is dead-code eliminated but we still need |
| 65 // to check that the library has been loaded. | 67 // to check that the library has been loaded. |
| 66 _compiler.deferredLoadTask.allOutputUnits.forEach( | 68 _compiler.deferredLoadTask.allOutputUnits.forEach( |
| 67 _registry.registerOutputUnit); | 69 _registry.registerOutputUnit); |
| 68 _task.outputClassLists.forEach(_registry.registerElements); | 70 _task.outputClassLists.forEach(_registry.registerElements); |
| 69 _task.outputStaticLists.forEach(_registry.registerElements); | 71 _task.outputStaticLists.forEach(_registry.registerElements); |
| 70 _task.outputConstantLists.forEach(_registerConstants); | 72 _task.outputConstantLists.forEach(_registerConstants); |
| 71 _task.outputStaticNonFinalFieldLists.forEach(_registry.registerElements); | 73 _task.outputStaticNonFinalFieldLists.forEach(_registry.registerElements); |
| 72 | 74 |
| 73 // TODO(kasperl): There's code that implicitly needs access to the special | 75 // TODO(kasperl): There's code that implicitly needs access to the special |
| 74 // $ holder so we have to register that. Can we track if we have to? | 76 // $ holder so we have to register that. Can we track if we have to? |
| 75 _registry.registerHolder(r'$'); | 77 _registry.registerHolder(r'$'); |
| 76 | 78 |
| 77 MainFragment mainOutput = _buildMainOutput(_registry.mainLibrariesMap); | 79 // We need to run the native-preparation before we build the output. The |
| 78 Iterable<Fragment> deferredOutputs = _registry.deferredLibrariesMap | 80 // preparation code, in turn needs the classes to be set up. |
| 79 .map((librariesMap) => _buildDeferredOutput(mainOutput, librariesMap)); | 81 // We thus build the classes before building their containers. |
| 80 | 82 _task.outputClassLists.forEach((OutputUnit _, List<ClassElement> classes) { |
| 81 List<Fragment> outputs = new List<Fragment>(_registry.librariesMapCount); | 83 classes.forEach(_buildClass); |
| 82 outputs[0] = mainOutput; | 84 }); |
| 83 outputs.setAll(1, deferredOutputs); | |
| 84 | |
| 85 List<Class> nativeClasses = _task.nativeClasses | |
| 86 .map((ClassElement classElement) { | |
| 87 Class result = _classes[classElement]; | |
| 88 return (result == null) ? _buildClass(classElement) : result; | |
| 89 }) | |
| 90 .toList(); | |
| 91 | 85 |
| 92 // Resolve the superclass references after we've processed all the classes. | 86 // Resolve the superclass references after we've processed all the classes. |
| 93 _classes.forEach((ClassElement element, Class c) { | 87 _classes.forEach((ClassElement element, Class c) { |
| 94 if (element.superclass != null) { | 88 if (element.superclass != null) { |
| 95 c.setSuperclass(_classes[element.superclass]); | 89 c.setSuperclass(_classes[element.superclass]); |
| 96 assert(c.superclass != null); | 90 assert(c.superclass != null); |
| 97 } | 91 } |
| 98 if (c is MixinApplication) { | 92 if (c is MixinApplication) { |
| 99 c.setMixinClass(_classes[computeMixinClass(element)]); | 93 c.setMixinClass(_classes[computeMixinClass(element)]); |
| 100 assert(c.mixinClass != null); | 94 assert(c.mixinClass != null); |
| 101 } | 95 } |
| 102 }); | 96 }); |
| 103 | 97 |
| 98 List<Class> nativeClasses = _task.nativeClassesAndSubclasses |
| 99 .map((ClassElement classElement) => _classes[classElement]) |
| 100 .toList(); |
| 101 |
| 104 Map<Class, Map<String, js.Expression>> additionalProperties = | 102 Map<Class, Map<String, js.Expression>> additionalProperties = |
| 105 new Map<Class, Map<String, js.Expression>>(); | 103 new Map<Class, Map<String, js.Expression>>(); |
| 106 | 104 |
| 107 List<Class> neededNativeClasses = | 105 _unneededNativeClasses = |
| 108 _task.nativeEmitter.prepareNativeClasses( | 106 _task.nativeEmitter.prepareNativeClasses( |
| 109 nativeClasses, | 107 nativeClasses, |
| 110 additionalProperties); | 108 additionalProperties); |
| 111 | 109 |
| 110 MainFragment mainOutput = _buildMainOutput(_registry.mainLibrariesMap); |
| 111 Iterable<Fragment> deferredOutputs = _registry.deferredLibrariesMap |
| 112 .map((librariesMap) => _buildDeferredOutput(mainOutput, librariesMap)); |
| 113 |
| 114 List<Fragment> outputs = new List<Fragment>(_registry.librariesMapCount); |
| 115 outputs[0] = mainOutput; |
| 116 outputs.setAll(1, deferredOutputs); |
| 117 |
| 112 _markEagerClasses(); | 118 _markEagerClasses(); |
| 113 | 119 |
| 120 bool containsNativeClasses = |
| 121 nativeClasses.length != _unneededNativeClasses.length; |
| 122 |
| 114 return new Program( | 123 return new Program( |
| 115 outputs, | 124 outputs, |
| 116 neededNativeClasses, | |
| 117 additionalProperties, | 125 additionalProperties, |
| 118 _buildLoadMap(), | 126 _buildLoadMap(), |
| 119 outputContainsNativeClasses: neededNativeClasses.isNotEmpty, | 127 outputContainsNativeClasses: containsNativeClasses, |
| 120 outputContainsConstantList: _task.outputContainsConstantList); | 128 outputContainsConstantList: _task.outputContainsConstantList); |
| 121 } | 129 } |
| 122 | 130 |
| 123 void _markEagerClasses() { | 131 void _markEagerClasses() { |
| 124 _markEagerInterceptorClasses(); | 132 _markEagerInterceptorClasses(); |
| 125 } | 133 } |
| 126 | 134 |
| 127 /// Builds a map from loadId to outputs-to-load. | 135 /// Builds a map from loadId to outputs-to-load. |
| 128 Map<String, List<Fragment>> _buildLoadMap() { | 136 Map<String, List<Fragment>> _buildLoadMap() { |
| 129 List<OutputUnit> convertHunks(List<OutputUnit> hunks) { | |
| 130 return hunks.map((OutputUnit unit) => _outputs[unit]) | |
| 131 .toList(growable: false); | |
| 132 } | |
| 133 | |
| 134 Map<String, List<Fragment>> loadMap = <String, List<Fragment>>{}; | 137 Map<String, List<Fragment>> loadMap = <String, List<Fragment>>{}; |
| 135 _compiler.deferredLoadTask.hunksToLoad | 138 _compiler.deferredLoadTask.hunksToLoad |
| 136 .forEach((String loadId, List<OutputUnit> outputUnits) { | 139 .forEach((String loadId, List<OutputUnit> outputUnits) { |
| 137 loadMap[loadId] = outputUnits | 140 loadMap[loadId] = outputUnits |
| 138 .map((OutputUnit unit) => _outputs[unit]) | 141 .map((OutputUnit unit) => _outputs[unit]) |
| 139 .toList(growable: false); | 142 .toList(growable: false); |
| 140 }); | 143 }); |
| 141 return loadMap; | 144 return loadMap; |
| 142 } | 145 } |
| 143 | 146 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 JavaScriptConstantCompiler handler = backend.constants; | 218 JavaScriptConstantCompiler handler = backend.constants; |
| 216 List<VariableElement> lazyFields = | 219 List<VariableElement> lazyFields = |
| 217 handler.getLazilyInitializedFieldsForEmission(); | 220 handler.getLazilyInitializedFieldsForEmission(); |
| 218 return Elements.sortedByPosition(lazyFields) | 221 return Elements.sortedByPosition(lazyFields) |
| 219 .map(_buildLazyField) | 222 .map(_buildLazyField) |
| 220 .where((field) => field != null) // Happens when the field was unused. | 223 .where((field) => field != null) // Happens when the field was unused. |
| 221 .toList(growable: false); | 224 .toList(growable: false); |
| 222 } | 225 } |
| 223 | 226 |
| 224 StaticField _buildLazyField(Element element) { | 227 StaticField _buildLazyField(Element element) { |
| 225 JavaScriptConstantCompiler handler = backend.constants; | |
| 226 js.Expression code = backend.generatedCode[element]; | 228 js.Expression code = backend.generatedCode[element]; |
| 227 // The code is null if we ended up not needing the lazily | 229 // The code is null if we ended up not needing the lazily |
| 228 // initialized field after all because of constant folding | 230 // initialized field after all because of constant folding |
| 229 // before code generation. | 231 // before code generation. |
| 230 if (code == null) return null; | 232 if (code == null) return null; |
| 231 | 233 |
| 232 String name = namer.getNameOfGlobalField(element); | 234 String name = namer.getNameOfGlobalField(element); |
| 233 bool isFinal = element.isFinal; | 235 bool isFinal = element.isFinal; |
| 234 bool isLazy = true; | 236 bool isLazy = true; |
| 235 return new StaticField(element, | 237 return new StaticField(element, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 256 .map(_buildStaticMethod) | 258 .map(_buildStaticMethod) |
| 257 .toList(); | 259 .toList(); |
| 258 | 260 |
| 259 if (library == backend.interceptorsLibrary) { | 261 if (library == backend.interceptorsLibrary) { |
| 260 statics.addAll(_generateGetInterceptorMethods()); | 262 statics.addAll(_generateGetInterceptorMethods()); |
| 261 statics.addAll(_generateOneShotInterceptors()); | 263 statics.addAll(_generateOneShotInterceptors()); |
| 262 } | 264 } |
| 263 | 265 |
| 264 List<Class> classes = elements | 266 List<Class> classes = elements |
| 265 .where((e) => e is ClassElement) | 267 .where((e) => e is ClassElement) |
| 266 .map(_buildClass) | 268 .map((ClassElement classElement) => _classes[classElement]) |
| 269 .where((Class cls) => |
| 270 !cls.isNative || !_unneededNativeClasses.contains(cls)) |
| 267 .toList(growable: false); | 271 .toList(growable: false); |
| 268 | 272 |
| 269 bool visitStatics = true; | 273 bool visitStatics = true; |
| 270 List<Field> staticFieldsForReflection = _buildFields(library, visitStatics); | 274 List<Field> staticFieldsForReflection = _buildFields(library, visitStatics); |
| 271 | 275 |
| 272 return new Library(library, uri, statics, classes, | 276 return new Library(library, uri, statics, classes, |
| 273 staticFieldsForReflection); | 277 staticFieldsForReflection); |
| 274 } | 278 } |
| 275 | 279 |
| 276 /// HACK for Try. | 280 /// HACK for Try. |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 513 _registry.registerConstant(outputUnit, constantValue); | 517 _registry.registerConstant(outputUnit, constantValue); |
| 514 assert(!_constants.containsKey(constantValue)); | 518 assert(!_constants.containsKey(constantValue)); |
| 515 String name = namer.constantName(constantValue); | 519 String name = namer.constantName(constantValue); |
| 516 String constantObject = namer.globalObjectForConstant(constantValue); | 520 String constantObject = namer.globalObjectForConstant(constantValue); |
| 517 Holder holder = _registry.registerHolder(constantObject); | 521 Holder holder = _registry.registerHolder(constantObject); |
| 518 Constant constant = new Constant(name, holder, constantValue); | 522 Constant constant = new Constant(name, holder, constantValue); |
| 519 _constants[constantValue] = constant; | 523 _constants[constantValue] = constant; |
| 520 } | 524 } |
| 521 } | 525 } |
| 522 } | 526 } |
| OLD | NEW |