| 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, Emitter; |
| 8 import '../model.dart'; | 8 import '../model.dart'; |
| 9 | 9 |
| 10 import '../../common.dart'; | 10 import '../../common.dart'; |
| 11 import '../../js/js.dart' as js; | 11 import '../../js/js.dart' as js; |
| 12 | 12 |
| 13 import '../../js_backend/js_backend.dart' show | 13 import '../../js_backend/js_backend.dart' show |
| 14 Namer, | 14 Namer, |
| 15 JavaScriptBackend, | 15 JavaScriptBackend, |
| 16 JavaScriptConstantCompiler; | 16 JavaScriptConstantCompiler; |
| 17 | 17 |
| 18 import '../js_emitter.dart' show | 18 import '../js_emitter.dart' show |
| 19 ClassStubGenerator, | 19 ClassStubGenerator, |
| 20 CodeEmitterTask, | 20 CodeEmitterTask, |
| 21 InterceptorStubGenerator, | 21 InterceptorStubGenerator, |
| 22 MainCallStubGenerator, | 22 MainCallStubGenerator, |
| 23 ParameterStubGenerator, | 23 ParameterStubGenerator, |
| 24 RuntimeTypeGenerator, | 24 RuntimeTypeGenerator, |
| 25 TypeTestProperties; | 25 TypeTestProperties; |
| 26 | 26 |
| 27 import '../../elements/elements.dart' show ParameterElement, MethodElement; | 27 import '../../elements/elements.dart' show ParameterElement, MethodElement; |
| 28 | 28 |
| 29 import '../../universe/universe.dart' show Universe, TypeMaskSet; | 29 import '../../universe/universe.dart' show Universe, TypeMaskSet; |
| 30 import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit; | 30 import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit; |
| 31 | 31 |
| 32 part 'collector.dart'; |
| 32 part 'registry.dart'; | 33 part 'registry.dart'; |
| 33 | 34 |
| 34 /// Builds a self-contained representation of the program that can then be | 35 /// Builds a self-contained representation of the program that can then be |
| 35 /// emitted more easily by the individual emitters. | 36 /// emitted more easily by the individual emitters. |
| 36 class ProgramBuilder { | 37 class ProgramBuilder { |
| 37 final Compiler _compiler; | 38 final Compiler _compiler; |
| 38 final Namer namer; | 39 final Namer namer; |
| 39 final CodeEmitterTask _task; | 40 final CodeEmitterTask _task; |
| 40 | 41 |
| 42 /// Contains the collected information the program builder used to build |
| 43 /// the model. |
| 44 // The collector will be filled on the first call to `buildProgram`. |
| 45 // It is stored and publicly exposed for backwards compatibility. |
| 46 final Collector collector; |
| 47 |
| 41 final Registry _registry; | 48 final Registry _registry; |
| 42 | 49 |
| 43 /// True if the program should store function types in the metadata. | 50 /// True if the program should store function types in the metadata. |
| 44 bool _storeFunctionTypesInMetadata = false; | 51 bool _storeFunctionTypesInMetadata = false; |
| 45 | 52 |
| 46 ProgramBuilder(Compiler compiler, | 53 ProgramBuilder(Compiler compiler, |
| 47 this.namer, | 54 Namer namer, |
| 48 this._task) | 55 this._task, |
| 56 Emitter emitter, |
| 57 Emitter oldEmitter, |
| 58 Set<ClassElement> rtiNeededClasses) |
| 49 : this._compiler = compiler, | 59 : this._compiler = compiler, |
| 60 this.namer = namer, |
| 61 this.collector = new Collector( |
| 62 compiler, namer, rtiNeededClasses, emitter, oldEmitter), |
| 50 this._registry = new Registry(compiler); | 63 this._registry = new Registry(compiler); |
| 51 | 64 |
| 52 JavaScriptBackend get backend => _compiler.backend; | 65 JavaScriptBackend get backend => _compiler.backend; |
| 53 Universe get universe => _compiler.codegenWorld; | 66 Universe get universe => _compiler.codegenWorld; |
| 54 | 67 |
| 55 /// Mapping from [ClassElement] to constructed [Class]. We need this to | 68 /// Mapping from [ClassElement] to constructed [Class]. We need this to |
| 56 /// update the superclass in the [Class]. | 69 /// update the superclass in the [Class]. |
| 57 final Map<ClassElement, Class> _classes = <ClassElement, Class>{}; | 70 final Map<ClassElement, Class> _classes = <ClassElement, Class>{}; |
| 58 | 71 |
| 59 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to | 72 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to |
| 60 /// generate the deferredLoadingMap (to know which hunks to load). | 73 /// generate the deferredLoadingMap (to know which hunks to load). |
| 61 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{}; | 74 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{}; |
| 62 | 75 |
| 63 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to | 76 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to |
| 64 /// update field-initializers to point to the ConstantModel. | 77 /// update field-initializers to point to the ConstantModel. |
| 65 final Map<ConstantValue, Constant> _constants = <ConstantValue, Constant>{}; | 78 final Map<ConstantValue, Constant> _constants = <ConstantValue, Constant>{}; |
| 66 | 79 |
| 67 Set<Class> _unneededNativeClasses; | 80 Set<Class> _unneededNativeClasses; |
| 68 | 81 |
| 69 Program buildProgram({bool storeFunctionTypesInMetadata: false}) { | 82 Program buildProgram({bool storeFunctionTypesInMetadata: false}) { |
| 83 collector.collect(); |
| 84 |
| 70 this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata; | 85 this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata; |
| 71 // Note: In rare cases (mostly tests) output units can be empty. This | 86 // Note: In rare cases (mostly tests) output units can be empty. This |
| 72 // happens when the deferred code is dead-code eliminated but we still need | 87 // happens when the deferred code is dead-code eliminated but we still need |
| 73 // to check that the library has been loaded. | 88 // to check that the library has been loaded. |
| 74 _compiler.deferredLoadTask.allOutputUnits.forEach( | 89 _compiler.deferredLoadTask.allOutputUnits.forEach( |
| 75 _registry.registerOutputUnit); | 90 _registry.registerOutputUnit); |
| 76 _task.outputClassLists.forEach(_registry.registerElements); | 91 collector.outputClassLists.forEach(_registry.registerElements); |
| 77 _task.outputStaticLists.forEach(_registry.registerElements); | 92 collector.outputStaticLists.forEach(_registry.registerElements); |
| 78 _task.outputConstantLists.forEach(_registerConstants); | 93 collector.outputConstantLists.forEach(_registerConstants); |
| 79 _task.outputStaticNonFinalFieldLists.forEach(_registry.registerElements); | 94 collector.outputStaticNonFinalFieldLists.forEach( |
| 95 _registry.registerElements); |
| 80 | 96 |
| 81 // TODO(kasperl): There's code that implicitly needs access to the special | 97 // TODO(kasperl): There's code that implicitly needs access to the special |
| 82 // $ holder so we have to register that. Can we track if we have to? | 98 // $ holder so we have to register that. Can we track if we have to? |
| 83 _registry.registerHolder(r'$'); | 99 _registry.registerHolder(r'$'); |
| 84 | 100 |
| 85 // We need to run the native-preparation before we build the output. The | 101 // We need to run the native-preparation before we build the output. The |
| 86 // preparation code, in turn needs the classes to be set up. | 102 // preparation code, in turn needs the classes to be set up. |
| 87 // We thus build the classes before building their containers. | 103 // We thus build the classes before building their containers. |
| 88 _task.outputClassLists.forEach((OutputUnit _, List<ClassElement> classes) { | 104 collector.outputClassLists.forEach((OutputUnit _, List<ClassElement> classes
) { |
| 89 classes.forEach(_buildClass); | 105 classes.forEach(_buildClass); |
| 90 }); | 106 }); |
| 91 | 107 |
| 92 // Resolve the superclass references after we've processed all the classes. | 108 // Resolve the superclass references after we've processed all the classes. |
| 93 _classes.forEach((ClassElement element, Class c) { | 109 _classes.forEach((ClassElement element, Class c) { |
| 94 if (element.superclass != null) { | 110 if (element.superclass != null) { |
| 95 c.setSuperclass(_classes[element.superclass]); | 111 c.setSuperclass(_classes[element.superclass]); |
| 96 assert(c.superclass != null); | 112 assert(c.superclass != null); |
| 97 } | 113 } |
| 98 if (c is MixinApplication) { | 114 if (c is MixinApplication) { |
| 99 c.setMixinClass(_classes[computeMixinClass(element)]); | 115 c.setMixinClass(_classes[computeMixinClass(element)]); |
| 100 assert(c.mixinClass != null); | 116 assert(c.mixinClass != null); |
| 101 } | 117 } |
| 102 }); | 118 }); |
| 103 | 119 |
| 104 List<Class> nativeClasses = _task.nativeClassesAndSubclasses | 120 List<Class> nativeClasses = collector.nativeClassesAndSubclasses |
| 105 .map((ClassElement classElement) => _classes[classElement]) | 121 .map((ClassElement classElement) => _classes[classElement]) |
| 106 .toList(); | 122 .toList(); |
| 107 | 123 |
| 108 _unneededNativeClasses = | 124 Set<ClassElement> interceptorClassesNeededByConstants = |
| 109 _task.nativeEmitter.prepareNativeClasses(nativeClasses); | 125 collector.computeInterceptorsReferencedFromConstants(); |
| 126 Set<ClassElement> classesModifiedByEmitRTISupport = |
| 127 _task.typeTestRegistry.computeClassesModifiedByEmitRuntimeTypeSupport(); |
| 128 |
| 129 |
| 130 _unneededNativeClasses = _task.nativeEmitter.prepareNativeClasses( |
| 131 nativeClasses, interceptorClassesNeededByConstants, |
| 132 classesModifiedByEmitRTISupport); |
| 110 | 133 |
| 111 MainFragment mainFragment = _buildMainFragment(_registry.mainLibrariesMap); | 134 MainFragment mainFragment = _buildMainFragment(_registry.mainLibrariesMap); |
| 112 Iterable<Fragment> deferredFragments = | 135 Iterable<Fragment> deferredFragments = |
| 113 _registry.deferredLibrariesMap.map(_buildDeferredFragment); | 136 _registry.deferredLibrariesMap.map(_buildDeferredFragment); |
| 114 | 137 |
| 115 List<Fragment> fragments = new List<Fragment>(_registry.librariesMapCount); | 138 List<Fragment> fragments = new List<Fragment>(_registry.librariesMapCount); |
| 116 fragments[0] = mainFragment; | 139 fragments[0] = mainFragment; |
| 117 fragments.setAll(1, deferredFragments); | 140 fragments.setAll(1, deferredFragments); |
| 118 | 141 |
| 119 _markEagerClasses(); | 142 _markEagerClasses(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 132 } | 155 } |
| 133 | 156 |
| 134 return new Program( | 157 return new Program( |
| 135 fragments, | 158 fragments, |
| 136 holders, | 159 holders, |
| 137 _buildLoadMap(), | 160 _buildLoadMap(), |
| 138 _buildTypeToInterceptorMap(), | 161 _buildTypeToInterceptorMap(), |
| 139 _task.metadataCollector, | 162 _task.metadataCollector, |
| 140 finalizers, | 163 finalizers, |
| 141 needsNativeSupport: needsNativeSupport, | 164 needsNativeSupport: needsNativeSupport, |
| 142 outputContainsConstantList: _task.outputContainsConstantList, | 165 outputContainsConstantList: collector.outputContainsConstantList, |
| 143 hasIsolateSupport: _compiler.hasIsolateSupport); | 166 hasIsolateSupport: _compiler.hasIsolateSupport); |
| 144 } | 167 } |
| 145 | 168 |
| 146 void _markEagerClasses() { | 169 void _markEagerClasses() { |
| 147 _markEagerInterceptorClasses(); | 170 _markEagerInterceptorClasses(); |
| 148 } | 171 } |
| 149 | 172 |
| 150 /// Builds a map from loadId to outputs-to-load. | 173 /// Builds a map from loadId to outputs-to-load. |
| 151 Map<String, List<Fragment>> _buildLoadMap() { | 174 Map<String, List<Fragment>> _buildLoadMap() { |
| 152 Map<String, List<Fragment>> loadMap = <String, List<Fragment>>{}; | 175 Map<String, List<Fragment>> loadMap = <String, List<Fragment>>{}; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 _buildLibraries(librariesMap), | 216 _buildLibraries(librariesMap), |
| 194 _buildStaticNonFinalFields(librariesMap), | 217 _buildStaticNonFinalFields(librariesMap), |
| 195 _buildStaticLazilyInitializedFields(librariesMap), | 218 _buildStaticLazilyInitializedFields(librariesMap), |
| 196 _buildConstants(librariesMap)); | 219 _buildConstants(librariesMap)); |
| 197 _outputs[librariesMap.outputUnit] = result; | 220 _outputs[librariesMap.outputUnit] = result; |
| 198 return result; | 221 return result; |
| 199 } | 222 } |
| 200 | 223 |
| 201 List<Constant> _buildConstants(LibrariesMap librariesMap) { | 224 List<Constant> _buildConstants(LibrariesMap librariesMap) { |
| 202 List<ConstantValue> constantValues = | 225 List<ConstantValue> constantValues = |
| 203 _task.outputConstantLists[librariesMap.outputUnit]; | 226 collector.outputConstantLists[librariesMap.outputUnit]; |
| 204 if (constantValues == null) return const <Constant>[]; | 227 if (constantValues == null) return const <Constant>[]; |
| 205 return constantValues.map((ConstantValue value) => _constants[value]) | 228 return constantValues.map((ConstantValue value) => _constants[value]) |
| 206 .toList(growable: false); | 229 .toList(growable: false); |
| 207 } | 230 } |
| 208 | 231 |
| 209 List<StaticField> _buildStaticNonFinalFields(LibrariesMap librariesMap) { | 232 List<StaticField> _buildStaticNonFinalFields(LibrariesMap librariesMap) { |
| 210 List<VariableElement> staticNonFinalFields = | 233 List<VariableElement> staticNonFinalFields = |
| 211 _task.outputStaticNonFinalFieldLists[librariesMap.outputUnit]; | 234 collector.outputStaticNonFinalFieldLists[librariesMap.outputUnit]; |
| 212 if (staticNonFinalFields == null) return const <StaticField>[]; | 235 if (staticNonFinalFields == null) return const <StaticField>[]; |
| 213 | 236 |
| 214 return staticNonFinalFields | 237 return staticNonFinalFields |
| 215 .map(_buildStaticField) | 238 .map(_buildStaticField) |
| 216 .toList(growable: false); | 239 .toList(growable: false); |
| 217 } | 240 } |
| 218 | 241 |
| 219 StaticField _buildStaticField(Element element) { | 242 StaticField _buildStaticField(Element element) { |
| 220 JavaScriptConstantCompiler handler = backend.constants; | 243 JavaScriptConstantCompiler handler = backend.constants; |
| 221 ConstantValue initialValue = handler.getInitialValueFor(element); | 244 ConstantValue initialValue = handler.getInitialValueFor(element); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 js.Name name = namer.className(element); | 341 js.Name name = namer.className(element); |
| 319 | 342 |
| 320 return new Class( | 343 return new Class( |
| 321 element, name, null, [], instanceFields, [], [], [], [], [], null, | 344 element, name, null, [], instanceFields, [], [], [], [], [], null, |
| 322 isDirectlyInstantiated: true, | 345 isDirectlyInstantiated: true, |
| 323 onlyForRti: false, | 346 onlyForRti: false, |
| 324 isNative: element.isNative); | 347 isNative: element.isNative); |
| 325 } | 348 } |
| 326 | 349 |
| 327 Class _buildClass(ClassElement element) { | 350 Class _buildClass(ClassElement element) { |
| 328 bool onlyForRti = _task.classesOnlyNeededForRti.contains(element); | 351 bool onlyForRti = collector.classesOnlyNeededForRti.contains(element); |
| 329 | 352 |
| 330 List<Method> methods = []; | 353 List<Method> methods = []; |
| 331 List<StubMethod> callStubs = <StubMethod>[]; | 354 List<StubMethod> callStubs = <StubMethod>[]; |
| 332 | 355 |
| 333 ClassStubGenerator classStubGenerator = | 356 ClassStubGenerator classStubGenerator = |
| 334 new ClassStubGenerator(_compiler, namer, backend); | 357 new ClassStubGenerator(_compiler, namer, backend); |
| 335 RuntimeTypeGenerator runtimeTypeGenerator = | 358 RuntimeTypeGenerator runtimeTypeGenerator = |
| 336 new RuntimeTypeGenerator(_compiler, _task, namer); | 359 new RuntimeTypeGenerator(_compiler, _task, namer); |
| 337 | 360 |
| 338 void visitMember(ClassElement enclosing, Element member) { | 361 void visitMember(ClassElement enclosing, Element member) { |
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 762 _registry.registerConstant(outputUnit, constantValue); | 785 _registry.registerConstant(outputUnit, constantValue); |
| 763 assert(!_constants.containsKey(constantValue)); | 786 assert(!_constants.containsKey(constantValue)); |
| 764 js.Name name = namer.constantName(constantValue); | 787 js.Name name = namer.constantName(constantValue); |
| 765 String constantObject = namer.globalObjectForConstant(constantValue); | 788 String constantObject = namer.globalObjectForConstant(constantValue); |
| 766 Holder holder = _registry.registerHolder(constantObject); | 789 Holder holder = _registry.registerHolder(constantObject); |
| 767 Constant constant = new Constant(name, holder, constantValue); | 790 Constant constant = new Constant(name, holder, constantValue); |
| 768 _constants[constantValue] = constant; | 791 _constants[constantValue] = constant; |
| 769 } | 792 } |
| 770 } | 793 } |
| 771 } | 794 } |
| OLD | NEW |