| 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 'model.dart'; | 7 import 'model.dart'; |
| 8 import '../common.dart'; | 8 import '../common.dart'; |
| 9 import '../js/js.dart' as js; | 9 import '../js/js.dart' as js; |
| 10 | 10 |
| 11 import '../js_backend/js_backend.dart' show Namer, JavaScriptBackend; | 11 import '../js_backend/js_backend.dart' show |
| 12 Namer, |
| 13 JavaScriptBackend, |
| 14 JavaScriptConstantCompiler; |
| 15 |
| 12 import '../js_emitter/js_emitter.dart' as emitterTask show | 16 import '../js_emitter/js_emitter.dart' as emitterTask show |
| 13 CodeEmitterTask, | 17 CodeEmitterTask, |
| 14 Emitter; | 18 Emitter; |
| 15 | 19 |
| 16 import '../universe/universe.dart' show Universe; | 20 import '../universe/universe.dart' show Universe; |
| 17 import '../deferred_load.dart' show DeferredLoadTask, OutputUnit; | 21 import '../deferred_load.dart' show DeferredLoadTask, OutputUnit; |
| 18 | 22 |
| 19 part 'registry.dart'; | 23 part 'registry.dart'; |
| 20 | 24 |
| 21 class ProgramBuilder { | 25 class ProgramBuilder { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 42 /// generate the deferredLoadingMap (to know which hunks to load). | 46 /// generate the deferredLoadingMap (to know which hunks to load). |
| 43 final Map<OutputUnit, Output> _outputs = <OutputUnit, Output>{}; | 47 final Map<OutputUnit, Output> _outputs = <OutputUnit, Output>{}; |
| 44 | 48 |
| 45 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to | 49 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to |
| 46 /// update field-initializers to point to the ConstantModel. | 50 /// update field-initializers to point to the ConstantModel. |
| 47 final Map<ConstantValue, Constant> _constants = <ConstantValue, Constant>{}; | 51 final Map<ConstantValue, Constant> _constants = <ConstantValue, Constant>{}; |
| 48 | 52 |
| 49 Program buildProgram() { | 53 Program buildProgram() { |
| 50 _task.outputClassLists.forEach(_registry.registerElements); | 54 _task.outputClassLists.forEach(_registry.registerElements); |
| 51 _task.outputStaticLists.forEach(_registry.registerElements); | 55 _task.outputStaticLists.forEach(_registry.registerElements); |
| 56 _task.outputConstantLists.forEach(_registerConstants); |
| 52 | 57 |
| 53 // TODO(kasperl): There's code that implicitly needs access to the special | 58 // TODO(kasperl): There's code that implicitly needs access to the special |
| 54 // $ holder so we have to register that. Can we track if we have to? | 59 // $ holder so we have to register that. Can we track if we have to? |
| 55 _registry.registerHolder(r'$'); | 60 _registry.registerHolder(r'$'); |
| 56 | 61 |
| 57 MainOutput mainOutput = _buildMainOutput(_registry.mainFragment); | 62 MainOutput mainOutput = _buildMainOutput(_registry.mainFragment); |
| 58 Iterable<Output> deferredOutputs = _registry.deferredFragments | 63 Iterable<Output> deferredOutputs = _registry.deferredFragments |
| 59 .map((fragment) => _buildDeferredOutput(mainOutput, fragment)); | 64 .map((fragment) => _buildDeferredOutput(mainOutput, fragment)); |
| 60 | 65 |
| 61 List<Output> outputs = new List<Output>(_registry.fragmentCount); | 66 List<Output> outputs = new List<Output>(_registry.fragmentCount); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 89 }); | 94 }); |
| 90 return loadMap; | 95 return loadMap; |
| 91 } | 96 } |
| 92 | 97 |
| 93 MainOutput _buildMainOutput(Fragment fragment) { | 98 MainOutput _buildMainOutput(Fragment fragment) { |
| 94 // Construct the main output from the libraries and the registered holders. | 99 // Construct the main output from the libraries and the registered holders. |
| 95 MainOutput result = new MainOutput( | 100 MainOutput result = new MainOutput( |
| 96 "", // The empty string is the name for the main output file. | 101 "", // The empty string is the name for the main output file. |
| 97 namer.elementAccess(_compiler.mainFunction), | 102 namer.elementAccess(_compiler.mainFunction), |
| 98 _buildLibraries(fragment), | 103 _buildLibraries(fragment), |
| 104 _buildStaticNonFinalFields(fragment), |
| 99 _buildConstants(fragment), | 105 _buildConstants(fragment), |
| 100 _registry.holders.toList(growable: false)); | 106 _registry.holders.toList(growable: false)); |
| 101 _outputs[fragment.outputUnit] = result; | 107 _outputs[fragment.outputUnit] = result; |
| 102 return result; | 108 return result; |
| 103 } | 109 } |
| 104 | 110 |
| 105 /// Returns a name composed of the main output file name and [name]. | 111 /// Returns a name composed of the main output file name and [name]. |
| 106 String _outputFileName(String name) { | 112 String _outputFileName(String name) { |
| 107 assert(name != ""); | 113 assert(name != ""); |
| 108 String outPath = _compiler.outputUri != null | 114 String outPath = _compiler.outputUri != null |
| 109 ? _compiler.outputUri.path | 115 ? _compiler.outputUri.path |
| 110 : "out"; | 116 : "out"; |
| 111 String outName = outPath.substring(outPath.lastIndexOf('/') + 1); | 117 String outName = outPath.substring(outPath.lastIndexOf('/') + 1); |
| 112 return "${outName}_$name"; | 118 return "${outName}_$name"; |
| 113 } | 119 } |
| 114 | 120 |
| 115 DeferredOutput _buildDeferredOutput(MainOutput mainOutput, | 121 DeferredOutput _buildDeferredOutput(MainOutput mainOutput, |
| 116 Fragment fragment) { | 122 Fragment fragment) { |
| 117 DeferredOutput result = new DeferredOutput( | 123 DeferredOutput result = new DeferredOutput( |
| 118 _outputFileName(fragment.name), fragment.name, | 124 _outputFileName(fragment.name), fragment.name, |
| 119 mainOutput, | 125 mainOutput, |
| 120 _buildLibraries(fragment), | 126 _buildLibraries(fragment), |
| 127 _buildStaticNonFinalFields(fragment), |
| 121 _buildConstants(fragment)); | 128 _buildConstants(fragment)); |
| 122 _outputs[fragment.outputUnit] = result; | 129 _outputs[fragment.outputUnit] = result; |
| 123 return result; | 130 return result; |
| 124 } | 131 } |
| 125 | 132 |
| 126 List<Constant> _buildConstants(Fragment fragment) { | 133 List<Constant> _buildConstants(Fragment fragment) { |
| 127 List<ConstantValue> constantValues = | 134 List<ConstantValue> constantValues = |
| 128 _task.outputConstantLists[fragment.outputUnit]; | 135 _task.outputConstantLists[fragment.outputUnit]; |
| 129 if (constantValues == null) return const <Constant>[]; | 136 if (constantValues == null) return const <Constant>[]; |
| 130 return constantValues.map((ConstantValue constantValue) { | 137 return constantValues.map((ConstantValue value) => _constants[value]) |
| 131 assert(!_constants.containsKey(constantValue)); | 138 .toList(growable: false); |
| 132 String name = namer.constantName(constantValue); | 139 } |
| 133 String constantObject = namer.globalObjectForConstant(constantValue); | 140 |
| 134 Holder holder = _registry.registerHolder(constantObject); | 141 List<StaticField> _buildStaticNonFinalFields(Fragment fragment) { |
| 135 Constant constant = new Constant(name, holder, constantValue); | 142 // TODO(floitsch): handle static non-final fields correctly with deferred |
| 136 _constants[constantValue] = constant; | 143 // libraries. |
| 137 return constant; | 144 if (fragment != _registry.mainFragment) return const <StaticField>[]; |
| 138 }).toList(); | 145 Iterable<VariableElement> staticNonFinalFields = |
| 146 backend.constants.getStaticNonFinalFieldsForEmission(); |
| 147 return Elements.sortedByPosition(staticNonFinalFields) |
| 148 .map(_buildStaticField) |
| 149 .toList(growable: false); |
| 150 } |
| 151 |
| 152 StaticField _buildStaticField(Element element) { |
| 153 JavaScriptConstantCompiler handler = backend.constants; |
| 154 ConstantValue initialValue = handler.getInitialValueFor(element).value; |
| 155 js.Expression code = _task.emitter.constantReference(initialValue); |
| 156 String name = namer.getNameOfGlobalField(element); |
| 157 bool isFinal = false; |
| 158 bool isLazy = false; |
| 159 return new StaticField(name, _registry.registerHolder(r'$'), code, |
| 160 isFinal, isLazy); |
| 161 } |
| 162 |
| 163 List<StaticField> _buildStaticLazilyInitializedFields(Fragment fragment) { |
| 164 JavaScriptConstantCompiler handler = backend.constants; |
| 165 List<VariableElement> lazyFields = |
| 166 handler.getLazilyInitializedFieldsForEmission(); |
| 167 // TODO(floitsch): handle static lazy finals correctly with deferred |
| 168 // libraries. |
| 169 if (fragment != _registry.mainFragment) return const <StaticField>[]; |
| 170 throw new UnimplementedError("lazy statics"); |
| 139 } | 171 } |
| 140 | 172 |
| 141 List<Library> _buildLibraries(Fragment fragment) { | 173 List<Library> _buildLibraries(Fragment fragment) { |
| 142 List<Library> libraries = new List<Library>(fragment.length); | 174 List<Library> libraries = new List<Library>(fragment.length); |
| 143 int count = 0; | 175 int count = 0; |
| 144 fragment.forEach((LibraryElement library, List<Element> elements) { | 176 fragment.forEach((LibraryElement library, List<Element> elements) { |
| 145 libraries[count++] = _buildLibrary(library, elements); | 177 libraries[count++] = _buildLibrary(library, elements); |
| 146 }); | 178 }); |
| 147 return libraries; | 179 return libraries; |
| 148 } | 180 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 return new StaticMethod(name, _registry.registerHolder(holder), code); | 231 return new StaticMethod(name, _registry.registerHolder(holder), code); |
| 200 } | 232 } |
| 201 | 233 |
| 202 StaticMethod _buildStaticMethodTearOff(FunctionElement element) { | 234 StaticMethod _buildStaticMethodTearOff(FunctionElement element) { |
| 203 String name = namer.getStaticClosureName(element); | 235 String name = namer.getStaticClosureName(element); |
| 204 String holder = namer.globalObjectFor(element); | 236 String holder = namer.globalObjectFor(element); |
| 205 // TODO(kasperl): This clearly doesn't work yet. | 237 // TODO(kasperl): This clearly doesn't work yet. |
| 206 js.Expression code = js.string("<<unimplemented>>"); | 238 js.Expression code = js.string("<<unimplemented>>"); |
| 207 return new StaticMethod(name, _registry.registerHolder(holder), code); | 239 return new StaticMethod(name, _registry.registerHolder(holder), code); |
| 208 } | 240 } |
| 241 |
| 242 void _registerConstants(OutputUnit outputUnit, |
| 243 List<ConstantValue> constantValues) { |
| 244 if (constantValues == null) return; |
| 245 for (ConstantValue constantValue in constantValues) { |
| 246 assert(!_constants.containsKey(constantValue)); |
| 247 String name = namer.constantName(constantValue); |
| 248 String constantObject = namer.globalObjectForConstant(constantValue); |
| 249 Holder holder = _registry.registerHolder(constantObject); |
| 250 Constant constant = new Constant(name, holder, constantValue); |
| 251 _constants[constantValue] = constant; |
| 252 }; |
| 253 } |
| 209 } | 254 } |
| OLD | NEW |