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 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 } | 97 } |
98 }); | 98 }); |
99 | 99 |
100 List<Class> nativeClasses = _task.nativeClassesAndSubclasses | 100 List<Class> nativeClasses = _task.nativeClassesAndSubclasses |
101 .map((ClassElement classElement) => _classes[classElement]) | 101 .map((ClassElement classElement) => _classes[classElement]) |
102 .toList(); | 102 .toList(); |
103 | 103 |
104 _unneededNativeClasses = | 104 _unneededNativeClasses = |
105 _task.nativeEmitter.prepareNativeClasses(nativeClasses); | 105 _task.nativeEmitter.prepareNativeClasses(nativeClasses); |
106 | 106 |
107 MainFragment mainOutput = _buildMainOutput(_registry.mainLibrariesMap); | 107 MainFragment mainFragment = _buildMainFragment(_registry.mainLibrariesMap); |
108 Iterable<Fragment> deferredOutputs = _registry.deferredLibrariesMap | 108 Iterable<Fragment> deferredFragments = |
109 .map((librariesMap) => _buildDeferredOutput(mainOutput, librariesMap)); | 109 _registry.deferredLibrariesMap.map(_buildDeferredFragment); |
110 | 110 |
111 List<Fragment> outputs = new List<Fragment>(_registry.librariesMapCount); | 111 List<Fragment> fragments = new List<Fragment>(_registry.librariesMapCount); |
112 outputs[0] = mainOutput; | 112 fragments[0] = mainFragment; |
113 outputs.setAll(1, deferredOutputs); | 113 fragments.setAll(1, deferredFragments); |
114 | 114 |
115 _markEagerClasses(); | 115 _markEagerClasses(); |
116 | 116 |
117 bool containsNativeClasses = | 117 bool containsNativeClasses = |
118 nativeClasses.length != _unneededNativeClasses.length; | 118 nativeClasses.length != _unneededNativeClasses.length; |
119 | 119 |
| 120 List<Holder> holders = _registry.holders.toList(growable: false); |
| 121 |
120 return new Program( | 122 return new Program( |
121 outputs, | 123 fragments, |
| 124 holders, |
122 _buildLoadMap(), | 125 _buildLoadMap(), |
123 _buildTypeToInterceptorMap(), | 126 _buildTypeToInterceptorMap(), |
124 _task.metadataCollector, | 127 _task.metadataCollector, |
125 outputContainsNativeClasses: containsNativeClasses, | 128 outputContainsNativeClasses: containsNativeClasses, |
126 outputContainsConstantList: _task.outputContainsConstantList, | 129 outputContainsConstantList: _task.outputContainsConstantList, |
127 hasIsolateSupport: _compiler.hasIsolateSupport); | 130 hasIsolateSupport: _compiler.hasIsolateSupport); |
128 } | 131 } |
129 | 132 |
130 void _markEagerClasses() { | 133 void _markEagerClasses() { |
131 _markEagerInterceptorClasses(); | 134 _markEagerInterceptorClasses(); |
(...skipping 10 matching lines...) Expand all Loading... |
142 }); | 145 }); |
143 return loadMap; | 146 return loadMap; |
144 } | 147 } |
145 | 148 |
146 js.Expression _buildTypeToInterceptorMap() { | 149 js.Expression _buildTypeToInterceptorMap() { |
147 InterceptorStubGenerator stubGenerator = | 150 InterceptorStubGenerator stubGenerator = |
148 new InterceptorStubGenerator(_compiler, namer, backend); | 151 new InterceptorStubGenerator(_compiler, namer, backend); |
149 return stubGenerator.generateTypeToInterceptorMap(); | 152 return stubGenerator.generateTypeToInterceptorMap(); |
150 } | 153 } |
151 | 154 |
152 MainFragment _buildMainOutput(LibrariesMap librariesMap) { | 155 MainFragment _buildMainFragment(LibrariesMap librariesMap) { |
153 // Construct the main output from the libraries and the registered holders. | 156 // Construct the main output from the libraries and the registered holders. |
154 MainFragment result = new MainFragment( | 157 MainFragment result = new MainFragment( |
155 librariesMap.outputUnit, | 158 librariesMap.outputUnit, |
156 "", // The empty string is the name for the main output file. | 159 "", // The empty string is the name for the main output file. |
157 _buildInvokeMain(), | 160 _buildInvokeMain(), |
158 _buildLibraries(librariesMap), | 161 _buildLibraries(librariesMap), |
159 _buildStaticNonFinalFields(librariesMap), | 162 _buildStaticNonFinalFields(librariesMap), |
160 _buildStaticLazilyInitializedFields(librariesMap), | 163 _buildStaticLazilyInitializedFields(librariesMap), |
161 _buildConstants(librariesMap), | 164 _buildConstants(librariesMap)); |
162 _registry.holders.toList(growable: false)); | |
163 _outputs[librariesMap.outputUnit] = result; | 165 _outputs[librariesMap.outputUnit] = result; |
164 return result; | 166 return result; |
165 } | 167 } |
166 | 168 |
167 js.Statement _buildInvokeMain() { | 169 js.Statement _buildInvokeMain() { |
168 MainCallStubGenerator generator = | 170 MainCallStubGenerator generator = |
169 new MainCallStubGenerator(_compiler, backend, backend.emitter); | 171 new MainCallStubGenerator(_compiler, backend, backend.emitter); |
170 return generator.generateInvokeMain(); | 172 return generator.generateInvokeMain(); |
171 } | 173 } |
172 | 174 |
173 DeferredFragment _buildDeferredOutput(MainFragment mainOutput, | 175 DeferredFragment _buildDeferredFragment(LibrariesMap librariesMap) { |
174 LibrariesMap librariesMap) { | |
175 DeferredFragment result = new DeferredFragment( | 176 DeferredFragment result = new DeferredFragment( |
176 librariesMap.outputUnit, | 177 librariesMap.outputUnit, |
177 backend.deferredPartFileName(librariesMap.name, addExtension: false), | 178 backend.deferredPartFileName(librariesMap.name, addExtension: false), |
178 librariesMap.name, | 179 librariesMap.name, |
179 mainOutput, | |
180 _buildLibraries(librariesMap), | 180 _buildLibraries(librariesMap), |
181 _buildStaticNonFinalFields(librariesMap), | 181 _buildStaticNonFinalFields(librariesMap), |
182 _buildStaticLazilyInitializedFields(librariesMap), | 182 _buildStaticLazilyInitializedFields(librariesMap), |
183 _buildConstants(librariesMap)); | 183 _buildConstants(librariesMap)); |
184 _outputs[librariesMap.outputUnit] = result; | 184 _outputs[librariesMap.outputUnit] = result; |
185 return result; | 185 return result; |
186 } | 186 } |
187 | 187 |
188 List<Constant> _buildConstants(LibrariesMap librariesMap) { | 188 List<Constant> _buildConstants(LibrariesMap librariesMap) { |
189 List<ConstantValue> constantValues = | 189 List<ConstantValue> constantValues = |
(...skipping 16 matching lines...) Expand all Loading... |
206 .toList(growable: false); | 206 .toList(growable: false); |
207 } | 207 } |
208 | 208 |
209 StaticField _buildStaticField(Element element) { | 209 StaticField _buildStaticField(Element element) { |
210 JavaScriptConstantCompiler handler = backend.constants; | 210 JavaScriptConstantCompiler handler = backend.constants; |
211 ConstantValue initialValue = handler.getInitialValueFor(element).value; | 211 ConstantValue initialValue = handler.getInitialValueFor(element).value; |
212 js.Expression code = _task.emitter.constantReference(initialValue); | 212 js.Expression code = _task.emitter.constantReference(initialValue); |
213 String name = namer.getNameOfGlobalField(element); | 213 String name = namer.getNameOfGlobalField(element); |
214 bool isFinal = false; | 214 bool isFinal = false; |
215 bool isLazy = false; | 215 bool isLazy = false; |
| 216 |
| 217 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 218 // building a static field. (Note that the $ holder is already registered |
| 219 // earlier). |
216 return new StaticField(element, | 220 return new StaticField(element, |
217 name, _registry.registerHolder(r'$'), code, | 221 name, _registry.registerHolder(r'$'), code, |
218 isFinal, isLazy); | 222 isFinal, isLazy); |
219 } | 223 } |
220 | 224 |
221 List<StaticField> _buildStaticLazilyInitializedFields( | 225 List<StaticField> _buildStaticLazilyInitializedFields( |
222 LibrariesMap librariesMap) { | 226 LibrariesMap librariesMap) { |
223 // TODO(floitsch): lazy fields should just be in their respective | 227 // TODO(floitsch): lazy fields should just be in their respective |
224 // libraries. | 228 // libraries. |
225 if (librariesMap != _registry.mainLibrariesMap) { | 229 if (librariesMap != _registry.mainLibrariesMap) { |
(...skipping 12 matching lines...) Expand all Loading... |
238 StaticField _buildLazyField(Element element) { | 242 StaticField _buildLazyField(Element element) { |
239 js.Expression code = backend.generatedCode[element]; | 243 js.Expression code = backend.generatedCode[element]; |
240 // The code is null if we ended up not needing the lazily | 244 // The code is null if we ended up not needing the lazily |
241 // initialized field after all because of constant folding | 245 // initialized field after all because of constant folding |
242 // before code generation. | 246 // before code generation. |
243 if (code == null) return null; | 247 if (code == null) return null; |
244 | 248 |
245 String name = namer.getNameOfGlobalField(element); | 249 String name = namer.getNameOfGlobalField(element); |
246 bool isFinal = element.isFinal; | 250 bool isFinal = element.isFinal; |
247 bool isLazy = true; | 251 bool isLazy = true; |
| 252 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 253 // building a static field. (Note that the $ holder is already registered |
| 254 // earlier). |
248 return new StaticField(element, | 255 return new StaticField(element, |
249 name, _registry.registerHolder(r'$'), code, | 256 name, _registry.registerHolder(r'$'), code, |
250 isFinal, isLazy); | 257 isFinal, isLazy); |
251 } | 258 } |
252 | 259 |
253 List<Library> _buildLibraries(LibrariesMap librariesMap) { | 260 List<Library> _buildLibraries(LibrariesMap librariesMap) { |
254 List<Library> libraries = new List<Library>(librariesMap.length); | 261 List<Library> libraries = new List<Library>(librariesMap.length); |
255 int count = 0; | 262 int count = 0; |
256 librariesMap.forEach((LibraryElement library, List<Element> elements) { | 263 librariesMap.forEach((LibraryElement library, List<Element> elements) { |
257 libraries[count++] = _buildLibrary(library, elements); | 264 libraries[count++] = _buildLibrary(library, elements); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 element, | 375 element, |
369 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); | 376 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); |
370 | 377 |
371 List<StubMethod> isChecks = <StubMethod>[]; | 378 List<StubMethod> isChecks = <StubMethod>[]; |
372 typeTests.properties.forEach((String name, js.Node code) { | 379 typeTests.properties.forEach((String name, js.Node code) { |
373 isChecks.add(_buildStubMethod(name, code)); | 380 isChecks.add(_buildStubMethod(name, code)); |
374 }); | 381 }); |
375 | 382 |
376 String name = namer.getNameOfClass(element); | 383 String name = namer.getNameOfClass(element); |
377 String holderName = namer.globalObjectFor(element); | 384 String holderName = namer.globalObjectFor(element); |
| 385 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 386 // building a class. |
378 Holder holder = _registry.registerHolder(holderName); | 387 Holder holder = _registry.registerHolder(holderName); |
379 bool isInstantiated = | 388 bool isInstantiated = |
380 _compiler.codegenWorld.directlyInstantiatedClasses.contains(element); | 389 _compiler.codegenWorld.directlyInstantiatedClasses.contains(element); |
381 | 390 |
382 Class result; | 391 Class result; |
383 if (element.isMixinApplication && !onlyForRti) { | 392 if (element.isMixinApplication && !onlyForRti) { |
384 assert(!element.isNative); | 393 assert(!element.isNative); |
385 assert(methods.isEmpty); | 394 assert(methods.isEmpty); |
386 | 395 |
387 result = new MixinApplication(element, | 396 result = new MixinApplication(element, |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 if (cls != null) cls.isEager = true; | 542 if (cls != null) cls.isEager = true; |
534 } | 543 } |
535 } | 544 } |
536 } | 545 } |
537 | 546 |
538 Iterable<StaticStubMethod> _generateGetInterceptorMethods() { | 547 Iterable<StaticStubMethod> _generateGetInterceptorMethods() { |
539 InterceptorStubGenerator stubGenerator = | 548 InterceptorStubGenerator stubGenerator = |
540 new InterceptorStubGenerator(_compiler, namer, backend); | 549 new InterceptorStubGenerator(_compiler, namer, backend); |
541 | 550 |
542 String holderName = namer.globalObjectFor(backend.interceptorsLibrary); | 551 String holderName = namer.globalObjectFor(backend.interceptorsLibrary); |
| 552 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 553 // generating the interceptor methods. |
543 Holder holder = _registry.registerHolder(holderName); | 554 Holder holder = _registry.registerHolder(holderName); |
544 | 555 |
545 Map<String, Set<ClassElement>> specializedGetInterceptors = | 556 Map<String, Set<ClassElement>> specializedGetInterceptors = |
546 backend.specializedGetInterceptors; | 557 backend.specializedGetInterceptors; |
547 List<String> names = specializedGetInterceptors.keys.toList()..sort(); | 558 List<String> names = specializedGetInterceptors.keys.toList()..sort(); |
548 return names.map((String name) { | 559 return names.map((String name) { |
549 Set<ClassElement> classes = specializedGetInterceptors[name]; | 560 Set<ClassElement> classes = specializedGetInterceptors[name]; |
550 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); | 561 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); |
551 return new StaticStubMethod(name, holder, code); | 562 return new StaticStubMethod(name, holder, code); |
552 }); | 563 }); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 }); | 607 }); |
597 | 608 |
598 return fields; | 609 return fields; |
599 } | 610 } |
600 | 611 |
601 Iterable<StaticStubMethod> _generateOneShotInterceptors() { | 612 Iterable<StaticStubMethod> _generateOneShotInterceptors() { |
602 InterceptorStubGenerator stubGenerator = | 613 InterceptorStubGenerator stubGenerator = |
603 new InterceptorStubGenerator(_compiler, namer, backend); | 614 new InterceptorStubGenerator(_compiler, namer, backend); |
604 | 615 |
605 String holderName = namer.globalObjectFor(backend.interceptorsLibrary); | 616 String holderName = namer.globalObjectFor(backend.interceptorsLibrary); |
| 617 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 618 // generating the interceptor methods. |
606 Holder holder = _registry.registerHolder(holderName); | 619 Holder holder = _registry.registerHolder(holderName); |
607 | 620 |
608 List<String> names = backend.oneShotInterceptors.keys.toList()..sort(); | 621 List<String> names = backend.oneShotInterceptors.keys.toList()..sort(); |
609 return names.map((String name) { | 622 return names.map((String name) { |
610 js.Expression code = stubGenerator.generateOneShotInterceptor(name); | 623 js.Expression code = stubGenerator.generateOneShotInterceptor(name); |
611 return new StaticStubMethod(name, holder, code); | 624 return new StaticStubMethod(name, holder, code); |
612 }); | 625 }); |
613 } | 626 } |
614 | 627 |
615 StaticDartMethod _buildStaticMethod(FunctionElement element) { | 628 StaticDartMethod _buildStaticMethod(FunctionElement element) { |
(...skipping 12 matching lines...) Expand all Loading... |
628 String tearOffName = | 641 String tearOffName = |
629 needsTearOff ? namer.getStaticClosureName(element) : null; | 642 needsTearOff ? namer.getStaticClosureName(element) : null; |
630 | 643 |
631 String callName = null; | 644 String callName = null; |
632 if (needsTearOff) { | 645 if (needsTearOff) { |
633 Selector callSelector = | 646 Selector callSelector = |
634 new Selector.fromElement(element).toCallSelector(); | 647 new Selector.fromElement(element).toCallSelector(); |
635 callName = namer.invocationName(callSelector); | 648 callName = namer.invocationName(callSelector); |
636 } | 649 } |
637 | 650 |
| 651 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 652 // building a static method. |
638 return new StaticDartMethod(element, | 653 return new StaticDartMethod(element, |
639 name, _registry.registerHolder(holder), code, | 654 name, _registry.registerHolder(holder), code, |
640 _generateParameterStubs(element, needsTearOff), | 655 _generateParameterStubs(element, needsTearOff), |
641 callName, element.type, | 656 callName, element.type, |
642 needsTearOff: needsTearOff, | 657 needsTearOff: needsTearOff, |
643 tearOffName: tearOffName, | 658 tearOffName: tearOffName, |
644 canBeApplied: canBeApplied, | 659 canBeApplied: canBeApplied, |
645 canBeReflected: canBeReflected); | 660 canBeReflected: canBeReflected); |
646 } | 661 } |
647 | 662 |
648 void _registerConstants(OutputUnit outputUnit, | 663 void _registerConstants(OutputUnit outputUnit, |
649 Iterable<ConstantValue> constantValues) { | 664 Iterable<ConstantValue> constantValues) { |
650 // `constantValues` is null if an outputUnit doesn't contain any constants. | 665 // `constantValues` is null if an outputUnit doesn't contain any constants. |
651 if (constantValues == null) return; | 666 if (constantValues == null) return; |
652 for (ConstantValue constantValue in constantValues) { | 667 for (ConstantValue constantValue in constantValues) { |
653 _registry.registerConstant(outputUnit, constantValue); | 668 _registry.registerConstant(outputUnit, constantValue); |
654 assert(!_constants.containsKey(constantValue)); | 669 assert(!_constants.containsKey(constantValue)); |
655 String name = namer.constantName(constantValue); | 670 String name = namer.constantName(constantValue); |
656 String constantObject = namer.globalObjectForConstant(constantValue); | 671 String constantObject = namer.globalObjectForConstant(constantValue); |
657 Holder holder = _registry.registerHolder(constantObject); | 672 Holder holder = _registry.registerHolder(constantObject); |
658 Constant constant = new Constant(name, holder, constantValue); | 673 Constant constant = new Constant(name, holder, constantValue); |
659 _constants[constantValue] = constant; | 674 _constants[constantValue] = constant; |
660 } | 675 } |
661 } | 676 } |
662 } | 677 } |
OLD | NEW |