Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(366)

Side by Side Diff: dart/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart

Issue 19405002: Implement reflecting on static fields. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 part of js_backend; 5 part of js_backend;
6 6
7 /** 7 /**
8 * A function element that represents a closure call. The signature is copied 8 * A function element that represents a closure call. The signature is copied
9 * from the given element. 9 * from the given element.
10 */ 10 */
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 /** Shorter access to [isolatePropertiesName]. Both here in the code, as 75 /** Shorter access to [isolatePropertiesName]. Both here in the code, as
76 well as in the generated code. */ 76 well as in the generated code. */
77 String isolateProperties; 77 String isolateProperties;
78 String classesCollector; 78 String classesCollector;
79 final Set<ClassElement> neededClasses = new Set<ClassElement>(); 79 final Set<ClassElement> neededClasses = new Set<ClassElement>();
80 final List<ClassElement> regularClasses = <ClassElement>[]; 80 final List<ClassElement> regularClasses = <ClassElement>[];
81 final List<ClassElement> deferredClasses = <ClassElement>[]; 81 final List<ClassElement> deferredClasses = <ClassElement>[];
82 final List<ClassElement> nativeClasses = <ClassElement>[]; 82 final List<ClassElement> nativeClasses = <ClassElement>[];
83 final List<Selector> trivialNsmHandlers = <Selector>[]; 83 final List<Selector> trivialNsmHandlers = <Selector>[];
84 final Map<String, String> mangledFieldNames = <String, String>{}; 84 final Map<String, String> mangledFieldNames = <String, String>{};
85 final Map<String, String> mangledGlobalFieldNames = <String, String>{};
85 final Set<String> recordedMangledNames = new Set<String>(); 86 final Set<String> recordedMangledNames = new Set<String>();
86 final Set<String> interceptorInvocationNames = new Set<String>(); 87 final Set<String> interceptorInvocationNames = new Set<String>();
87 88
88 /// A list of JS expressions that represent metadata, parameter names and 89 /// A list of JS expressions that represent metadata, parameter names and
89 /// type, and return types. 90 /// type, and return types.
90 final List<String> globalMetadata = []; 91 final List<String> globalMetadata = [];
91 92
92 /// A map used to canonicalize the entries of globalMetadata. 93 /// A map used to canonicalize the entries of globalMetadata.
93 final Map<String, int> globalMetadataMap = <String, int>{}; 94 final Map<String, int> globalMetadataMap = <String, int>{};
94 95
(...skipping 1355 matching lines...) Expand 10 before | Expand all | Expand 10 after
1450 functionTypes.forEach(addSignature); 1451 functionTypes.forEach(addSignature);
1451 }); 1452 });
1452 } 1453 }
1453 1454
1454 /** 1455 /**
1455 * Documentation wanted -- johnniwinther 1456 * Documentation wanted -- johnniwinther
1456 * 1457 *
1457 * Invariant: [classElement] must be a declaration element. 1458 * Invariant: [classElement] must be a declaration element.
1458 */ 1459 */
1459 void visitClassFields(ClassElement classElement, 1460 void visitClassFields(ClassElement classElement,
1461 bool visitStatics,
1460 void addField(Element member, 1462 void addField(Element member,
1461 String name, 1463 String name,
1462 String accessorName, 1464 String accessorName,
1463 bool needsGetter, 1465 bool needsGetter,
1464 bool needsSetter, 1466 bool needsSetter,
1465 bool needsCheckedSetter)) { 1467 bool needsCheckedSetter)) {
1466 assert(invariant(classElement, classElement.isDeclaration)); 1468 assert(invariant(classElement, classElement.isDeclaration));
1467 // If the class is never instantiated we still need to set it up for 1469 // If the class is never instantiated we still need to set it up for
1468 // inheritance purposes, but we can simplify its JavaScript constructor. 1470 // inheritance purposes, but we can simplify its JavaScript constructor.
1469 bool isInstantiated = 1471 bool isInstantiated =
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1516 // Getters and setters with suffixes will be generated dynamically. 1518 // Getters and setters with suffixes will be generated dynamically.
1517 addField(member, 1519 addField(member,
1518 fieldName, 1520 fieldName,
1519 accessorName, 1521 accessorName,
1520 needsGetter, 1522 needsGetter,
1521 needsSetter, 1523 needsSetter,
1522 needsCheckedSetter); 1524 needsCheckedSetter);
1523 } 1525 }
1524 } 1526 }
1525 1527
1526 // TODO(kasperl): We should make sure to only emit one version of 1528 if (visitStatics) {
1527 // overridden fields. Right now, we rely on the ordering so the 1529 classElement.implementation.forEachStaticField(visitField);
1528 // fields pulled in from mixins are replaced with the fields from 1530 } else {
1529 // the class definition. 1531 // TODO(kasperl): We should make sure to only emit one version of
1532 // overridden fields. Right now, we rely on the ordering so the
1533 // fields pulled in from mixins are replaced with the fields from
1534 // the class definition.
1530 1535
1531 // If a class is not instantiated then we add the field just so we can 1536 // If a class is not instantiated then we add the field just so we can
1532 // generate the field getter/setter dynamically. Since this is only 1537 // generate the field getter/setter dynamically. Since this is only
1533 // allowed on fields that are in [classElement] we don't need to visit 1538 // allowed on fields that are in [classElement] we don't need to visit
1534 // superclasses for non-instantiated classes. 1539 // superclasses for non-instantiated classes.
1535 classElement.implementation.forEachInstanceField( 1540 classElement.implementation.forEachInstanceField(
1536 visitField, 1541 visitField,
1537 includeSuperAndInjectedMembers: isInstantiated); 1542 includeSuperAndInjectedMembers: isInstantiated);
1543 }
1538 } 1544 }
1539 1545
1540 void generateGetter(Element member, String fieldName, String accessorName, 1546 void generateGetter(Element member, String fieldName, String accessorName,
1541 ClassBuilder builder) { 1547 ClassBuilder builder) {
1542 String getterName = namer.getterNameFromAccessorName(accessorName); 1548 String getterName = namer.getterNameFromAccessorName(accessorName);
1543 String receiver = backend.isInterceptorClass(member.getEnclosingClass()) 1549 String receiver = backend.isInterceptorClass(member.getEnclosingClass())
1544 ? 'receiver' : 'this'; 1550 ? 'receiver' : 'this';
1545 List<String> args = backend.isInterceptedMethod(member) 1551 List<String> args = backend.isInterceptedMethod(member)
1546 ? ['receiver'] 1552 ? ['receiver']
1547 : []; 1553 : [];
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1613 } 1619 }
1614 1620
1615 void emitRuntimeName(String runtimeName, ClassBuilder builder) { 1621 void emitRuntimeName(String runtimeName, ClassBuilder builder) {
1616 /* Do nothing. */ 1622 /* Do nothing. */
1617 } 1623 }
1618 1624
1619 void recordMangledField(Element member, 1625 void recordMangledField(Element member,
1620 String accessorName, 1626 String accessorName,
1621 String memberName) { 1627 String memberName) {
1622 if (!backend.retainGetter(member)) return; 1628 if (!backend.retainGetter(member)) return;
1623 String previousName = mangledFieldNames.putIfAbsent( 1629 String previousName;
1624 '${namer.getterPrefix}$accessorName', 1630 if (member.isInstanceMember()) {
1625 () => memberName); 1631 previousName = mangledFieldNames.putIfAbsent(
1632 '${namer.getterPrefix}$accessorName',
1633 () => memberName);
1634 } else {
1635 previousName = mangledGlobalFieldNames.putIfAbsent(
1636 accessorName,
1637 () => memberName);
1638 }
1626 assert(invariant(member, previousName == memberName, 1639 assert(invariant(member, previousName == memberName,
1627 message: '$previousName != ${memberName}')); 1640 message: '$previousName != ${memberName}'));
1628 } 1641 }
1629 1642
1630 /// Returns `true` if fields added. 1643 /// Returns `true` if fields added.
1631 bool emitClassFields(ClassElement classElement, 1644 bool emitClassFields(ClassElement classElement,
1632 ClassBuilder builder, 1645 ClassBuilder builder,
1633 String superName, 1646 String superName,
1634 { bool classIsNative: false }) { 1647 { bool classIsNative: false,
1648 bool emitStatics: false }) {
1635 assert(superName != null); 1649 assert(superName != null);
1636 String separator = ''; 1650 String separator = '';
1637 String nativeName = namer.getPrimitiveInterceptorRuntimeName(classElement); 1651 String nativeName = namer.getPrimitiveInterceptorRuntimeName(classElement);
1638 StringBuffer buffer = new StringBuffer(); 1652 StringBuffer buffer = new StringBuffer();
1639 if (nativeName != null) { 1653 if (!emitStatics) {
1640 buffer.write('$nativeName/'); 1654 if (nativeName != null) {
1655 buffer.write('$nativeName/');
1656 }
1657 buffer.write('$superName;');
1641 } 1658 }
1642 buffer.write('$superName;');
1643 int bufferClassLength = buffer.length; 1659 int bufferClassLength = buffer.length;
1644 1660
1645 var fieldMetadata = []; 1661 var fieldMetadata = [];
1646 bool hasMetadata = false; 1662 bool hasMetadata = false;
1647 1663
1648 visitClassFields(classElement, (Element member, 1664 visitClassFields(classElement, emitStatics,
1649 String name, 1665 (Element member,
1650 String accessorName, 1666 String name,
1651 bool needsGetter, 1667 String accessorName,
1652 bool needsSetter, 1668 bool needsGetter,
1653 bool needsCheckedSetter) { 1669 bool needsSetter,
1670 bool needsCheckedSetter) {
1654 // Ignore needsCheckedSetter - that is handled below. 1671 // Ignore needsCheckedSetter - that is handled below.
1655 bool needsAccessor = (needsGetter || needsSetter); 1672 bool needsAccessor = (needsGetter || needsSetter);
1656 // We need to output the fields for non-native classes so we can auto- 1673 // We need to output the fields for non-native classes so we can auto-
1657 // generate the constructor. For native classes there are no 1674 // generate the constructor. For native classes there are no
1658 // constructors, so we don't need the fields unless we are generating 1675 // constructors, so we don't need the fields unless we are generating
1659 // accessors at runtime. 1676 // accessors at runtime.
1660 if (!classIsNative || needsAccessor) { 1677 if (!classIsNative || needsAccessor) {
1661 buffer.write(separator); 1678 buffer.write(separator);
1662 separator = ','; 1679 separator = ',';
1663 var metadata = buildMetadataFunction(member); 1680 var metadata = buildMetadataFunction(member);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1721 fieldMetadata.insert(0, classDataNode); 1738 fieldMetadata.insert(0, classDataNode);
1722 classDataNode = new jsAst.ArrayInitializer.from(fieldMetadata); 1739 classDataNode = new jsAst.ArrayInitializer.from(fieldMetadata);
1723 } 1740 }
1724 builder.addProperty('', classDataNode); 1741 builder.addProperty('', classDataNode);
1725 return fieldsAdded; 1742 return fieldsAdded;
1726 } 1743 }
1727 1744
1728 void emitClassGettersSetters(ClassElement classElement, 1745 void emitClassGettersSetters(ClassElement classElement,
1729 ClassBuilder builder) { 1746 ClassBuilder builder) {
1730 1747
1731 visitClassFields(classElement, (Element member, 1748 visitClassFields(classElement, false,
1732 String name, 1749 (Element member,
1733 String accessorName, 1750 String name,
1734 bool needsGetter, 1751 String accessorName,
1735 bool needsSetter, 1752 bool needsGetter,
1736 bool needsCheckedSetter) { 1753 bool needsSetter,
1754 bool needsCheckedSetter) {
1737 compiler.withCurrentElement(member, () { 1755 compiler.withCurrentElement(member, () {
1738 if (needsCheckedSetter) { 1756 if (needsCheckedSetter) {
1739 assert(!needsSetter); 1757 assert(!needsSetter);
1740 generateCheckedSetter(member, name, accessorName, builder); 1758 generateCheckedSetter(member, name, accessorName, builder);
1741 } 1759 }
1742 if (!getterAndSetterCanBeImplementedByFieldSpec) { 1760 if (!getterAndSetterCanBeImplementedByFieldSpec) {
1743 if (needsGetter) { 1761 if (needsGetter) {
1744 generateGetter(member, name, accessorName, builder); 1762 generateGetter(member, name, accessorName, builder);
1745 } 1763 }
1746 if (needsSetter) { 1764 if (needsSetter) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1786 if (metadata != null) { 1804 if (metadata != null) {
1787 builder.addProperty("@", metadata); 1805 builder.addProperty("@", metadata);
1788 } 1806 }
1789 emitClassGettersSetters(classElement, builder); 1807 emitClassGettersSetters(classElement, builder);
1790 if (!classElement.isMixinApplication) { 1808 if (!classElement.isMixinApplication) {
1791 emitInstanceMembers(classElement, builder); 1809 emitInstanceMembers(classElement, builder);
1792 } 1810 }
1793 emitIsTests(classElement, builder); 1811 emitIsTests(classElement, builder);
1794 1812
1795 List<CodeBuffer> classBuffers = elementBuffers[classElement]; 1813 List<CodeBuffer> classBuffers = elementBuffers[classElement];
1814 if (classBuffers == null) {
1815 classBuffers = [];
1816 } else {
1817 elementBuffers.remove(classElement);
1818 }
1796 CodeBuffer statics = new CodeBuffer(); 1819 CodeBuffer statics = new CodeBuffer();
1820 statics.write('{$n');
1797 bool hasStatics = false; 1821 bool hasStatics = false;
1798 if (classBuffers != null) { 1822 ClassBuilder staticsBuilder = new ClassBuilder();
1799 statics.write('{$n'); 1823 if (emitClassFields(
1800 elementBuffers.remove(classElement); 1824 classElement, staticsBuilder, superName, emitStatics: true)) {
1801 for (CodeBuffer classBuffer in classBuffers) { 1825 hasStatics = true;
1802 // TODO(ahe): What about deferred? 1826 statics.write('"":$_');
1803 if (classBuffer != null) { 1827 statics.write(
1804 hasStatics = true; 1828 jsAst.prettyPrint(staticsBuilder.properties.single.value, compiler));
1805 statics.addBuffer(classBuffer); 1829 statics.write(',$n');
1806 } 1830 }
1831 for (CodeBuffer classBuffer in classBuffers) {
1832 // TODO(ahe): What about deferred?
1833 if (classBuffer != null) {
1834 hasStatics = true;
1835 statics.addBuffer(classBuffer);
1807 } 1836 }
1808 statics.write('}$n');
1809 } 1837 }
1838 statics.write('}$n');
1810 if (hasStatics) { 1839 if (hasStatics) {
1811 builder.addProperty('static', new jsAst.Blob(statics)); 1840 builder.addProperty('static', new jsAst.Blob(statics));
1812 } 1841 }
1813 1842
1814 // TODO(ahe): This method (generateClass) should return a jsAst.Expression. 1843 // TODO(ahe): This method (generateClass) should return a jsAst.Expression.
1815 if (!buffer.isEmpty) { 1844 if (!buffer.isEmpty) {
1816 buffer.write(',$n$n'); 1845 buffer.write(',$n$n');
1817 } 1846 }
1818 buffer.write('$className:$_'); 1847 buffer.write('$className:$_');
1819 buffer.write(jsAst.prettyPrint(builder.toObjectInitializer(), compiler)); 1848 buffer.write(jsAst.prettyPrint(builder.toObjectInitializer(), compiler));
(...skipping 1667 matching lines...) Expand 10 before | Expand all | Expand 10 after
3487 properties.add(new jsAst.Property(js.string(key), value)); 3516 properties.add(new jsAst.Property(js.string(key), value));
3488 } 3517 }
3489 var map = new jsAst.ObjectInitializer(properties); 3518 var map = new jsAst.ObjectInitializer(properties);
3490 mainBuffer.write( 3519 mainBuffer.write(
3491 jsAst.prettyPrint( 3520 jsAst.prettyPrint(
3492 js('init.mangledNames = #', map).toStatement(), compiler)); 3521 js('init.mangledNames = #', map).toStatement(), compiler));
3493 if (compiler.enableMinification) { 3522 if (compiler.enableMinification) {
3494 mainBuffer.write(';'); 3523 mainBuffer.write(';');
3495 } 3524 }
3496 } 3525 }
3526 if (!mangledGlobalFieldNames.isEmpty) {
3527 var keys = mangledGlobalFieldNames.keys.toList();
3528 keys.sort();
3529 var properties = [];
3530 for (String key in keys) {
3531 var value = js.string('${mangledGlobalFieldNames[key]}');
3532 properties.add(new jsAst.Property(js.string(key), value));
3533 }
3534 var map = new jsAst.ObjectInitializer(properties);
3535 mainBuffer.write(
3536 jsAst.prettyPrint(
3537 js('init.mangledGlobalNames = #', map).toStatement(), compiler ));
ngeoffray 2013/07/17 07:41:11 long line
ahe 2013/07/17 08:39:15 Done.
3538 if (compiler.enableMinification) {
3539 mainBuffer.write(';');
3540 }
3541 }
3497 mainBuffer 3542 mainBuffer
3498 ..write(getReflectionDataParser()) 3543 ..write(getReflectionDataParser())
3499 ..write('([$n'); 3544 ..write('([$n');
3500 3545
3501 var sortedElements = Elements.sortedByPosition(elementBuffers.keys); 3546 var sortedElements = Elements.sortedByPosition(elementBuffers.keys);
3502 bool hasPendingStatics = false; 3547 bool hasPendingStatics = false;
3503 for (Element element in sortedElements) { 3548 for (Element element in sortedElements) {
3504 if (!element.isLibrary()) { 3549 if (!element.isLibrary()) {
3505 for (var b in elementBuffers[element]) { 3550 for (var b in elementBuffers[element]) {
3506 if (b != null) { 3551 if (b != null) {
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
3754 var data = reflectionData[i]; 3799 var data = reflectionData[i];
3755 var name = data[0]; 3800 var name = data[0];
3756 var uri = data[1]; 3801 var uri = data[1];
3757 var metadata = data[2]; 3802 var metadata = data[2];
3758 var descriptor = data[3]; 3803 var descriptor = data[3];
3759 var classes = []; 3804 var classes = [];
3760 var functions = []; 3805 var functions = [];
3761 function processStatics(descriptor) { 3806 function processStatics(descriptor) {
3762 for (var property in descriptor) { 3807 for (var property in descriptor) {
3763 if (!hasOwnProperty.call(descriptor, property)) continue; 3808 if (!hasOwnProperty.call(descriptor, property)) continue;
3809 if (property === "") continue;
3764 var element = descriptor[property]; 3810 var element = descriptor[property];
3765 var firstChar = property.substring(0, 1); 3811 var firstChar = property.substring(0, 1);
3766 var previousProperty; 3812 var previousProperty;
3767 if (firstChar === "+") { 3813 if (firstChar === "+") {
3768 mangledGlobalNames[previousProperty] = property.substring(1); 3814 mangledGlobalNames[previousProperty] = property.substring(1);
3769 } else if (firstChar === "@") { 3815 } else if (firstChar === "@") {
3770 property = property.substring(1); 3816 property = property.substring(1);
3771 ${namer.CURRENT_ISOLATE}[property][$metadataField] = element; 3817 ${namer.CURRENT_ISOLATE}[property][$metadataField] = element;
3772 } else if (typeof element === "function") { 3818 } else if (typeof element === "function") {
3773 ${namer.CURRENT_ISOLATE}[previousProperty = property] = element; 3819 ${namer.CURRENT_ISOLATE}[previousProperty = property] = element;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3807 3853
3808 const String HOOKS_API_USAGE = """ 3854 const String HOOKS_API_USAGE = """
3809 // The code supports the following hooks: 3855 // The code supports the following hooks:
3810 // dartPrint(message) - if this function is defined it is called 3856 // dartPrint(message) - if this function is defined it is called
3811 // instead of the Dart [print] method. 3857 // instead of the Dart [print] method.
3812 // dartMainRunner(main) - if this function is defined, the Dart [main] 3858 // dartMainRunner(main) - if this function is defined, the Dart [main]
3813 // method will not be invoked directly. 3859 // method will not be invoked directly.
3814 // Instead, a closure that will invoke [main] is 3860 // Instead, a closure that will invoke [main] is
3815 // passed to [dartMainRunner]. 3861 // passed to [dartMainRunner].
3816 """; 3862 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698