Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 js_backend.namer; | 5 library js_backend.namer; |
| 6 | 6 |
| 7 import 'dart:collection' show HashMap; | 7 import 'dart:collection' show HashMap; |
| 8 | 8 |
| 9 import 'package:js_runtime/shared/embedded_names.dart' show JsGetName; | 9 import 'package:js_runtime/shared/embedded_names.dart' show JsGetName; |
| 10 | 10 |
| 11 import '../closure.dart'; | 11 import '../closure.dart'; |
| 12 import '../common.dart'; | 12 import '../common.dart'; |
| 13 import '../common/names.dart' show Identifiers, Selectors; | 13 import '../common/names.dart' show Identifiers, Selectors; |
| 14 import '../compiler.dart' show Compiler; | 14 import '../compiler.dart' show Compiler; |
| 15 import '../constants/values.dart'; | 15 import '../constants/values.dart'; |
| 16 import '../core_types.dart' show CommonElements; | 16 import '../core_types.dart' show CommonElements; |
| 17 import '../elements/resolution_types.dart'; | 17 import '../elements/resolution_types.dart'; |
| 18 import '../diagnostics/invariant.dart' show DEBUG_MODE; | 18 import '../diagnostics/invariant.dart' show DEBUG_MODE; |
| 19 import '../elements/elements.dart'; | 19 import '../elements/elements.dart'; |
| 20 import '../elements/entities.dart'; | 20 import '../elements/entities.dart'; |
| 21 import '../js/js.dart' as jsAst; | 21 import '../js/js.dart' as jsAst; |
| 22 import '../js/js.dart' show js; | 22 import '../js/js.dart' show js; |
| 23 import '../tree/tree.dart'; | 23 import '../tree/tree.dart'; |
| 24 import '../universe/call_structure.dart' show CallStructure; | 24 import '../universe/call_structure.dart' show CallStructure; |
| 25 import '../universe/selector.dart' show Selector, SelectorKind; | 25 import '../universe/selector.dart' show Selector, SelectorKind; |
| 26 import '../universe/world_builder.dart' show CodegenWorldBuilder; | |
| 26 import '../util/characters.dart'; | 27 import '../util/characters.dart'; |
| 27 import '../util/util.dart'; | 28 import '../util/util.dart'; |
| 28 import '../world.dart' show ClosedWorld; | 29 import '../world.dart' show ClosedWorld; |
| 29 import 'backend.dart'; | 30 import 'backend.dart'; |
| 30 import 'backend_helpers.dart'; | 31 import 'backend_helpers.dart'; |
| 31 import 'constant_system_javascript.dart'; | 32 import 'constant_system_javascript.dart'; |
| 32 | 33 |
| 33 part 'field_naming_mixin.dart'; | 34 part 'field_naming_mixin.dart'; |
| 34 part 'frequency_namer.dart'; | 35 part 'frequency_namer.dart'; |
| 35 part 'minify_namer.dart'; | 36 part 'minify_namer.dart'; |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 397 jsAst.Name get rtiFieldName => _rtiFieldName ??= new StringBackedName(r'$ti'); | 398 jsAst.Name get rtiFieldName => _rtiFieldName ??= new StringBackedName(r'$ti'); |
| 398 | 399 |
| 399 // Name of property in a class description for the native dispatch metadata. | 400 // Name of property in a class description for the native dispatch metadata. |
| 400 final String nativeSpecProperty = '%'; | 401 final String nativeSpecProperty = '%'; |
| 401 | 402 |
| 402 static final RegExp IDENTIFIER = new RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$'); | 403 static final RegExp IDENTIFIER = new RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$'); |
| 403 static final RegExp NON_IDENTIFIER_CHAR = new RegExp(r'[^A-Za-z_0-9$]'); | 404 static final RegExp NON_IDENTIFIER_CHAR = new RegExp(r'[^A-Za-z_0-9$]'); |
| 404 | 405 |
| 405 final JavaScriptBackend backend; | 406 final JavaScriptBackend backend; |
| 406 final ClosedWorld closedWorld; | 407 final ClosedWorld closedWorld; |
| 408 final CodegenWorldBuilder codegenWorldBuilder; | |
| 407 | 409 |
| 408 /// Used disambiguated names in the global namespace, issued by | 410 /// Used disambiguated names in the global namespace, issued by |
| 409 /// [_disambiguateGlobal], and [_disambiguateInternalGlobal]. | 411 /// [_disambiguateGlobal], and [_disambiguateInternalGlobal]. |
| 410 /// | 412 /// |
| 411 /// Although global names are distributed across a number of global objects, | 413 /// Although global names are distributed across a number of global objects, |
| 412 /// (see [globalObjectFor]), we currently use a single namespace for all these | 414 /// (see [globalObjectFor]), we currently use a single namespace for all these |
| 413 /// names. | 415 /// names. |
| 414 final NamingScope globalScope = new NamingScope(); | 416 final NamingScope globalScope = new NamingScope(); |
| 415 final Map<Element, jsAst.Name> userGlobals = | 417 final Map<Element, jsAst.Name> userGlobals = |
| 416 new HashMap<Element, jsAst.Name>(); | 418 new HashMap<Element, jsAst.Name>(); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 453 | 455 |
| 454 final Map<String, String> suggestedGlobalNames = <String, String>{}; | 456 final Map<String, String> suggestedGlobalNames = <String, String>{}; |
| 455 final Map<String, String> suggestedInstanceNames = <String, String>{}; | 457 final Map<String, String> suggestedInstanceNames = <String, String>{}; |
| 456 | 458 |
| 457 /// Used to store unique keys for library names. Keys are not used as names, | 459 /// Used to store unique keys for library names. Keys are not used as names, |
| 458 /// nor are they visible in the output. The only serve as an internal | 460 /// nor are they visible in the output. The only serve as an internal |
| 459 /// key into maps. | 461 /// key into maps. |
| 460 final Map<LibraryElement, String> _libraryKeys = | 462 final Map<LibraryElement, String> _libraryKeys = |
| 461 new HashMap<LibraryElement, String>(); | 463 new HashMap<LibraryElement, String>(); |
| 462 | 464 |
| 463 Namer(JavaScriptBackend backend, this.closedWorld) | 465 Namer(JavaScriptBackend backend, this.closedWorld, |
| 466 CodegenWorldBuilder codegenWorldBuilder) | |
| 464 : this.backend = backend, | 467 : this.backend = backend, |
| 465 constantHasher = | 468 this.codegenWorldBuilder = codegenWorldBuilder, |
| 466 new ConstantCanonicalHasher(backend.rtiEncoder, backend.reporter), | 469 constantHasher = new ConstantCanonicalHasher( |
| 470 backend.rtiEncoder, backend.reporter, codegenWorldBuilder), | |
| 467 functionTypeNamer = new FunctionTypeNamer(backend.rtiEncoder) { | 471 functionTypeNamer = new FunctionTypeNamer(backend.rtiEncoder) { |
| 468 _literalAsyncPrefix = new StringBackedName(asyncPrefix); | 472 _literalAsyncPrefix = new StringBackedName(asyncPrefix); |
| 469 _literalGetterPrefix = new StringBackedName(getterPrefix); | 473 _literalGetterPrefix = new StringBackedName(getterPrefix); |
| 470 _literalSetterPrefix = new StringBackedName(setterPrefix); | 474 _literalSetterPrefix = new StringBackedName(setterPrefix); |
| 471 _literalLazyGetterPrefix = new StringBackedName(lazyGetterPrefix); | 475 _literalLazyGetterPrefix = new StringBackedName(lazyGetterPrefix); |
| 472 } | 476 } |
| 473 | 477 |
| 474 BackendHelpers get helpers => backend.helpers; | 478 BackendHelpers get helpers => backend.helpers; |
| 475 | 479 |
| 476 DiagnosticReporter get reporter => backend.reporter; | 480 DiagnosticReporter get reporter => backend.reporter; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 585 constantNames[constant] = result; | 589 constantNames[constant] = result; |
| 586 } | 590 } |
| 587 return _newReference(result); | 591 return _newReference(result); |
| 588 } | 592 } |
| 589 | 593 |
| 590 /// Proposed name for [constant]. | 594 /// Proposed name for [constant]. |
| 591 String constantLongName(ConstantValue constant) { | 595 String constantLongName(ConstantValue constant) { |
| 592 String longName = constantLongNames[constant]; | 596 String longName = constantLongNames[constant]; |
| 593 if (longName == null) { | 597 if (longName == null) { |
| 594 longName = new ConstantNamingVisitor( | 598 longName = new ConstantNamingVisitor( |
| 595 backend.rtiEncoder, reporter, constantHasher) | 599 backend.rtiEncoder, reporter, codegenWorldBuilder, constantHasher) |
| 596 .getName(constant); | 600 .getName(constant); |
| 597 constantLongNames[constant] = longName; | 601 constantLongNames[constant] = longName; |
| 598 } | 602 } |
| 599 return longName; | 603 return longName; |
| 600 } | 604 } |
| 601 | 605 |
| 602 String breakLabelName(LabelDefinition label) { | 606 String breakLabelName(LabelDefinition label) { |
| 603 return '\$${label.labelName}\$${label.target.nestingLevel}'; | 607 return '\$${label.labelName}\$${label.target.nestingLevel}'; |
| 604 } | 608 } |
| 605 | 609 |
| (...skipping 1032 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1638 * | 1642 * |
| 1639 */ | 1643 */ |
| 1640 class ConstantNamingVisitor implements ConstantValueVisitor { | 1644 class ConstantNamingVisitor implements ConstantValueVisitor { |
| 1641 static final RegExp IDENTIFIER = new RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$'); | 1645 static final RegExp IDENTIFIER = new RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$'); |
| 1642 static const MAX_FRAGMENTS = 5; | 1646 static const MAX_FRAGMENTS = 5; |
| 1643 static const MAX_EXTRA_LENGTH = 30; | 1647 static const MAX_EXTRA_LENGTH = 30; |
| 1644 static const DEFAULT_TAG_LENGTH = 3; | 1648 static const DEFAULT_TAG_LENGTH = 3; |
| 1645 | 1649 |
| 1646 final RuntimeTypesEncoder rtiEncoder; | 1650 final RuntimeTypesEncoder rtiEncoder; |
| 1647 final DiagnosticReporter reporter; | 1651 final DiagnosticReporter reporter; |
| 1652 final CodegenWorldBuilder codegenWorldBuilder; | |
| 1648 final ConstantCanonicalHasher hasher; | 1653 final ConstantCanonicalHasher hasher; |
| 1649 | 1654 |
| 1650 String root = null; // First word, usually a type name. | 1655 String root = null; // First word, usually a type name. |
| 1651 bool failed = false; // Failed to generate something pretty. | 1656 bool failed = false; // Failed to generate something pretty. |
| 1652 List<String> fragments = <String>[]; | 1657 List<String> fragments = <String>[]; |
| 1653 int length = 0; | 1658 int length = 0; |
| 1654 | 1659 |
| 1655 ConstantNamingVisitor(this.rtiEncoder, this.reporter, this.hasher); | 1660 ConstantNamingVisitor( |
| 1661 this.rtiEncoder, this.reporter, this.codegenWorldBuilder, this.hasher); | |
| 1656 | 1662 |
| 1657 String getName(ConstantValue constant) { | 1663 String getName(ConstantValue constant) { |
| 1658 _visit(constant); | 1664 _visit(constant); |
| 1659 if (root == null) return 'CONSTANT'; | 1665 if (root == null) return 'CONSTANT'; |
| 1660 if (failed) return '${root}_${getHashTag(constant, DEFAULT_TAG_LENGTH)}'; | 1666 if (failed) return '${root}_${getHashTag(constant, DEFAULT_TAG_LENGTH)}'; |
| 1661 if (fragments.length == 1) return 'C_${root}'; | 1667 if (fragments.length == 1) return 'C_${root}'; |
| 1662 return fragments.join('_'); | 1668 return fragments.join('_'); |
| 1663 } | 1669 } |
| 1664 | 1670 |
| 1665 String getHashTag(ConstantValue constant, int width) => | 1671 String getHashTag(ConstantValue constant, int width) => |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1774 } else { | 1780 } else { |
| 1775 // Using some bits from the keys hash tag groups the names Maps with the | 1781 // Using some bits from the keys hash tag groups the names Maps with the |
| 1776 // same structure. | 1782 // same structure. |
| 1777 add(getHashTag(constant.keyList, 2) + getHashTag(constant, 3)); | 1783 add(getHashTag(constant.keyList, 2) + getHashTag(constant, 3)); |
| 1778 } | 1784 } |
| 1779 } | 1785 } |
| 1780 | 1786 |
| 1781 @override | 1787 @override |
| 1782 void visitConstructed(ConstructedConstantValue constant, [_]) { | 1788 void visitConstructed(ConstructedConstantValue constant, [_]) { |
| 1783 addRoot(constant.type.element.name); | 1789 addRoot(constant.type.element.name); |
| 1784 constant.type.element.forEachInstanceField((_, FieldElement field) { | 1790 codegenWorldBuilder.forEachInstanceField(constant.type.element, |
|
Siggi Cherem (dart-lang)
2017/01/11 22:57:47
interesting - correct me if I'm wrong, but I thoug
Johnni Winther
2017/01/12 11:17:45
I agree. We should create a ClosedWorld for codege
| |
| 1791 (_, FieldElement field) { | |
| 1785 if (failed) return; | 1792 if (failed) return; |
| 1786 _visit(constant.fields[field]); | 1793 _visit(constant.fields[field]); |
| 1787 }, includeSuperAndInjectedMembers: true); | 1794 }); |
| 1788 } | 1795 } |
| 1789 | 1796 |
| 1790 @override | 1797 @override |
| 1791 void visitType(TypeConstantValue constant, [_]) { | 1798 void visitType(TypeConstantValue constant, [_]) { |
| 1792 // Generates something like 'Type_String_k8F', using the simple name of the | 1799 // Generates something like 'Type_String_k8F', using the simple name of the |
| 1793 // type and a hash to disambiguate the same name in different libraries. | 1800 // type and a hash to disambiguate the same name in different libraries. |
| 1794 addRoot('Type'); | 1801 addRoot('Type'); |
| 1795 ResolutionDartType type = constant.representedType; | 1802 ResolutionDartType type = constant.representedType; |
| 1796 String name = type.element?.name; | 1803 String name = type.element?.name; |
| 1797 if (name == null) { | 1804 if (name == null) { |
| 1798 // e.g. DartType 'dynamic' has no element. | 1805 // e.g. DartType 'dynamic' has no element. |
| 1799 name = rtiEncoder.getTypeRepresentationForTypeConstant(type); | 1806 name = rtiEncoder.getTypeRepresentationForTypeConstant(type); |
| 1800 } | 1807 } |
| 1801 addIdentifier(name); | 1808 addIdentifier(name); |
| 1802 add(getHashTag(constant, 3)); | 1809 add(getHashTag(constant, 3)); |
| 1803 } | 1810 } |
| 1804 | 1811 |
| 1805 @override | 1812 @override |
| 1806 void visitInterceptor(InterceptorConstantValue constant, [_]) { | 1813 void visitInterceptor(InterceptorConstantValue constant, [_]) { |
| 1807 addRoot(constant.dispatchedType.element.name); | 1814 addRoot(constant.cls.name); |
| 1808 add('methods'); | 1815 add('methods'); |
| 1809 } | 1816 } |
| 1810 | 1817 |
| 1811 @override | 1818 @override |
| 1812 void visitSynthetic(SyntheticConstantValue constant, [_]) { | 1819 void visitSynthetic(SyntheticConstantValue constant, [_]) { |
| 1813 switch (constant.valueKind) { | 1820 switch (constant.valueKind) { |
| 1814 case SyntheticConstantKind.DUMMY_INTERCEPTOR: | 1821 case SyntheticConstantKind.DUMMY_INTERCEPTOR: |
| 1815 add('dummy_receiver'); | 1822 add('dummy_receiver'); |
| 1816 break; | 1823 break; |
| 1817 case SyntheticConstantKind.TYPEVARIABLE_REFERENCE: | 1824 case SyntheticConstantKind.TYPEVARIABLE_REFERENCE: |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1839 * so it can't be used for generating names. This hasher keeps consistency | 1846 * so it can't be used for generating names. This hasher keeps consistency |
| 1840 * between runs by basing hash values of the names of elements, rather than | 1847 * between runs by basing hash values of the names of elements, rather than |
| 1841 * their hashCodes. | 1848 * their hashCodes. |
| 1842 */ | 1849 */ |
| 1843 class ConstantCanonicalHasher implements ConstantValueVisitor<int, Null> { | 1850 class ConstantCanonicalHasher implements ConstantValueVisitor<int, Null> { |
| 1844 static const _MASK = 0x1fffffff; | 1851 static const _MASK = 0x1fffffff; |
| 1845 static const _UINT32_LIMIT = 4 * 1024 * 1024 * 1024; | 1852 static const _UINT32_LIMIT = 4 * 1024 * 1024 * 1024; |
| 1846 | 1853 |
| 1847 final DiagnosticReporter reporter; | 1854 final DiagnosticReporter reporter; |
| 1848 final RuntimeTypesEncoder rtiEncoder; | 1855 final RuntimeTypesEncoder rtiEncoder; |
| 1856 final CodegenWorldBuilder codegenWorldBuilder; | |
| 1849 final Map<ConstantValue, int> hashes = new Map<ConstantValue, int>(); | 1857 final Map<ConstantValue, int> hashes = new Map<ConstantValue, int>(); |
| 1850 | 1858 |
| 1851 ConstantCanonicalHasher(this.rtiEncoder, this.reporter); | 1859 ConstantCanonicalHasher( |
| 1860 this.rtiEncoder, this.reporter, this.codegenWorldBuilder); | |
| 1852 | 1861 |
| 1853 int getHash(ConstantValue constant) => _visit(constant); | 1862 int getHash(ConstantValue constant) => _visit(constant); |
| 1854 | 1863 |
| 1855 int _visit(ConstantValue constant) { | 1864 int _visit(ConstantValue constant) { |
| 1856 int hash = hashes[constant]; | 1865 int hash = hashes[constant]; |
| 1857 if (hash == null) { | 1866 if (hash == null) { |
| 1858 hash = _finish(constant.accept(this, null)); | 1867 hash = _finish(constant.accept(this, null)); |
| 1859 hashes[constant] = hash; | 1868 hashes[constant] = hash; |
| 1860 } | 1869 } |
| 1861 return hash; | 1870 return hash; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1899 | 1908 |
| 1900 @override | 1909 @override |
| 1901 int visitMap(MapConstantValue constant, [_]) { | 1910 int visitMap(MapConstantValue constant, [_]) { |
| 1902 int hash = _hashList(constant.length, constant.keys); | 1911 int hash = _hashList(constant.length, constant.keys); |
| 1903 return _hashList(hash, constant.values); | 1912 return _hashList(hash, constant.values); |
| 1904 } | 1913 } |
| 1905 | 1914 |
| 1906 @override | 1915 @override |
| 1907 int visitConstructed(ConstructedConstantValue constant, [_]) { | 1916 int visitConstructed(ConstructedConstantValue constant, [_]) { |
| 1908 int hash = _hashString(3, constant.type.element.name); | 1917 int hash = _hashString(3, constant.type.element.name); |
| 1909 constant.type.element.forEachInstanceField((_, FieldElement field) { | 1918 codegenWorldBuilder.forEachInstanceField(constant.type.element, |
| 1919 (_, FieldElement field) { | |
| 1910 hash = _combine(hash, _visit(constant.fields[field])); | 1920 hash = _combine(hash, _visit(constant.fields[field])); |
| 1911 }, includeSuperAndInjectedMembers: true); | 1921 }); |
| 1912 return hash; | 1922 return hash; |
| 1913 } | 1923 } |
| 1914 | 1924 |
| 1915 @override | 1925 @override |
| 1916 int visitType(TypeConstantValue constant, [_]) { | 1926 int visitType(TypeConstantValue constant, [_]) { |
| 1917 ResolutionDartType type = constant.representedType; | 1927 ResolutionDartType type = constant.representedType; |
| 1918 // This name includes the library name and type parameters. | 1928 // This name includes the library name and type parameters. |
| 1919 String name = rtiEncoder.getTypeRepresentationForTypeConstant(type); | 1929 String name = rtiEncoder.getTypeRepresentationForTypeConstant(type); |
| 1920 return _hashString(4, name); | 1930 return _hashString(4, name); |
| 1921 } | 1931 } |
| 1922 | 1932 |
| 1923 @override | 1933 @override |
| 1924 int visitInterceptor(InterceptorConstantValue constant, [_]) { | 1934 int visitInterceptor(InterceptorConstantValue constant, [_]) { |
| 1925 String typeName = constant.dispatchedType.element.name; | 1935 String typeName = constant.cls.name; |
| 1926 return _hashString(5, typeName); | 1936 return _hashString(5, typeName); |
| 1927 } | 1937 } |
| 1928 | 1938 |
| 1929 @override | 1939 @override |
| 1930 int visitSynthetic(SyntheticConstantValue constant, [_]) { | 1940 int visitSynthetic(SyntheticConstantValue constant, [_]) { |
| 1931 switch (constant.valueKind) { | 1941 switch (constant.valueKind) { |
| 1932 case SyntheticConstantKind.TYPEVARIABLE_REFERENCE: | 1942 case SyntheticConstantKind.TYPEVARIABLE_REFERENCE: |
| 1933 // These contain a deferred opaque index into metadata. There is nothing | 1943 // These contain a deferred opaque index into metadata. There is nothing |
| 1934 // we can access that is stable between compiles. Luckily, since they | 1944 // we can access that is stable between compiles. Luckily, since they |
| 1935 // resolve to integer indexes, they're always part of a larger constant. | 1945 // resolve to integer indexes, they're always part of a larger constant. |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2095 void addSuggestion(String original, String suggestion) { | 2105 void addSuggestion(String original, String suggestion) { |
| 2096 assert(!_suggestedNames.containsKey(original)); | 2106 assert(!_suggestedNames.containsKey(original)); |
| 2097 _suggestedNames[original] = suggestion; | 2107 _suggestedNames[original] = suggestion; |
| 2098 } | 2108 } |
| 2099 | 2109 |
| 2100 bool hasSuggestion(String original) => _suggestedNames.containsKey(original); | 2110 bool hasSuggestion(String original) => _suggestedNames.containsKey(original); |
| 2101 bool isSuggestion(String candidate) { | 2111 bool isSuggestion(String candidate) { |
| 2102 return _suggestedNames.containsValue(candidate); | 2112 return _suggestedNames.containsValue(candidate); |
| 2103 } | 2113 } |
| 2104 } | 2114 } |
| OLD | NEW |