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.full_emitter; | 5 library dart2js.js_emitter.full_emitter; |
6 | 6 |
7 import 'dart:convert'; | 7 import 'dart:convert'; |
8 import 'dart:collection' show HashMap; | 8 import 'dart:collection' show HashMap; |
9 | 9 |
10 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames; | 10 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames; |
11 import 'package:js_runtime/shared/embedded_names.dart' show | 11 import 'package:js_runtime/shared/embedded_names.dart' show |
12 JsBuiltin, | 12 JsBuiltin, |
13 JsGetName; | 13 JsGetName; |
14 | 14 |
15 import '../headers.dart'; | 15 import '../headers.dart'; |
16 | 16 |
17 import '../js_emitter.dart' hide Emitter; | 17 import '../js_emitter.dart' hide Emitter; |
18 import '../js_emitter.dart' as js_emitter show Emitter; | 18 import '../js_emitter.dart' as js_emitter show Emitter; |
19 | 19 |
20 import '../model.dart'; | 20 import '../model.dart'; |
21 import '../program_builder/program_builder.dart'; | 21 import '../program_builder/program_builder.dart'; |
22 | 22 |
23 import '../../common.dart'; | 23 import '../../common.dart'; |
24 | 24 |
25 import '../../constants/values.dart'; | 25 import '../../constants/values.dart'; |
26 | 26 |
27 import '../../deferred_load.dart' show OutputUnit; | 27 import '../../deferred_load.dart' show OutputUnit; |
28 | 28 |
29 import '../../diagnostics/messages.dart' show MessageKind; | 29 import '../../diagnostics/diagnostic_listener.dart' show |
| 30 DiagnosticReporter; |
| 31 |
| 32 import '../../diagnostics/messages.dart' show |
| 33 MessageKind; |
30 | 34 |
31 import '../../diagnostics/spannable.dart' show | 35 import '../../diagnostics/spannable.dart' show |
32 NO_LOCATION_SPANNABLE; | 36 NO_LOCATION_SPANNABLE; |
33 | 37 |
34 import '../../elements/elements.dart' show | 38 import '../../elements/elements.dart' show |
35 ConstructorBodyElement, | 39 ConstructorBodyElement, |
36 ElementKind, | 40 ElementKind, |
37 FieldElement, | 41 FieldElement, |
38 Name, | 42 Name, |
39 ParameterElement, | 43 ParameterElement, |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 cachedClassBuilders = compiler.cacheStrategy.newMap(), | 189 cachedClassBuilders = compiler.cacheStrategy.newMap(), |
186 cachedElements = compiler.cacheStrategy.newSet() { | 190 cachedElements = compiler.cacheStrategy.newSet() { |
187 constantEmitter = new ConstantEmitter( | 191 constantEmitter = new ConstantEmitter( |
188 compiler, namer, this.constantReference, constantListGenerator); | 192 compiler, namer, this.constantReference, constantListGenerator); |
189 containerBuilder.emitter = this; | 193 containerBuilder.emitter = this; |
190 classEmitter.emitter = this; | 194 classEmitter.emitter = this; |
191 nsmEmitter.emitter = this; | 195 nsmEmitter.emitter = this; |
192 interceptorEmitter.emitter = this; | 196 interceptorEmitter.emitter = this; |
193 } | 197 } |
194 | 198 |
| 199 DiagnosticReporter get reporter => compiler.reporter; |
| 200 |
195 List<jsAst.Node> cspPrecompiledFunctionFor(OutputUnit outputUnit) { | 201 List<jsAst.Node> cspPrecompiledFunctionFor(OutputUnit outputUnit) { |
196 return _cspPrecompiledFunctions.putIfAbsent( | 202 return _cspPrecompiledFunctions.putIfAbsent( |
197 outputUnit, | 203 outputUnit, |
198 () => new List<jsAst.Node>()); | 204 () => new List<jsAst.Node>()); |
199 } | 205 } |
200 | 206 |
201 List<jsAst.Expression> cspPrecompiledConstructorNamesFor( | 207 List<jsAst.Expression> cspPrecompiledConstructorNamesFor( |
202 OutputUnit outputUnit) { | 208 OutputUnit outputUnit) { |
203 return _cspPrecompiledConstructorNames.putIfAbsent( | 209 return _cspPrecompiledConstructorNames.putIfAbsent( |
204 outputUnit, | 210 outputUnit, |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 return jsAst.js.expressionTemplateFor("$typesAccess[#]"); | 414 return jsAst.js.expressionTemplateFor("$typesAccess[#]"); |
409 | 415 |
410 case JsBuiltin.createDartClosureFromNameOfStaticFunction: | 416 case JsBuiltin.createDartClosureFromNameOfStaticFunction: |
411 // The global-functions map contains a map from name to tear-off | 417 // The global-functions map contains a map from name to tear-off |
412 // getters. | 418 // getters. |
413 String functionGettersMap = | 419 String functionGettersMap = |
414 generateEmbeddedGlobalAccessString(embeddedNames.GLOBAL_FUNCTIONS); | 420 generateEmbeddedGlobalAccessString(embeddedNames.GLOBAL_FUNCTIONS); |
415 return jsAst.js.expressionTemplateFor("$functionGettersMap[#]()"); | 421 return jsAst.js.expressionTemplateFor("$functionGettersMap[#]()"); |
416 | 422 |
417 default: | 423 default: |
418 compiler.internalError(NO_LOCATION_SPANNABLE, | 424 reporter.internalError(NO_LOCATION_SPANNABLE, |
419 "Unhandled Builtin: $builtin"); | 425 "Unhandled Builtin: $builtin"); |
420 return null; | 426 return null; |
421 } | 427 } |
422 } | 428 } |
423 | 429 |
424 List<jsAst.Statement> buildTrivialNsmHandlers(){ | 430 List<jsAst.Statement> buildTrivialNsmHandlers(){ |
425 return nsmEmitter.buildTrivialNsmHandlers(); | 431 return nsmEmitter.buildTrivialNsmHandlers(); |
426 } | 432 } |
427 | 433 |
428 jsAst.Statement buildNativeInfoHandler( | 434 jsAst.Statement buildNativeInfoHandler( |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
547 Element element = elementOrSelector; | 553 Element element = elementOrSelector; |
548 if (element.isGenerativeConstructorBody) { | 554 if (element.isGenerativeConstructorBody) { |
549 return null; | 555 return null; |
550 } else if (element.isClass) { | 556 } else if (element.isClass) { |
551 ClassElement cls = element; | 557 ClassElement cls = element; |
552 if (cls.isUnnamedMixinApplication) return null; | 558 if (cls.isUnnamedMixinApplication) return null; |
553 return cls.name; | 559 return cls.name; |
554 } else if (element.isTypedef) { | 560 } else if (element.isTypedef) { |
555 return element.name; | 561 return element.name; |
556 } | 562 } |
557 throw compiler.internalError(element, | 563 throw reporter.internalError(element, |
558 'Do not know how to reflect on this $element.'); | 564 'Do not know how to reflect on this $element.'); |
559 } | 565 } |
560 | 566 |
561 String namedParametersAsReflectionNames(CallStructure structure) { | 567 String namedParametersAsReflectionNames(CallStructure structure) { |
562 if (structure.isUnnamed) return ''; | 568 if (structure.isUnnamed) return ''; |
563 String names = structure.getOrderedNamedArguments().join(':'); | 569 String names = structure.getOrderedNamedArguments().join(':'); |
564 return ':$names'; | 570 return ':$names'; |
565 } | 571 } |
566 | 572 |
567 jsAst.Statement buildCspPrecompiledFunctionFor( | 573 jsAst.Statement buildCspPrecompiledFunctionFor( |
(...skipping 17 matching lines...) Expand all Loading... |
585 'result': new jsAst.ArrayInitializer( | 591 'result': new jsAst.ArrayInitializer( |
586 cspPrecompiledConstructorNamesFor(outputUnit))}); | 592 cspPrecompiledConstructorNamesFor(outputUnit))}); |
587 } else { | 593 } else { |
588 return js.comment("Constructors are generated at runtime."); | 594 return js.comment("Constructors are generated at runtime."); |
589 } | 595 } |
590 } | 596 } |
591 | 597 |
592 void assembleClass(Class cls, ClassBuilder enclosingBuilder, | 598 void assembleClass(Class cls, ClassBuilder enclosingBuilder, |
593 Fragment fragment) { | 599 Fragment fragment) { |
594 ClassElement classElement = cls.element; | 600 ClassElement classElement = cls.element; |
595 compiler.withCurrentElement(classElement, () { | 601 reporter.withCurrentElement(classElement, () { |
596 if (compiler.hasIncrementalSupport) { | 602 if (compiler.hasIncrementalSupport) { |
597 ClassBuilder cachedBuilder = | 603 ClassBuilder cachedBuilder = |
598 cachedClassBuilders.putIfAbsent(classElement, () { | 604 cachedClassBuilders.putIfAbsent(classElement, () { |
599 ClassBuilder builder = | 605 ClassBuilder builder = |
600 new ClassBuilder.forClass(classElement, namer); | 606 new ClassBuilder.forClass(classElement, namer); |
601 classEmitter.emitClass(cls, builder, fragment); | 607 classEmitter.emitClass(cls, builder, fragment); |
602 return builder; | 608 return builder; |
603 }); | 609 }); |
604 invariant(classElement, cachedBuilder.fields.isEmpty); | 610 invariant(classElement, cachedBuilder.fields.isEmpty); |
605 invariant(classElement, cachedBuilder.superName == null); | 611 invariant(classElement, cachedBuilder.superName == null); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
638 | 644 |
639 bool inMainUnit = (outputUnit == compiler.deferredLoadTask.mainOutputUnit); | 645 bool inMainUnit = (outputUnit == compiler.deferredLoadTask.mainOutputUnit); |
640 JavaScriptConstantCompiler handler = backend.constants; | 646 JavaScriptConstantCompiler handler = backend.constants; |
641 List<jsAst.Statement> parts = <jsAst.Statement>[]; | 647 List<jsAst.Statement> parts = <jsAst.Statement>[]; |
642 | 648 |
643 Iterable<Element> fields = outputStaticNonFinalFieldLists[outputUnit]; | 649 Iterable<Element> fields = outputStaticNonFinalFieldLists[outputUnit]; |
644 // If the outputUnit does not contain any static non-final fields, then | 650 // If the outputUnit does not contain any static non-final fields, then |
645 // [fields] is `null`. | 651 // [fields] is `null`. |
646 if (fields != null) { | 652 if (fields != null) { |
647 for (Element element in fields) { | 653 for (Element element in fields) { |
648 compiler.withCurrentElement(element, () { | 654 reporter.withCurrentElement(element, () { |
649 ConstantValue constant = handler.getInitialValueFor(element); | 655 ConstantValue constant = handler.getInitialValueFor(element); |
650 parts.add(buildInitialization(element, constantReference(constant))); | 656 parts.add(buildInitialization(element, constantReference(constant))); |
651 }); | 657 }); |
652 } | 658 } |
653 } | 659 } |
654 | 660 |
655 if (inMainUnit && outputStaticNonFinalFieldLists.length > 1) { | 661 if (inMainUnit && outputStaticNonFinalFieldLists.length > 1) { |
656 // In the main output-unit we output a stub initializer for deferred | 662 // In the main output-unit we output a stub initializer for deferred |
657 // variables, so that `isolateProperties` stays a fast object. | 663 // variables, so that `isolateProperties` stays a fast object. |
658 outputStaticNonFinalFieldLists.forEach( | 664 outputStaticNonFinalFieldLists.forEach( |
659 (OutputUnit fieldsOutputUnit, Iterable<VariableElement> fields) { | 665 (OutputUnit fieldsOutputUnit, Iterable<VariableElement> fields) { |
660 if (fieldsOutputUnit == outputUnit) return; // Skip the main unit. | 666 if (fieldsOutputUnit == outputUnit) return; // Skip the main unit. |
661 for (Element element in fields) { | 667 for (Element element in fields) { |
662 compiler.withCurrentElement(element, () { | 668 reporter.withCurrentElement(element, () { |
663 parts.add(buildInitialization(element, jsAst.number(0))); | 669 parts.add(buildInitialization(element, jsAst.number(0))); |
664 }); | 670 }); |
665 } | 671 } |
666 }); | 672 }); |
667 } | 673 } |
668 | 674 |
669 return new jsAst.Block(parts); | 675 return new jsAst.Block(parts); |
670 } | 676 } |
671 | 677 |
672 jsAst.Statement buildLazilyInitializedStaticFields() { | 678 jsAst.Statement buildLazilyInitializedStaticFields() { |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
893 return js.statement(''' | 899 return js.statement(''' |
894 function init() { | 900 function init() { |
895 $isolatePropertiesName = Object.create(null); | 901 $isolatePropertiesName = Object.create(null); |
896 #allClasses = map(); | 902 #allClasses = map(); |
897 #getTypeFromName = function(name) {return #allClasses[name];}; | 903 #getTypeFromName = function(name) {return #allClasses[name];}; |
898 #interceptorsByTag = map(); | 904 #interceptorsByTag = map(); |
899 #leafTags = map(); | 905 #leafTags = map(); |
900 #finishedClasses = map(); | 906 #finishedClasses = map(); |
901 | 907 |
902 if (#needsLazyInitializer) { | 908 if (#needsLazyInitializer) { |
903 // [staticName] is only provided in non-minified mode. If missing, we | 909 // [staticName] is only provided in non-minified mode. If missing, we |
904 // fall back to [fieldName]. Likewise, [prototype] is optional and | 910 // fall back to [fieldName]. Likewise, [prototype] is optional and |
905 // defaults to the isolateProperties object. | 911 // defaults to the isolateProperties object. |
906 $lazyInitializerName = function (fieldName, getterName, lazyValue, | 912 $lazyInitializerName = function (fieldName, getterName, lazyValue, |
907 staticName, prototype) { | 913 staticName, prototype) { |
908 if (!#lazies) #lazies = Object.create(null); | 914 if (!#lazies) #lazies = Object.create(null); |
909 #lazies[fieldName] = getterName; | 915 #lazies[fieldName] = getterName; |
910 | 916 |
911 // 'prototype' will be undefined except if we are doing an update | 917 // 'prototype' will be undefined except if we are doing an update |
912 // during incremental compilation. In this case we put the lazy | 918 // during incremental compilation. In this case we put the lazy |
913 // field directly on the isolate instead of the isolateProperties. | 919 // field directly on the isolate instead of the isolateProperties. |
914 prototype = prototype || $isolatePropertiesName; | 920 prototype = prototype || $isolatePropertiesName; |
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1325 return new jsAst.Block(parts); | 1331 return new jsAst.Block(parts); |
1326 } | 1332 } |
1327 | 1333 |
1328 void checkEverythingEmitted(Iterable<Element> elements) { | 1334 void checkEverythingEmitted(Iterable<Element> elements) { |
1329 List<Element> pendingStatics; | 1335 List<Element> pendingStatics; |
1330 if (!compiler.hasIncrementalSupport) { | 1336 if (!compiler.hasIncrementalSupport) { |
1331 pendingStatics = | 1337 pendingStatics = |
1332 Elements.sortedByPosition(elements.where((e) => !e.isLibrary)); | 1338 Elements.sortedByPosition(elements.where((e) => !e.isLibrary)); |
1333 | 1339 |
1334 pendingStatics.forEach((element) => | 1340 pendingStatics.forEach((element) => |
1335 compiler.reportInfo( | 1341 reporter.reportInfo( |
1336 element, MessageKind.GENERIC, {'text': 'Pending statics.'})); | 1342 element, MessageKind.GENERIC, {'text': 'Pending statics.'})); |
1337 } | 1343 } |
1338 | 1344 |
1339 if (pendingStatics != null && !pendingStatics.isEmpty) { | 1345 if (pendingStatics != null && !pendingStatics.isEmpty) { |
1340 compiler.internalError(pendingStatics.first, | 1346 reporter.internalError(pendingStatics.first, |
1341 'Pending statics (see above).'); | 1347 'Pending statics (see above).'); |
1342 } | 1348 } |
1343 } | 1349 } |
1344 | 1350 |
1345 void assembleLibrary(Library library, Fragment fragment) { | 1351 void assembleLibrary(Library library, Fragment fragment) { |
1346 LibraryElement libraryElement = library.element; | 1352 LibraryElement libraryElement = library.element; |
1347 | 1353 |
1348 assembleStaticFunctions(library.statics, fragment); | 1354 assembleStaticFunctions(library.statics, fragment); |
1349 | 1355 |
1350 ClassBuilder libraryBuilder = | 1356 ClassBuilder libraryBuilder = |
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1805 Map<OutputUnit, String> deferredLoadHashes = | 1811 Map<OutputUnit, String> deferredLoadHashes = |
1806 emitDeferredOutputUnits(deferredParts); | 1812 emitDeferredOutputUnits(deferredParts); |
1807 | 1813 |
1808 deferredHashTokens.forEach((OutputUnit key, _DeferredOutputUnitHash token) { | 1814 deferredHashTokens.forEach((OutputUnit key, _DeferredOutputUnitHash token) { |
1809 token.setHash(deferredLoadHashes[key]); | 1815 token.setHash(deferredLoadHashes[key]); |
1810 }); | 1816 }); |
1811 emitMainOutputUnit(program.mainFragment.outputUnit, mainOutput); | 1817 emitMainOutputUnit(program.mainFragment.outputUnit, mainOutput); |
1812 | 1818 |
1813 if (backend.requiresPreamble && | 1819 if (backend.requiresPreamble && |
1814 !backend.htmlLibraryIsLoaded) { | 1820 !backend.htmlLibraryIsLoaded) { |
1815 compiler.reportHintMessage( | 1821 reporter.reportHintMessage( |
1816 NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE); | 1822 NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE); |
1817 } | 1823 } |
1818 // Return the total program size. | 1824 // Return the total program size. |
1819 return outputBuffers.values.fold(0, (a, b) => a + b.length); | 1825 return outputBuffers.values.fold(0, (a, b) => a + b.length); |
1820 } | 1826 } |
1821 | 1827 |
1822 String generateSourceMapTag(Uri sourceMapUri, Uri fileUri) { | 1828 String generateSourceMapTag(Uri sourceMapUri, Uri fileUri) { |
1823 if (sourceMapUri != null && fileUri != null) { | 1829 if (sourceMapUri != null && fileUri != null) { |
1824 String sourceMapFileName = relativize(fileUri, sourceMapUri, false); | 1830 String sourceMapFileName = relativize(fileUri, sourceMapUri, false); |
1825 return ''' | 1831 return ''' |
(...skipping 13 matching lines...) Expand all Loading... |
1839 ClassElement cls = | 1845 ClassElement cls = |
1840 element.enclosingClassOrCompilationUnit.declaration; | 1846 element.enclosingClassOrCompilationUnit.declaration; |
1841 if (compiler.codegenWorld.directlyInstantiatedClasses.contains(cls) && | 1847 if (compiler.codegenWorld.directlyInstantiatedClasses.contains(cls) && |
1842 !cls.isNative && | 1848 !cls.isNative && |
1843 compiler.deferredLoadTask.outputUnitForElement(element) == | 1849 compiler.deferredLoadTask.outputUnitForElement(element) == |
1844 compiler.deferredLoadTask.outputUnitForElement(cls)) { | 1850 compiler.deferredLoadTask.outputUnitForElement(cls)) { |
1845 owner = cls; | 1851 owner = cls; |
1846 } | 1852 } |
1847 } | 1853 } |
1848 if (owner == null) { | 1854 if (owner == null) { |
1849 compiler.internalError(element, 'Owner is null.'); | 1855 reporter.internalError(element, 'Owner is null.'); |
1850 } | 1856 } |
1851 return elementDescriptors | 1857 return elementDescriptors |
1852 .putIfAbsent(fragment, () => new Map<Element, ClassBuilder>()) | 1858 .putIfAbsent(fragment, () => new Map<Element, ClassBuilder>()) |
1853 .putIfAbsent(owner, () { | 1859 .putIfAbsent(owner, () { |
1854 return new ClassBuilder(owner, namer, owner.isClass); | 1860 return new ClassBuilder(owner, namer, owner.isClass); |
1855 }); | 1861 }); |
1856 } | 1862 } |
1857 | 1863 |
1858 /// Emits support-code for deferred loading into [output]. | 1864 /// Emits support-code for deferred loading into [output]. |
1859 jsAst.Statement buildDeferredBoilerPlate( | 1865 jsAst.Statement buildDeferredBoilerPlate( |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2119 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 2125 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
2120 if (element.isInstanceMember) { | 2126 if (element.isInstanceMember) { |
2121 cachedClassBuilders.remove(element.enclosingClass); | 2127 cachedClassBuilders.remove(element.enclosingClass); |
2122 | 2128 |
2123 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 2129 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
2124 | 2130 |
2125 } | 2131 } |
2126 } | 2132 } |
2127 } | 2133 } |
2128 } | 2134 } |
OLD | NEW |