| 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 : this._compiler = compiler, | 42 : this._compiler = compiler, |
| 43 this._registry = new Registry(compiler); | 43 this._registry = new Registry(compiler); |
| 44 | 44 |
| 45 JavaScriptBackend get backend => _compiler.backend; | 45 JavaScriptBackend get backend => _compiler.backend; |
| 46 Universe get universe => _compiler.codegenWorld; | 46 Universe get universe => _compiler.codegenWorld; |
| 47 | 47 |
| 48 /// Mapping from [ClassElement] to constructed [Class]. We need this to | 48 /// Mapping from [ClassElement] to constructed [Class]. We need this to |
| 49 /// update the superclass in the [Class]. | 49 /// update the superclass in the [Class]. |
| 50 final Map<ClassElement, Class> _classes = <ClassElement, Class>{}; | 50 final Map<ClassElement, Class> _classes = <ClassElement, Class>{}; |
| 51 | 51 |
| 52 /// Mapping from [OutputUnit] to constructed [Output]. We need this to | 52 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to |
| 53 /// generate the deferredLoadingMap (to know which hunks to load). | 53 /// generate the deferredLoadingMap (to know which hunks to load). |
| 54 final Map<OutputUnit, Output> _outputs = <OutputUnit, Output>{}; | 54 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{}; |
| 55 | 55 |
| 56 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to | 56 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to |
| 57 /// update field-initializers to point to the ConstantModel. | 57 /// update field-initializers to point to the ConstantModel. |
| 58 final Map<ConstantValue, Constant> _constants = <ConstantValue, Constant>{}; | 58 final Map<ConstantValue, Constant> _constants = <ConstantValue, Constant>{}; |
| 59 | 59 |
| 60 Program buildProgram() { | 60 Program buildProgram() { |
| 61 _task.outputClassLists.forEach(_registry.registerElements); | 61 _task.outputClassLists.forEach(_registry.registerElements); |
| 62 _task.outputStaticLists.forEach(_registry.registerElements); | 62 _task.outputStaticLists.forEach(_registry.registerElements); |
| 63 _task.outputConstantLists.forEach(_registerConstants); | 63 _task.outputConstantLists.forEach(_registerConstants); |
| 64 | 64 |
| 65 // TODO(kasperl): There's code that implicitly needs access to the special | 65 // TODO(kasperl): There's code that implicitly needs access to the special |
| 66 // $ holder so we have to register that. Can we track if we have to? | 66 // $ holder so we have to register that. Can we track if we have to? |
| 67 _registry.registerHolder(r'$'); | 67 _registry.registerHolder(r'$'); |
| 68 | 68 |
| 69 MainOutput mainOutput = _buildMainOutput(_registry.mainFragment); | 69 MainFragment mainOutput = _buildMainOutput(_registry.mainLibrariesMap); |
| 70 Iterable<Output> deferredOutputs = _registry.deferredFragments | 70 Iterable<Fragment> deferredOutputs = _registry.deferredLibrariesMap |
| 71 .map((fragment) => _buildDeferredOutput(mainOutput, fragment)); | 71 .map((librariesMap) => _buildDeferredOutput(mainOutput, librariesMap)); |
| 72 | 72 |
| 73 List<Output> outputs = new List<Output>(_registry.fragmentCount); | 73 List<Fragment> outputs = new List<Fragment>(_registry.librariesMapCount); |
| 74 outputs[0] = mainOutput; | 74 outputs[0] = mainOutput; |
| 75 outputs.setAll(1, deferredOutputs); | 75 outputs.setAll(1, deferredOutputs); |
| 76 | 76 |
| 77 Program result = | 77 Program result = |
| 78 new Program(outputs, _task.outputContainsConstantList, _buildLoadMap()); | 78 new Program(outputs, _task.outputContainsConstantList, _buildLoadMap()); |
| 79 | 79 |
| 80 // Resolve the superclass references after we've processed all the classes. | 80 // Resolve the superclass references after we've processed all the classes. |
| 81 _classes.forEach((ClassElement element, Class c) { | 81 _classes.forEach((ClassElement element, Class c) { |
| 82 if (element.superclass != null) { | 82 if (element.superclass != null) { |
| 83 c.setSuperclass(_classes[element.superclass]); | 83 c.setSuperclass(_classes[element.superclass]); |
| 84 } | 84 } |
| 85 if (element.isMixinApplication) { | 85 if (element.isMixinApplication) { |
| 86 MixinApplication mixinApplication = c; | 86 MixinApplication mixinApplication = c; |
| 87 mixinApplication.setMixinClass(_classes[computeMixinClass(element)]); | 87 mixinApplication.setMixinClass(_classes[computeMixinClass(element)]); |
| 88 } | 88 } |
| 89 }); | 89 }); |
| 90 | 90 |
| 91 _markEagerClasses(); | 91 _markEagerClasses(); |
| 92 | 92 |
| 93 return result; | 93 return result; |
| 94 } | 94 } |
| 95 | 95 |
| 96 void _markEagerClasses() { | 96 void _markEagerClasses() { |
| 97 _markEagerInterceptorClasses(); | 97 _markEagerInterceptorClasses(); |
| 98 } | 98 } |
| 99 | 99 |
| 100 /// Builds a map from loadId to outputs-to-load. | 100 /// Builds a map from loadId to outputs-to-load. |
| 101 Map<String, List<Output>> _buildLoadMap() { | 101 Map<String, List<Fragment>> _buildLoadMap() { |
| 102 List<OutputUnit> convertHunks(List<OutputUnit> hunks) { | 102 List<OutputUnit> convertHunks(List<OutputUnit> hunks) { |
| 103 return hunks.map((OutputUnit unit) => _outputs[unit]) | 103 return hunks.map((OutputUnit unit) => _outputs[unit]) |
| 104 .toList(growable: false); | 104 .toList(growable: false); |
| 105 } | 105 } |
| 106 | 106 |
| 107 Map<String, List<Output>> loadMap = <String, List<Output>>{}; | 107 Map<String, List<Fragment>> loadMap = <String, List<Fragment>>{}; |
| 108 _compiler.deferredLoadTask.hunksToLoad | 108 _compiler.deferredLoadTask.hunksToLoad |
| 109 .forEach((String loadId, List<OutputUnit> outputUnits) { | 109 .forEach((String loadId, List<OutputUnit> outputUnits) { |
| 110 loadMap[loadId] = outputUnits | 110 loadMap[loadId] = outputUnits |
| 111 .map((OutputUnit unit) => _outputs[unit]) | 111 .map((OutputUnit unit) => _outputs[unit]) |
| 112 .toList(growable: false); | 112 .toList(growable: false); |
| 113 }); | 113 }); |
| 114 return loadMap; | 114 return loadMap; |
| 115 } | 115 } |
| 116 | 116 |
| 117 MainOutput _buildMainOutput(Fragment fragment) { | 117 MainFragment _buildMainOutput(LibrariesMap librariesMap) { |
| 118 // Construct the main output from the libraries and the registered holders. | 118 // Construct the main output from the libraries and the registered holders. |
| 119 MainOutput result = new MainOutput( | 119 MainFragment result = new MainFragment( |
| 120 "", // The empty string is the name for the main output file. | 120 "", // The empty string is the name for the main output file. |
| 121 backend.emitter.staticFunctionAccess(_compiler.mainFunction), | 121 backend.emitter.staticFunctionAccess(_compiler.mainFunction), |
| 122 _buildLibraries(fragment), | 122 _buildLibraries(librariesMap), |
| 123 _buildStaticNonFinalFields(fragment), | 123 _buildStaticNonFinalFields(librariesMap), |
| 124 _buildStaticLazilyInitializedFields(fragment), | 124 _buildStaticLazilyInitializedFields(librariesMap), |
| 125 _buildConstants(fragment), | 125 _buildConstants(librariesMap), |
| 126 _registry.holders.toList(growable: false)); | 126 _registry.holders.toList(growable: false)); |
| 127 _outputs[fragment.outputUnit] = result; | 127 _outputs[librariesMap.outputUnit] = result; |
| 128 return result; | 128 return result; |
| 129 } | 129 } |
| 130 | 130 |
| 131 DeferredOutput _buildDeferredOutput(MainOutput mainOutput, | 131 DeferredFragment _buildDeferredOutput(MainFragment mainOutput, |
| 132 Fragment fragment) { | 132 LibrariesMap librariesMap) { |
| 133 DeferredOutput result = new DeferredOutput( | 133 DeferredFragment result = new DeferredFragment( |
| 134 backend.deferredPartFileName(fragment.name, addExtension: false), | 134 backend.deferredPartFileName(librariesMap.name, addExtension: false), |
| 135 fragment.name, | 135 librariesMap.name, |
| 136 mainOutput, | 136 mainOutput, |
| 137 _buildLibraries(fragment), | 137 _buildLibraries(librariesMap), |
| 138 _buildStaticNonFinalFields(fragment), | 138 _buildStaticNonFinalFields(librariesMap), |
| 139 _buildStaticLazilyInitializedFields(fragment), | 139 _buildStaticLazilyInitializedFields(librariesMap), |
| 140 _buildConstants(fragment)); | 140 _buildConstants(librariesMap)); |
| 141 _outputs[fragment.outputUnit] = result; | 141 _outputs[librariesMap.outputUnit] = result; |
| 142 return result; | 142 return result; |
| 143 } | 143 } |
| 144 | 144 |
| 145 List<Constant> _buildConstants(Fragment fragment) { | 145 List<Constant> _buildConstants(LibrariesMap librariesMap) { |
| 146 List<ConstantValue> constantValues = | 146 List<ConstantValue> constantValues = |
| 147 _task.outputConstantLists[fragment.outputUnit]; | 147 _task.outputConstantLists[librariesMap.outputUnit]; |
| 148 if (constantValues == null) return const <Constant>[]; | 148 if (constantValues == null) return const <Constant>[]; |
| 149 return constantValues.map((ConstantValue value) => _constants[value]) | 149 return constantValues.map((ConstantValue value) => _constants[value]) |
| 150 .toList(growable: false); | 150 .toList(growable: false); |
| 151 } | 151 } |
| 152 | 152 |
| 153 List<StaticField> _buildStaticNonFinalFields(Fragment fragment) { | 153 List<StaticField> _buildStaticNonFinalFields(LibrariesMap librariesMap) { |
| 154 // TODO(floitsch): handle static non-final fields correctly with deferred | 154 // TODO(floitsch): handle static non-final fields correctly with deferred |
| 155 // libraries. | 155 // libraries. |
| 156 if (fragment != _registry.mainFragment) return const <StaticField>[]; | 156 if (librariesMap != _registry.mainLibrariesMap) { |
| 157 return const <StaticField>[]; |
| 158 } |
| 157 Iterable<VariableElement> staticNonFinalFields = | 159 Iterable<VariableElement> staticNonFinalFields = |
| 158 backend.constants.getStaticNonFinalFieldsForEmission(); | 160 backend.constants.getStaticNonFinalFieldsForEmission(); |
| 159 return Elements.sortedByPosition(staticNonFinalFields) | 161 return Elements.sortedByPosition(staticNonFinalFields) |
| 160 .map(_buildStaticField) | 162 .map(_buildStaticField) |
| 161 .toList(growable: false); | 163 .toList(growable: false); |
| 162 } | 164 } |
| 163 | 165 |
| 164 StaticField _buildStaticField(Element element) { | 166 StaticField _buildStaticField(Element element) { |
| 165 JavaScriptConstantCompiler handler = backend.constants; | 167 JavaScriptConstantCompiler handler = backend.constants; |
| 166 ConstantValue initialValue = handler.getInitialValueFor(element).value; | 168 ConstantValue initialValue = handler.getInitialValueFor(element).value; |
| 167 js.Expression code = _task.emitter.constantReference(initialValue); | 169 js.Expression code = _task.emitter.constantReference(initialValue); |
| 168 String name = namer.getNameOfGlobalField(element); | 170 String name = namer.getNameOfGlobalField(element); |
| 169 bool isFinal = false; | 171 bool isFinal = false; |
| 170 bool isLazy = false; | 172 bool isLazy = false; |
| 171 return new StaticField(element, | 173 return new StaticField(element, |
| 172 name, _registry.registerHolder(r'$'), code, | 174 name, _registry.registerHolder(r'$'), code, |
| 173 isFinal, isLazy); | 175 isFinal, isLazy); |
| 174 } | 176 } |
| 175 | 177 |
| 176 List<StaticField> _buildStaticLazilyInitializedFields(Fragment fragment) { | 178 List<StaticField> _buildStaticLazilyInitializedFields( |
| 179 LibrariesMap librariesMap) { |
| 177 // TODO(floitsch): lazy fields should just be in their respective | 180 // TODO(floitsch): lazy fields should just be in their respective |
| 178 // libraries. | 181 // libraries. |
| 179 if (fragment != _registry.mainFragment) return const <StaticField>[]; | 182 if (librariesMap != _registry.mainLibrariesMap) { |
| 183 return const <StaticField>[]; |
| 184 } |
| 180 | 185 |
| 181 JavaScriptConstantCompiler handler = backend.constants; | 186 JavaScriptConstantCompiler handler = backend.constants; |
| 182 List<VariableElement> lazyFields = | 187 List<VariableElement> lazyFields = |
| 183 handler.getLazilyInitializedFieldsForEmission(); | 188 handler.getLazilyInitializedFieldsForEmission(); |
| 184 return Elements.sortedByPosition(lazyFields) | 189 return Elements.sortedByPosition(lazyFields) |
| 185 .map(_buildLazyField) | 190 .map(_buildLazyField) |
| 186 .where((field) => field != null) // Happens when the field was unused. | 191 .where((field) => field != null) // Happens when the field was unused. |
| 187 .toList(growable: false); | 192 .toList(growable: false); |
| 188 } | 193 } |
| 189 | 194 |
| 190 StaticField _buildLazyField(Element element) { | 195 StaticField _buildLazyField(Element element) { |
| 191 JavaScriptConstantCompiler handler = backend.constants; | 196 JavaScriptConstantCompiler handler = backend.constants; |
| 192 js.Expression code = backend.generatedCode[element]; | 197 js.Expression code = backend.generatedCode[element]; |
| 193 // The code is null if we ended up not needing the lazily | 198 // The code is null if we ended up not needing the lazily |
| 194 // initialized field after all because of constant folding | 199 // initialized field after all because of constant folding |
| 195 // before code generation. | 200 // before code generation. |
| 196 if (code == null) return null; | 201 if (code == null) return null; |
| 197 | 202 |
| 198 String name = namer.getNameOfGlobalField(element); | 203 String name = namer.getNameOfGlobalField(element); |
| 199 bool isFinal = element.isFinal; | 204 bool isFinal = element.isFinal; |
| 200 bool isLazy = true; | 205 bool isLazy = true; |
| 201 return new StaticField(element, | 206 return new StaticField(element, |
| 202 name, _registry.registerHolder(r'$'), code, | 207 name, _registry.registerHolder(r'$'), code, |
| 203 isFinal, isLazy); | 208 isFinal, isLazy); |
| 204 } | 209 } |
| 205 | 210 |
| 206 List<Library> _buildLibraries(Fragment fragment) { | 211 List<Library> _buildLibraries(LibrariesMap librariesMap) { |
| 207 List<Library> libraries = new List<Library>(fragment.length); | 212 List<Library> libraries = new List<Library>(librariesMap.length); |
| 208 int count = 0; | 213 int count = 0; |
| 209 fragment.forEach((LibraryElement library, List<Element> elements) { | 214 librariesMap.forEach((LibraryElement library, List<Element> elements) { |
| 210 libraries[count++] = _buildLibrary(library, elements); | 215 libraries[count++] = _buildLibrary(library, elements); |
| 211 }); | 216 }); |
| 212 return libraries; | 217 return libraries; |
| 213 } | 218 } |
| 214 | 219 |
| 215 // Note that a library-element may have multiple [Library]s, if it is split | 220 // Note that a library-element may have multiple [Library]s, if it is split |
| 216 // into multiple output units. | 221 // into multiple output units. |
| 217 Library _buildLibrary(LibraryElement library, List<Element> elements) { | 222 Library _buildLibrary(LibraryElement library, List<Element> elements) { |
| 218 String uri = library.canonicalUri.toString(); | 223 String uri = library.canonicalUri.toString(); |
| 219 | 224 |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 438 _registry.registerConstant(outputUnit, constantValue); | 443 _registry.registerConstant(outputUnit, constantValue); |
| 439 assert(!_constants.containsKey(constantValue)); | 444 assert(!_constants.containsKey(constantValue)); |
| 440 String name = namer.constantName(constantValue); | 445 String name = namer.constantName(constantValue); |
| 441 String constantObject = namer.globalObjectForConstant(constantValue); | 446 String constantObject = namer.globalObjectForConstant(constantValue); |
| 442 Holder holder = _registry.registerHolder(constantObject); | 447 Holder holder = _registry.registerHolder(constantObject); |
| 443 Constant constant = new Constant(name, holder, constantValue); | 448 Constant constant = new Constant(name, holder, constantValue); |
| 444 _constants[constantValue] = constant; | 449 _constants[constantValue] = constant; |
| 445 }; | 450 }; |
| 446 } | 451 } |
| 447 } | 452 } |
| OLD | NEW |