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

Side by Side Diff: pkg/compiler/lib/src/js_backend/namer.dart

Issue 2568723007: Create Namer and Emitter on codegen start. (Closed)
Patch Set: Small fix. Created 4 years 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
OLDNEW
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
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 395
396 jsAst.Name _rtiFieldName; 396 jsAst.Name _rtiFieldName;
397 jsAst.Name get rtiFieldName => _rtiFieldName ??= new StringBackedName(r'$ti'); 397 jsAst.Name get rtiFieldName => _rtiFieldName ??= new StringBackedName(r'$ti');
398 398
399 // Name of property in a class description for the native dispatch metadata. 399 // Name of property in a class description for the native dispatch metadata.
400 final String nativeSpecProperty = '%'; 400 final String nativeSpecProperty = '%';
401 401
402 static final RegExp IDENTIFIER = new RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$'); 402 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$]'); 403 static final RegExp NON_IDENTIFIER_CHAR = new RegExp(r'[^A-Za-z_0-9$]');
404 404
405 final Compiler compiler; 405 final JavaScriptBackend backend;
406 final ClosedWorld closedWorld;
406 407
407 /// Used disambiguated names in the global namespace, issued by 408 /// Used disambiguated names in the global namespace, issued by
408 /// [_disambiguateGlobal], and [_disambiguateInternalGlobal]. 409 /// [_disambiguateGlobal], and [_disambiguateInternalGlobal].
409 /// 410 ///
410 /// Although global names are distributed across a number of global objects, 411 /// Although global names are distributed across a number of global objects,
411 /// (see [globalObjectFor]), we currently use a single namespace for all these 412 /// (see [globalObjectFor]), we currently use a single namespace for all these
412 /// names. 413 /// names.
413 final NamingScope globalScope = new NamingScope(); 414 final NamingScope globalScope = new NamingScope();
414 final Map<Element, jsAst.Name> userGlobals = 415 final Map<Element, jsAst.Name> userGlobals =
415 new HashMap<Element, jsAst.Name>(); 416 new HashMap<Element, jsAst.Name>();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 453
453 final Map<String, String> suggestedGlobalNames = <String, String>{}; 454 final Map<String, String> suggestedGlobalNames = <String, String>{};
454 final Map<String, String> suggestedInstanceNames = <String, String>{}; 455 final Map<String, String> suggestedInstanceNames = <String, String>{};
455 456
456 /// Used to store unique keys for library names. Keys are not used as names, 457 /// Used to store unique keys for library names. Keys are not used as names,
457 /// nor are they visible in the output. The only serve as an internal 458 /// nor are they visible in the output. The only serve as an internal
458 /// key into maps. 459 /// key into maps.
459 final Map<LibraryElement, String> _libraryKeys = 460 final Map<LibraryElement, String> _libraryKeys =
460 new HashMap<LibraryElement, String>(); 461 new HashMap<LibraryElement, String>();
461 462
462 Namer(Compiler compiler) 463 Namer(JavaScriptBackend backend, this.closedWorld)
463 : compiler = compiler, 464 : this.backend = backend,
464 constantHasher = new ConstantCanonicalHasher(compiler), 465 constantHasher =
465 functionTypeNamer = new FunctionTypeNamer(compiler) { 466 new ConstantCanonicalHasher(backend.rtiEncoder, backend.reporter),
467 functionTypeNamer = new FunctionTypeNamer(backend.rtiEncoder) {
466 _literalAsyncPrefix = new StringBackedName(asyncPrefix); 468 _literalAsyncPrefix = new StringBackedName(asyncPrefix);
467 _literalGetterPrefix = new StringBackedName(getterPrefix); 469 _literalGetterPrefix = new StringBackedName(getterPrefix);
468 _literalSetterPrefix = new StringBackedName(setterPrefix); 470 _literalSetterPrefix = new StringBackedName(setterPrefix);
469 _literalLazyGetterPrefix = new StringBackedName(lazyGetterPrefix); 471 _literalLazyGetterPrefix = new StringBackedName(lazyGetterPrefix);
470 } 472 }
471 473
472 JavaScriptBackend get backend => compiler.backend;
473
474 BackendHelpers get helpers => backend.helpers; 474 BackendHelpers get helpers => backend.helpers;
475 475
476 DiagnosticReporter get reporter => compiler.reporter; 476 DiagnosticReporter get reporter => backend.reporter;
477 477
478 CoreClasses get coreClasses => compiler.coreClasses; 478 CoreClasses get coreClasses => closedWorld.coreClasses;
479 479
480 String get deferredTypesName => 'deferredTypes'; 480 String get deferredTypesName => 'deferredTypes';
481 String get isolateName => 'Isolate'; 481 String get isolateName => 'Isolate';
482 String get isolatePropertiesName => r'$isolateProperties'; 482 String get isolatePropertiesName => r'$isolateProperties';
483 jsAst.Name get noSuchMethodName => invocationName(Selectors.noSuchMethod_); 483 jsAst.Name get noSuchMethodName => invocationName(Selectors.noSuchMethod_);
484 484
485 /** 485 /**
486 * Some closures must contain their name. The name is stored in 486 * Some closures must contain their name. The name is stored in
487 * [STATIC_CLOSURE_NAME_NAME]. 487 * [STATIC_CLOSURE_NAME_NAME].
488 */ 488 */
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
584 result = getFreshName(constantScope, longName); 584 result = getFreshName(constantScope, longName);
585 constantNames[constant] = result; 585 constantNames[constant] = result;
586 } 586 }
587 return _newReference(result); 587 return _newReference(result);
588 } 588 }
589 589
590 /// Proposed name for [constant]. 590 /// Proposed name for [constant].
591 String constantLongName(ConstantValue constant) { 591 String constantLongName(ConstantValue constant) {
592 String longName = constantLongNames[constant]; 592 String longName = constantLongNames[constant];
593 if (longName == null) { 593 if (longName == null) {
594 longName = 594 longName = new ConstantNamingVisitor(
595 new ConstantNamingVisitor(compiler, constantHasher).getName(constant); 595 backend.rtiEncoder, reporter, constantHasher)
596 .getName(constant);
596 constantLongNames[constant] = longName; 597 constantLongNames[constant] = longName;
597 } 598 }
598 return longName; 599 return longName;
599 } 600 }
600 601
601 String breakLabelName(LabelDefinition label) { 602 String breakLabelName(LabelDefinition label) {
602 return '\$${label.labelName}\$${label.target.nestingLevel}'; 603 return '\$${label.labelName}\$${label.target.nestingLevel}';
603 } 604 }
604 605
605 String implicitBreakLabelName(JumpTarget target) { 606 String implicitBreakLabelName(JumpTarget target) {
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
847 element, () => asEntity.declaredEntity.name); 848 element, () => asEntity.declaredEntity.name);
848 } 849 }
849 850
850 // If the name of the field might clash with another field, 851 // If the name of the field might clash with another field,
851 // use a mangled field name to avoid potential clashes. 852 // use a mangled field name to avoid potential clashes.
852 // Note that if the class extends a native class, that native class might 853 // Note that if the class extends a native class, that native class might
853 // have fields with fixed backend names, so we assume the worst and always 854 // have fields with fixed backend names, so we assume the worst and always
854 // mangle the field names of classes extending native classes. 855 // mangle the field names of classes extending native classes.
855 // Methods on such classes are stored on the interceptor, not the instance, 856 // Methods on such classes are stored on the interceptor, not the instance,
856 // so only fields have the potential to clash with a native property name. 857 // so only fields have the potential to clash with a native property name.
857 ClosedWorld closedWorld = compiler.closedWorld;
858 if (closedWorld.isUsedAsMixin(enclosingClass) || 858 if (closedWorld.isUsedAsMixin(enclosingClass) ||
859 _isShadowingSuperField(element) || 859 _isShadowingSuperField(element) ||
860 _isUserClassExtendingNative(enclosingClass)) { 860 _isUserClassExtendingNative(enclosingClass)) {
861 String proposeName() => '${enclosingClass.name}_${element.name}'; 861 String proposeName() => '${enclosingClass.name}_${element.name}';
862 return _disambiguateInternalMember(element, proposeName); 862 return _disambiguateInternalMember(element, proposeName);
863 } 863 }
864 864
865 // No superclass uses the disambiguated name as a property name, so we can 865 // No superclass uses the disambiguated name as a property name, so we can
866 // use it for this field. This generates nicer field names since otherwise 866 // use it for this field. This generates nicer field names since otherwise
867 // the field name would have to be mangled. 867 // the field name would have to be mangled.
(...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after
1636 * Duration_16000 // const Duration(milliseconds: 16) 1636 * Duration_16000 // const Duration(milliseconds: 16)
1637 * EventKeyProvider_keyup // const EventKeyProvider('keyup') 1637 * EventKeyProvider_keyup // const EventKeyProvider('keyup')
1638 * 1638 *
1639 */ 1639 */
1640 class ConstantNamingVisitor implements ConstantValueVisitor { 1640 class ConstantNamingVisitor implements ConstantValueVisitor {
1641 static final RegExp IDENTIFIER = new RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$'); 1641 static final RegExp IDENTIFIER = new RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$');
1642 static const MAX_FRAGMENTS = 5; 1642 static const MAX_FRAGMENTS = 5;
1643 static const MAX_EXTRA_LENGTH = 30; 1643 static const MAX_EXTRA_LENGTH = 30;
1644 static const DEFAULT_TAG_LENGTH = 3; 1644 static const DEFAULT_TAG_LENGTH = 3;
1645 1645
1646 final Compiler compiler; 1646 final RuntimeTypesEncoder rtiEncoder;
1647 final DiagnosticReporter reporter;
1647 final ConstantCanonicalHasher hasher; 1648 final ConstantCanonicalHasher hasher;
1648 1649
1649 String root = null; // First word, usually a type name. 1650 String root = null; // First word, usually a type name.
1650 bool failed = false; // Failed to generate something pretty. 1651 bool failed = false; // Failed to generate something pretty.
1651 List<String> fragments = <String>[]; 1652 List<String> fragments = <String>[];
1652 int length = 0; 1653 int length = 0;
1653 1654
1654 ConstantNamingVisitor(this.compiler, this.hasher); 1655 ConstantNamingVisitor(this.rtiEncoder, this.reporter, this.hasher);
1655
1656 DiagnosticReporter get reporter => compiler.reporter;
1657 1656
1658 String getName(ConstantValue constant) { 1657 String getName(ConstantValue constant) {
1659 _visit(constant); 1658 _visit(constant);
1660 if (root == null) return 'CONSTANT'; 1659 if (root == null) return 'CONSTANT';
1661 if (failed) return '${root}_${getHashTag(constant, DEFAULT_TAG_LENGTH)}'; 1660 if (failed) return '${root}_${getHashTag(constant, DEFAULT_TAG_LENGTH)}';
1662 if (fragments.length == 1) return 'C_${root}'; 1661 if (fragments.length == 1) return 'C_${root}';
1663 return fragments.join('_'); 1662 return fragments.join('_');
1664 } 1663 }
1665 1664
1666 String getHashTag(ConstantValue constant, int width) => 1665 String getHashTag(ConstantValue constant, int width) =>
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1790 1789
1791 @override 1790 @override
1792 void visitType(TypeConstantValue constant, [_]) { 1791 void visitType(TypeConstantValue constant, [_]) {
1793 // Generates something like 'Type_String_k8F', using the simple name of the 1792 // Generates something like 'Type_String_k8F', using the simple name of the
1794 // type and a hash to disambiguate the same name in different libraries. 1793 // type and a hash to disambiguate the same name in different libraries.
1795 addRoot('Type'); 1794 addRoot('Type');
1796 DartType type = constant.representedType; 1795 DartType type = constant.representedType;
1797 String name = type.element?.name; 1796 String name = type.element?.name;
1798 if (name == null) { 1797 if (name == null) {
1799 // e.g. DartType 'dynamic' has no element. 1798 // e.g. DartType 'dynamic' has no element.
1800 JavaScriptBackend backend = compiler.backend; 1799 name = rtiEncoder.getTypeRepresentationForTypeConstant(type);
1801 name = backend.rtiEncoder.getTypeRepresentationForTypeConstant(type);
1802 } 1800 }
1803 addIdentifier(name); 1801 addIdentifier(name);
1804 add(getHashTag(constant, 3)); 1802 add(getHashTag(constant, 3));
1805 } 1803 }
1806 1804
1807 @override 1805 @override
1808 void visitInterceptor(InterceptorConstantValue constant, [_]) { 1806 void visitInterceptor(InterceptorConstantValue constant, [_]) {
1809 addRoot(constant.dispatchedType.element.name); 1807 addRoot(constant.dispatchedType.element.name);
1810 add('methods'); 1808 add('methods');
1811 } 1809 }
(...skipping 27 matching lines...) Expand all
1839 * 1837 *
1840 * Unfortunately, [Constant.hashCode] is not stable under minor perturbations, 1838 * Unfortunately, [Constant.hashCode] is not stable under minor perturbations,
1841 * so it can't be used for generating names. This hasher keeps consistency 1839 * so it can't be used for generating names. This hasher keeps consistency
1842 * between runs by basing hash values of the names of elements, rather than 1840 * between runs by basing hash values of the names of elements, rather than
1843 * their hashCodes. 1841 * their hashCodes.
1844 */ 1842 */
1845 class ConstantCanonicalHasher implements ConstantValueVisitor<int, Null> { 1843 class ConstantCanonicalHasher implements ConstantValueVisitor<int, Null> {
1846 static const _MASK = 0x1fffffff; 1844 static const _MASK = 0x1fffffff;
1847 static const _UINT32_LIMIT = 4 * 1024 * 1024 * 1024; 1845 static const _UINT32_LIMIT = 4 * 1024 * 1024 * 1024;
1848 1846
1849 final Compiler compiler; 1847 final DiagnosticReporter reporter;
1848 final RuntimeTypesEncoder rtiEncoder;
1850 final Map<ConstantValue, int> hashes = new Map<ConstantValue, int>(); 1849 final Map<ConstantValue, int> hashes = new Map<ConstantValue, int>();
1851 1850
1852 ConstantCanonicalHasher(this.compiler); 1851 ConstantCanonicalHasher(this.rtiEncoder, this.reporter);
1853
1854 DiagnosticReporter get reporter => compiler.reporter;
1855 1852
1856 int getHash(ConstantValue constant) => _visit(constant); 1853 int getHash(ConstantValue constant) => _visit(constant);
1857 1854
1858 int _visit(ConstantValue constant) { 1855 int _visit(ConstantValue constant) {
1859 int hash = hashes[constant]; 1856 int hash = hashes[constant];
1860 if (hash == null) { 1857 if (hash == null) {
1861 hash = _finish(constant.accept(this, null)); 1858 hash = _finish(constant.accept(this, null));
1862 hashes[constant] = hash; 1859 hashes[constant] = hash;
1863 } 1860 }
1864 return hash; 1861 return hash;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1911 int hash = _hashString(3, constant.type.element.name); 1908 int hash = _hashString(3, constant.type.element.name);
1912 constant.type.element.forEachInstanceField((_, FieldElement field) { 1909 constant.type.element.forEachInstanceField((_, FieldElement field) {
1913 hash = _combine(hash, _visit(constant.fields[field])); 1910 hash = _combine(hash, _visit(constant.fields[field]));
1914 }, includeSuperAndInjectedMembers: true); 1911 }, includeSuperAndInjectedMembers: true);
1915 return hash; 1912 return hash;
1916 } 1913 }
1917 1914
1918 @override 1915 @override
1919 int visitType(TypeConstantValue constant, [_]) { 1916 int visitType(TypeConstantValue constant, [_]) {
1920 DartType type = constant.representedType; 1917 DartType type = constant.representedType;
1921 JavaScriptBackend backend = compiler.backend;
1922 // This name includes the library name and type parameters. 1918 // This name includes the library name and type parameters.
1923 String name = backend.rtiEncoder.getTypeRepresentationForTypeConstant(type); 1919 String name = rtiEncoder.getTypeRepresentationForTypeConstant(type);
1924 return _hashString(4, name); 1920 return _hashString(4, name);
1925 } 1921 }
1926 1922
1927 @override 1923 @override
1928 int visitInterceptor(InterceptorConstantValue constant, [_]) { 1924 int visitInterceptor(InterceptorConstantValue constant, [_]) {
1929 String typeName = constant.dispatchedType.element.name; 1925 String typeName = constant.dispatchedType.element.name;
1930 return _hashString(5, typeName); 1926 return _hashString(5, typeName);
1931 } 1927 }
1932 1928
1933 @override 1929 @override
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
2020 } 2016 }
2021 2017
2022 static int _finish(int hash) { 2018 static int _finish(int hash) {
2023 hash = _MASK & (hash + (((_MASK >> 3) & hash) << 3)); 2019 hash = _MASK & (hash + (((_MASK >> 3) & hash) << 3));
2024 hash = hash & (hash >> 11); 2020 hash = hash & (hash >> 11);
2025 return _MASK & (hash + (((_MASK >> 15) & hash) << 15)); 2021 return _MASK & (hash + (((_MASK >> 15) & hash) << 15));
2026 } 2022 }
2027 } 2023 }
2028 2024
2029 class FunctionTypeNamer extends BaseDartTypeVisitor { 2025 class FunctionTypeNamer extends BaseDartTypeVisitor {
2030 final Compiler compiler; 2026 final RuntimeTypesEncoder rtiEncoder;
2031 StringBuffer sb; 2027 StringBuffer sb;
2032 2028
2033 FunctionTypeNamer(this.compiler); 2029 FunctionTypeNamer(this.rtiEncoder);
2034
2035 JavaScriptBackend get backend => compiler.backend;
2036 2030
2037 String computeName(DartType type) { 2031 String computeName(DartType type) {
2038 sb = new StringBuffer(); 2032 sb = new StringBuffer();
2039 visit(type); 2033 visit(type);
2040 return sb.toString(); 2034 return sb.toString();
2041 } 2035 }
2042 2036
2043 visit(DartType type, [_]) { 2037 visit(DartType type, [_]) {
2044 type.accept(this, null); 2038 type.accept(this, null);
2045 } 2039 }
2046 2040
2047 visitType(DartType type, _) { 2041 visitType(DartType type, _) {
2048 sb.write(type.name); 2042 sb.write(type.name);
2049 } 2043 }
2050 2044
2051 visitFunctionType(FunctionType type, _) { 2045 visitFunctionType(FunctionType type, _) {
2052 if (backend.rtiEncoder.isSimpleFunctionType(type)) { 2046 if (rtiEncoder.isSimpleFunctionType(type)) {
2053 sb.write('args${type.parameterTypes.length}'); 2047 sb.write('args${type.parameterTypes.length}');
2054 return; 2048 return;
2055 } 2049 }
2056 visit(type.returnType); 2050 visit(type.returnType);
2057 sb.write('_'); 2051 sb.write('_');
2058 for (DartType parameter in type.parameterTypes) { 2052 for (DartType parameter in type.parameterTypes) {
2059 sb.write('_'); 2053 sb.write('_');
2060 visit(parameter); 2054 visit(parameter);
2061 } 2055 }
2062 bool first = false; 2056 bool first = false;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2101 void addSuggestion(String original, String suggestion) { 2095 void addSuggestion(String original, String suggestion) {
2102 assert(!_suggestedNames.containsKey(original)); 2096 assert(!_suggestedNames.containsKey(original));
2103 _suggestedNames[original] = suggestion; 2097 _suggestedNames[original] = suggestion;
2104 } 2098 }
2105 2099
2106 bool hasSuggestion(String original) => _suggestedNames.containsKey(original); 2100 bool hasSuggestion(String original) => _suggestedNames.containsKey(original);
2107 bool isSuggestion(String candidate) { 2101 bool isSuggestion(String candidate) {
2108 return _suggestedNames.containsValue(candidate); 2102 return _suggestedNames.containsValue(candidate);
2109 } 2103 }
2110 } 2104 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/minify_namer.dart ('k') | pkg/compiler/lib/src/js_emitter/class_stub_generator.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698