| 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 |