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

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

Issue 2727253007: Add NativeClassData/NativeClassDataBuilder (Closed)
Patch Set: Created 3 years, 9 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
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
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 '../constants/values.dart'; 14 import '../constants/values.dart';
15 import '../common_elements.dart' show CommonElements; 15 import '../common_elements.dart' show CommonElements;
16 import '../diagnostics/invariant.dart' show DEBUG_MODE; 16 import '../diagnostics/invariant.dart' show DEBUG_MODE;
17 import '../elements/elements.dart'; 17 import '../elements/elements.dart';
18 import '../elements/entities.dart'; 18 import '../elements/entities.dart';
19 import '../elements/resolution_types.dart'; 19 import '../elements/resolution_types.dart';
20 import '../elements/types.dart'; 20 import '../elements/types.dart';
21 import '../js/js.dart' as jsAst; 21 import '../js/js.dart' as jsAst;
22 import '../js/js.dart' show js;
23 import '../tree/tree.dart'; 22 import '../tree/tree.dart';
24 import '../universe/call_structure.dart' show CallStructure; 23 import '../universe/call_structure.dart' show CallStructure;
25 import '../universe/selector.dart' show Selector, SelectorKind; 24 import '../universe/selector.dart' show Selector, SelectorKind;
26 import '../universe/world_builder.dart' show CodegenWorldBuilder; 25 import '../universe/world_builder.dart' show CodegenWorldBuilder;
27 import 'package:front_end/src/fasta/scanner/characters.dart'; 26 import 'package:front_end/src/fasta/scanner/characters.dart';
28 import '../util/util.dart'; 27 import '../util/util.dart';
29 import '../world.dart' show ClosedWorld; 28 import '../world.dart' show ClosedWorld;
30 import 'backend.dart'; 29 import 'backend.dart';
31 import 'backend_helpers.dart'; 30 import 'backend_helpers.dart';
32 import 'constant_system_javascript.dart'; 31 import 'constant_system_javascript.dart';
32 import 'native_data.dart';
33 33
34 part 'field_naming_mixin.dart'; 34 part 'field_naming_mixin.dart';
35 part 'frequency_namer.dart'; 35 part 'frequency_namer.dart';
36 part 'minify_namer.dart'; 36 part 'minify_namer.dart';
37 part 'namer_names.dart'; 37 part 'namer_names.dart';
38 38
39 /** 39 /**
40 * Assigns JavaScript identifiers to Dart variables, class-names and members. 40 * Assigns JavaScript identifiers to Dart variables, class-names and members.
41 * 41 *
42 * Names are generated through three stages: 42 * Names are generated through three stages:
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 478
479 jsAst.Name _rtiFieldName; 479 jsAst.Name _rtiFieldName;
480 jsAst.Name get rtiFieldName => _rtiFieldName ??= new StringBackedName(r'$ti'); 480 jsAst.Name get rtiFieldName => _rtiFieldName ??= new StringBackedName(r'$ti');
481 481
482 // Name of property in a class description for the native dispatch metadata. 482 // Name of property in a class description for the native dispatch metadata.
483 final String nativeSpecProperty = '%'; 483 final String nativeSpecProperty = '%';
484 484
485 static final RegExp IDENTIFIER = new RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$'); 485 static final RegExp IDENTIFIER = new RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$');
486 static final RegExp NON_IDENTIFIER_CHAR = new RegExp(r'[^A-Za-z_0-9$]'); 486 static final RegExp NON_IDENTIFIER_CHAR = new RegExp(r'[^A-Za-z_0-9$]');
487 487
488 final JavaScriptBackend backend; 488 final BackendHelpers _helpers;
489 final ClosedWorld closedWorld; 489 final NativeData _nativeData;
490 final CodegenWorldBuilder codegenWorldBuilder; 490 final ClosedWorld _closedWorld;
491 final CodegenWorldBuilder _codegenWorldBuilder;
491 492
492 RuntimeTypesEncoder _rtiEncoder; 493 RuntimeTypesEncoder _rtiEncoder;
493 RuntimeTypesEncoder get rtiEncoder { 494 RuntimeTypesEncoder get rtiEncoder {
494 assert(invariant(NO_LOCATION_SPANNABLE, _rtiEncoder != null, 495 assert(invariant(NO_LOCATION_SPANNABLE, _rtiEncoder != null,
495 message: "Namer.rtiEncoder has not been set.")); 496 message: "Namer.rtiEncoder has not been set."));
496 return _rtiEncoder; 497 return _rtiEncoder;
497 } 498 }
498 499
499 void set rtiEncoder(RuntimeTypesEncoder value) { 500 void set rtiEncoder(RuntimeTypesEncoder value) {
500 assert(invariant(NO_LOCATION_SPANNABLE, _rtiEncoder == null, 501 assert(invariant(NO_LOCATION_SPANNABLE, _rtiEncoder == null,
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 551
551 final Map<String, String> suggestedGlobalNames = <String, String>{}; 552 final Map<String, String> suggestedGlobalNames = <String, String>{};
552 final Map<String, String> suggestedInstanceNames = <String, String>{}; 553 final Map<String, String> suggestedInstanceNames = <String, String>{};
553 554
554 /// Used to store unique keys for library names. Keys are not used as names, 555 /// Used to store unique keys for library names. Keys are not used as names,
555 /// nor are they visible in the output. The only serve as an internal 556 /// nor are they visible in the output. The only serve as an internal
556 /// key into maps. 557 /// key into maps.
557 final Map<LibraryElement, String> _libraryKeys = 558 final Map<LibraryElement, String> _libraryKeys =
558 new HashMap<LibraryElement, String>(); 559 new HashMap<LibraryElement, String>();
559 560
560 Namer(JavaScriptBackend backend, this.closedWorld, 561 Namer(this._helpers, this._nativeData, this._closedWorld,
561 CodegenWorldBuilder codegenWorldBuilder) 562 this._codegenWorldBuilder) {
562 : this.backend = backend,
563 this.codegenWorldBuilder = codegenWorldBuilder {
564 _literalAsyncPrefix = new StringBackedName(asyncPrefix); 563 _literalAsyncPrefix = new StringBackedName(asyncPrefix);
565 _literalGetterPrefix = new StringBackedName(getterPrefix); 564 _literalGetterPrefix = new StringBackedName(getterPrefix);
566 _literalSetterPrefix = new StringBackedName(setterPrefix); 565 _literalSetterPrefix = new StringBackedName(setterPrefix);
567 _literalLazyGetterPrefix = new StringBackedName(lazyGetterPrefix); 566 _literalLazyGetterPrefix = new StringBackedName(lazyGetterPrefix);
568 } 567 }
569 568
570 BackendHelpers get helpers => backend.helpers; 569 CommonElements get _commonElements => _closedWorld.commonElements;
571
572 DiagnosticReporter get reporter => backend.reporter;
573
574 CommonElements get commonElements => closedWorld.commonElements;
575 570
576 String get deferredTypesName => 'deferredTypes'; 571 String get deferredTypesName => 'deferredTypes';
577 String get isolateName => 'Isolate'; 572 String get isolateName => 'Isolate';
578 String get isolatePropertiesName => r'$isolateProperties'; 573 String get isolatePropertiesName => r'$isolateProperties';
579 jsAst.Name get noSuchMethodName => invocationName(Selectors.noSuchMethod_); 574 jsAst.Name get noSuchMethodName => invocationName(Selectors.noSuchMethod_);
580 575
581 /** 576 /**
582 * Some closures must contain their name. The name is stored in 577 * Some closures must contain their name. The name is stored in
583 * [STATIC_CLOSURE_NAME_NAME]. 578 * [STATIC_CLOSURE_NAME_NAME].
584 */ 579 */
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
637 return asName(functionTypeVoidReturnTag); 632 return asName(functionTypeVoidReturnTag);
638 case JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG: 633 case JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG:
639 return asName(functionTypeReturnTypeTag); 634 return asName(functionTypeReturnTypeTag);
640 case JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG: 635 case JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG:
641 return asName(functionTypeRequiredParametersTag); 636 return asName(functionTypeRequiredParametersTag);
642 case JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG: 637 case JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG:
643 return asName(functionTypeOptionalParametersTag); 638 return asName(functionTypeOptionalParametersTag);
644 case JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG: 639 case JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG:
645 return asName(functionTypeNamedParametersTag); 640 return asName(functionTypeNamedParametersTag);
646 case JsGetName.IS_INDEXABLE_FIELD_NAME: 641 case JsGetName.IS_INDEXABLE_FIELD_NAME:
647 return operatorIs(helpers.jsIndexingBehaviorInterface); 642 return operatorIs(_helpers.jsIndexingBehaviorInterface);
648 case JsGetName.NULL_CLASS_TYPE_NAME: 643 case JsGetName.NULL_CLASS_TYPE_NAME:
649 ClassElement nullClass = commonElements.nullClass; 644 ClassElement nullClass = _commonElements.nullClass;
650 return runtimeTypeName(nullClass); 645 return runtimeTypeName(nullClass);
651 case JsGetName.OBJECT_CLASS_TYPE_NAME: 646 case JsGetName.OBJECT_CLASS_TYPE_NAME:
652 ClassElement objectClass = commonElements.objectClass; 647 ClassElement objectClass = _commonElements.objectClass;
653 return runtimeTypeName(objectClass); 648 return runtimeTypeName(objectClass);
654 case JsGetName.FUNCTION_CLASS_TYPE_NAME: 649 case JsGetName.FUNCTION_CLASS_TYPE_NAME:
655 ClassElement functionClass = commonElements.functionClass; 650 ClassElement functionClass = _commonElements.functionClass;
656 return runtimeTypeName(functionClass); 651 return runtimeTypeName(functionClass);
657 default: 652 default:
658 reporter.reportErrorMessage(node, MessageKind.GENERIC, 653 throw new SpannableAssertionFailure(
659 {'text': 'Error: Namer has no name for "$name".'}); 654 node, 'Error: Namer has no name for "$name".');
660 return asName('BROKEN');
661 } 655 }
662 } 656 }
663 657
664 /// Return a reference to the given [name]. 658 /// Return a reference to the given [name].
665 /// 659 ///
666 /// This is used to ensure that every use site of a name has a unique node so 660 /// This is used to ensure that every use site of a name has a unique node so
667 /// that we can properly attribute source information. 661 /// that we can properly attribute source information.
668 jsAst.Name _newReference(jsAst.Name name) { 662 jsAst.Name _newReference(jsAst.Name name) {
669 return new _NameReference(name); 663 return new _NameReference(name);
670 } 664 }
(...skipping 12 matching lines...) Expand all
683 result = getFreshName(constantScope, longName); 677 result = getFreshName(constantScope, longName);
684 constantNames[constant] = result; 678 constantNames[constant] = result;
685 } 679 }
686 return _newReference(result); 680 return _newReference(result);
687 } 681 }
688 682
689 /// Proposed name for [constant]. 683 /// Proposed name for [constant].
690 String constantLongName(ConstantValue constant) { 684 String constantLongName(ConstantValue constant) {
691 String longName = constantLongNames[constant]; 685 String longName = constantLongNames[constant];
692 if (longName == null) { 686 if (longName == null) {
693 _constantHasher ??= new ConstantCanonicalHasher( 687 _constantHasher ??=
694 rtiEncoder, reporter, codegenWorldBuilder); 688 new ConstantCanonicalHasher(rtiEncoder, _codegenWorldBuilder);
695 longName = new ConstantNamingVisitor( 689 longName = new ConstantNamingVisitor(
696 rtiEncoder, reporter, codegenWorldBuilder, _constantHasher) 690 rtiEncoder, _codegenWorldBuilder, _constantHasher)
697 .getName(constant); 691 .getName(constant);
698 constantLongNames[constant] = longName; 692 constantLongNames[constant] = longName;
699 } 693 }
700 return longName; 694 return longName;
701 } 695 }
702 696
703 String breakLabelName(LabelDefinition label) { 697 String breakLabelName(LabelDefinition label) {
704 return '\$${label.labelName}\$${label.target.nestingLevel}'; 698 return '\$${label.labelName}\$${label.target.nestingLevel}';
705 } 699 }
706 700
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
771 765
772 /// Annotated name for [method] encoding arity and named parameters. 766 /// Annotated name for [method] encoding arity and named parameters.
773 jsAst.Name instanceMethodName(MethodElement method) { 767 jsAst.Name instanceMethodName(MethodElement method) {
774 if (method.isGenerativeConstructorBody) { 768 if (method.isGenerativeConstructorBody) {
775 return constructorBodyName(method); 769 return constructorBodyName(method);
776 } 770 }
777 return invocationName(new Selector.fromElement(method)); 771 return invocationName(new Selector.fromElement(method));
778 } 772 }
779 773
780 String _jsNameHelper(Element e) { 774 String _jsNameHelper(Element e) {
781 String jsInteropName = backend.nativeData.getJsInteropName(e); 775 String jsInteropName = _nativeData.getJsInteropName(e);
782 if (jsInteropName != null && jsInteropName.isNotEmpty) return jsInteropName; 776 if (jsInteropName != null && jsInteropName.isNotEmpty) return jsInteropName;
783 return e.isLibrary 777 return e.isLibrary ? 'self' : _nativeData.getUnescapedJSInteropName(e.name);
784 ? 'self'
785 : backend.nativeData.getUnescapedJSInteropName(e.name);
786 } 778 }
787 779
788 /// Returns a JavaScript path specifying the context in which 780 /// Returns a JavaScript path specifying the context in which
789 /// [element.fixedBackendName] should be evaluated. Only applicable for 781 /// [element.fixedBackendName] should be evaluated. Only applicable for
790 /// elements using typed JavaScript interop. 782 /// elements using typed JavaScript interop.
791 /// For example: fixedBackendPath for the static method createMap in the 783 /// For example: fixedBackendPath for the static method createMap in the
792 /// Map class of the goog.map JavaScript library would have path 784 /// Map class of the goog.map JavaScript library would have path
793 /// "goog.maps.Map". 785 /// "goog.maps.Map".
794 String fixedBackendMethodPath(MethodElement element) { 786 String fixedBackendMethodPath(MethodElement element) {
795 return _fixedBackendPath(element); 787 return _fixedBackendPath(element);
796 } 788 }
797 789
798 String _fixedBackendPath(Element element) { 790 String _fixedBackendPath(Element element) {
799 if (!backend.nativeData.isJsInterop(element)) return null; 791 if (!_nativeData.isJsInterop(element)) return null;
800 if (element.isInstanceMember) return 'this'; 792 if (element.isInstanceMember) return 'this';
801 if (element.isConstructor) return _fixedBackendPath(element.enclosingClass); 793 if (element.isConstructor) return _fixedBackendPath(element.enclosingClass);
802 if (element.isLibrary) return 'self'; 794 if (element.isLibrary) return 'self';
803 var sb = new StringBuffer(); 795 var sb = new StringBuffer();
804 sb..write(_jsNameHelper(element.library)); 796 sb..write(_jsNameHelper(element.library));
805 797
806 if (element.enclosingClass != null && element.enclosingClass != element) { 798 if (element.enclosingClass != null && element.enclosingClass != element) {
807 sb..write('.')..write(_jsNameHelper(element.enclosingClass)); 799 sb..write('.')..write(_jsNameHelper(element.enclosingClass));
808 } 800 }
809 return sb.toString(); 801 return sb.toString();
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
871 List<String> suffix = callSuffixForStructure(selector.callStructure); 863 List<String> suffix = callSuffixForStructure(selector.callStructure);
872 if (selector.name == Identifiers.call) { 864 if (selector.name == Identifiers.call) {
873 // Derive the annotated name for this variant of 'call'. 865 // Derive the annotated name for this variant of 'call'.
874 return deriveCallMethodName(suffix); 866 return deriveCallMethodName(suffix);
875 } 867 }
876 jsAst.Name disambiguatedName = 868 jsAst.Name disambiguatedName =
877 _disambiguateMember(selector.memberName, suffix); 869 _disambiguateMember(selector.memberName, suffix);
878 return disambiguatedName; // Methods other than call are not annotated. 870 return disambiguatedName; // Methods other than call are not annotated.
879 871
880 default: 872 default:
881 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, 873 throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE,
882 'Unexpected selector kind: ${selector.kind}'); 874 'Unexpected selector kind: ${selector.kind}');
883 return null;
884 } 875 }
885 } 876 }
886 877
887 /** 878 /**
888 * Returns the internal name used for an invocation mirror of this selector. 879 * Returns the internal name used for an invocation mirror of this selector.
889 */ 880 */
890 jsAst.Name invocationMirrorInternalName(Selector selector) => 881 jsAst.Name invocationMirrorInternalName(Selector selector) =>
891 invocationName(selector); 882 invocationName(selector);
892 883
893 /** 884 /**
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
928 jsAst.Name globalPropertyName(Element element) { 919 jsAst.Name globalPropertyName(Element element) {
929 return _disambiguateGlobal(element); 920 return _disambiguateGlobal(element);
930 } 921 }
931 922
932 /** 923 /**
933 * Returns the JavaScript property name used to store an instance field. 924 * Returns the JavaScript property name used to store an instance field.
934 */ 925 */
935 jsAst.Name instanceFieldPropertyName(FieldElement element) { 926 jsAst.Name instanceFieldPropertyName(FieldElement element) {
936 ClassElement enclosingClass = element.enclosingClass; 927 ClassElement enclosingClass = element.enclosingClass;
937 928
938 if (backend.nativeData.hasFixedBackendName(element)) { 929 if (_nativeData.hasFixedBackendName(element)) {
939 return new StringBackedName( 930 return new StringBackedName(_nativeData.getFixedBackendName(element));
940 backend.nativeData.getFixedBackendName(element));
941 } 931 }
942 932
943 // Some elements, like e.g. instances of BoxFieldElement are special. 933 // Some elements, like e.g. instances of BoxFieldElement are special.
944 // They are created with a unique and safe name for the element model. 934 // They are created with a unique and safe name for the element model.
945 // While their name is unique, it is not very readable. So we try to 935 // While their name is unique, it is not very readable. So we try to
946 // preserve the original, proposed name. 936 // preserve the original, proposed name.
947 // However, as boxes are not really instances of classes, the usual naming 937 // However, as boxes are not really instances of classes, the usual naming
948 // scheme that tries to avoid name clashes with super classes does not 938 // scheme that tries to avoid name clashes with super classes does not
949 // apply. So we can directly grab a name. 939 // apply. So we can directly grab a name.
950 Entity asEntity = element; 940 Entity asEntity = element;
951 if (asEntity is JSEntity) { 941 if (asEntity is JSEntity) {
952 return _disambiguateInternalMember( 942 return _disambiguateInternalMember(
953 element, () => asEntity.declaredEntity.name); 943 element, () => asEntity.declaredEntity.name);
954 } 944 }
955 945
956 // If the name of the field might clash with another field, 946 // If the name of the field might clash with another field,
957 // use a mangled field name to avoid potential clashes. 947 // use a mangled field name to avoid potential clashes.
958 // Note that if the class extends a native class, that native class might 948 // Note that if the class extends a native class, that native class might
959 // have fields with fixed backend names, so we assume the worst and always 949 // have fields with fixed backend names, so we assume the worst and always
960 // mangle the field names of classes extending native classes. 950 // mangle the field names of classes extending native classes.
961 // Methods on such classes are stored on the interceptor, not the instance, 951 // Methods on such classes are stored on the interceptor, not the instance,
962 // so only fields have the potential to clash with a native property name. 952 // so only fields have the potential to clash with a native property name.
963 if (closedWorld.isUsedAsMixin(enclosingClass) || 953 if (_closedWorld.isUsedAsMixin(enclosingClass) ||
964 _isShadowingSuperField(element) || 954 _isShadowingSuperField(element) ||
965 _isUserClassExtendingNative(enclosingClass)) { 955 _isUserClassExtendingNative(enclosingClass)) {
966 String proposeName() => '${enclosingClass.name}_${element.name}'; 956 String proposeName() => '${enclosingClass.name}_${element.name}';
967 return _disambiguateInternalMember(element, proposeName); 957 return _disambiguateInternalMember(element, proposeName);
968 } 958 }
969 959
970 // No superclass uses the disambiguated name as a property name, so we can 960 // No superclass uses the disambiguated name as a property name, so we can
971 // use it for this field. This generates nicer field names since otherwise 961 // use it for this field. This generates nicer field names since otherwise
972 // the field name would have to be mangled. 962 // the field name would have to be mangled.
973 return _disambiguateMember(element.memberName); 963 return _disambiguateMember(element.memberName);
974 } 964 }
975 965
976 bool _isShadowingSuperField(Element element) { 966 bool _isShadowingSuperField(Element element) {
977 return element.enclosingClass.hasFieldShadowedBy(element); 967 return element.enclosingClass.hasFieldShadowedBy(element);
978 } 968 }
979 969
980 /// True if [class_] is a non-native class that inherits from a native class. 970 /// True if [class_] is a non-native class that inherits from a native class.
981 bool _isUserClassExtendingNative(ClassElement class_) { 971 bool _isUserClassExtendingNative(ClassElement class_) {
982 return !backend.nativeData.isNativeClass(class_) && 972 return !_nativeData.isNativeClass(class_) &&
983 backend.nativeData.isNativeOrExtendsNative(class_.superclass); 973 _nativeData.isNativeOrExtendsNative(class_.superclass);
984 } 974 }
985 975
986 /// Annotated name for the setter of [element]. 976 /// Annotated name for the setter of [element].
987 jsAst.Name setterForElement(MemberElement element) { 977 jsAst.Name setterForElement(MemberElement element) {
988 // We dynamically create setters from the field-name. The setter name must 978 // We dynamically create setters from the field-name. The setter name must
989 // therefore be derived from the instance field-name. 979 // therefore be derived from the instance field-name.
990 jsAst.Name name = _disambiguateMember(element.memberName); 980 jsAst.Name name = _disambiguateMember(element.memberName);
991 return deriveSetterName(name); 981 return deriveSetterName(name);
992 } 982 }
993 983
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
1351 String disambiguated = name; 1341 String disambiguated = name;
1352 for (int c = 0; libraryLongNames.containsValue(disambiguated); c++) { 1342 for (int c = 0; libraryLongNames.containsValue(disambiguated); c++) {
1353 disambiguated = "$name$c"; 1343 disambiguated = "$name$c";
1354 } 1344 }
1355 libraryLongNames[library] = disambiguated; 1345 libraryLongNames[library] = disambiguated;
1356 return disambiguated; 1346 return disambiguated;
1357 } 1347 }
1358 1348
1359 String suffixForGetInterceptor(Iterable<ClassEntity> classes) { 1349 String suffixForGetInterceptor(Iterable<ClassEntity> classes) {
1360 String abbreviate(ClassElement cls) { 1350 String abbreviate(ClassElement cls) {
1361 if (cls == commonElements.objectClass) return "o"; 1351 if (cls == _commonElements.objectClass) return "o";
1362 if (cls == helpers.jsStringClass) return "s"; 1352 if (cls == _helpers.jsStringClass) return "s";
1363 if (cls == helpers.jsArrayClass) return "a"; 1353 if (cls == _helpers.jsArrayClass) return "a";
1364 if (cls == helpers.jsDoubleClass) return "d"; 1354 if (cls == _helpers.jsDoubleClass) return "d";
1365 if (cls == helpers.jsIntClass) return "i"; 1355 if (cls == _helpers.jsIntClass) return "i";
1366 if (cls == helpers.jsNumberClass) return "n"; 1356 if (cls == _helpers.jsNumberClass) return "n";
1367 if (cls == helpers.jsNullClass) return "u"; 1357 if (cls == _helpers.jsNullClass) return "u";
1368 if (cls == helpers.jsBoolClass) return "b"; 1358 if (cls == _helpers.jsBoolClass) return "b";
1369 if (cls == helpers.jsInterceptorClass) return "I"; 1359 if (cls == _helpers.jsInterceptorClass) return "I";
1370 return cls.name; 1360 return cls.name;
1371 } 1361 }
1372 1362
1373 List<String> names = classes 1363 List<String> names = classes
1374 .where((cls) => !backend.nativeData.isNativeOrExtendsNative(cls)) 1364 .where((cls) => !_nativeData.isNativeOrExtendsNative(cls))
1375 .map(abbreviate) 1365 .map(abbreviate)
1376 .toList(); 1366 .toList();
1377 // There is one dispatch mechanism for all native classes. 1367 // There is one dispatch mechanism for all native classes.
1378 if (classes.any((cls) => backend.nativeData.isNativeOrExtendsNative(cls))) { 1368 if (classes.any((cls) => _nativeData.isNativeOrExtendsNative(cls))) {
1379 names.add("x"); 1369 names.add("x");
1380 } 1370 }
1381 // Sort the names of the classes after abbreviating them to ensure 1371 // Sort the names of the classes after abbreviating them to ensure
1382 // the suffix is stable and predictable for the suggested names. 1372 // the suffix is stable and predictable for the suggested names.
1383 names.sort(); 1373 names.sort();
1384 return names.join(); 1374 return names.join();
1385 } 1375 }
1386 1376
1387 /// Property name used for `getInterceptor` or one of its specializations. 1377 /// Property name used for `getInterceptor` or one of its specializations.
1388 jsAst.Name nameForGetInterceptor(Iterable<ClassEntity> classes) { 1378 jsAst.Name nameForGetInterceptor(Iterable<ClassEntity> classes) {
1389 MethodElement getInterceptor = helpers.getInterceptorMethod; 1379 MethodElement getInterceptor = _helpers.getInterceptorMethod;
1390 if (classes.contains(helpers.jsInterceptorClass)) { 1380 if (classes.contains(_helpers.jsInterceptorClass)) {
1391 // If the base Interceptor class is in the set of intercepted classes, we 1381 // If the base Interceptor class is in the set of intercepted classes, we
1392 // need to go through the generic getInterceptorMethod, since any subclass 1382 // need to go through the generic getInterceptorMethod, since any subclass
1393 // of the base Interceptor could match. 1383 // of the base Interceptor could match.
1394 // The unspecialized getInterceptor method can also be accessed through 1384 // The unspecialized getInterceptor method can also be accessed through
1395 // its element, so we treat this as a user-space global instead of an 1385 // its element, so we treat this as a user-space global instead of an
1396 // internal global. 1386 // internal global.
1397 return _disambiguateGlobal(getInterceptor); 1387 return _disambiguateGlobal(getInterceptor);
1398 } 1388 }
1399 String suffix = suffixForGetInterceptor(classes); 1389 String suffix = suffixForGetInterceptor(classes);
1400 return _disambiguateInternalGlobal("${getInterceptor.name}\$$suffix"); 1390 return _disambiguateInternalGlobal("${getInterceptor.name}\$$suffix");
1401 } 1391 }
1402 1392
1403 /// Property name used for the one-shot interceptor method for the given 1393 /// Property name used for the one-shot interceptor method for the given
1404 /// [selector] and return-type specialization. 1394 /// [selector] and return-type specialization.
1405 jsAst.Name nameForGetOneShotInterceptor( 1395 jsAst.Name nameForGetOneShotInterceptor(
1406 Selector selector, Iterable<ClassEntity> classes) { 1396 Selector selector, Iterable<ClassEntity> classes) {
1407 // The one-shot name is a global name derived from the invocation name. To 1397 // The one-shot name is a global name derived from the invocation name. To
1408 // avoid instability we would like the names to be unique and not clash with 1398 // avoid instability we would like the names to be unique and not clash with
1409 // other global names. 1399 // other global names.
1410 jsAst.Name root = invocationName(selector); 1400 jsAst.Name root = invocationName(selector);
1411 1401
1412 if (classes.contains(helpers.jsInterceptorClass)) { 1402 if (classes.contains(_helpers.jsInterceptorClass)) {
1413 // If the base Interceptor class is in the set of intercepted classes, 1403 // If the base Interceptor class is in the set of intercepted classes,
1414 // this is the most general specialization which uses the generic 1404 // this is the most general specialization which uses the generic
1415 // getInterceptor method. 1405 // getInterceptor method.
1416 // TODO(sra): Find a way to get the simple name when Object is not in the 1406 // TODO(sra): Find a way to get the simple name when Object is not in the
1417 // set of classes for most general variant, e.g. "$lt$n" could be "$lt". 1407 // set of classes for most general variant, e.g. "$lt$n" could be "$lt".
1418 return new CompoundName([root, _literalDollar]); 1408 return new CompoundName([root, _literalDollar]);
1419 } else { 1409 } else {
1420 String suffix = suffixForGetInterceptor(classes); 1410 String suffix = suffixForGetInterceptor(classes);
1421 return new CompoundName( 1411 return new CompoundName(
1422 [root, _literalDollar, new StringBackedName(suffix)]); 1412 [root, _literalDollar, new StringBackedName(suffix)]);
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
1522 globalObjectFor(element); 1512 globalObjectFor(element);
1523 1513
1524 /// Returns [staticStateHolder] or one of [reservedGlobalObjectNames]. 1514 /// Returns [staticStateHolder] or one of [reservedGlobalObjectNames].
1525 String globalObjectFor(Element element) { 1515 String globalObjectFor(Element element) {
1526 if (_isPropertyOfStaticStateHolder(element)) return staticStateHolder; 1516 if (_isPropertyOfStaticStateHolder(element)) return staticStateHolder;
1527 return globalObjectForLibrary(element.library); 1517 return globalObjectForLibrary(element.library);
1528 } 1518 }
1529 1519
1530 /// Returns the [reservedGlobalObjectNames] for [library]. 1520 /// Returns the [reservedGlobalObjectNames] for [library].
1531 String globalObjectForLibrary(LibraryElement library) { 1521 String globalObjectForLibrary(LibraryElement library) {
1532 if (library == helpers.interceptorsLibrary) return 'J'; 1522 if (library == _helpers.interceptorsLibrary) return 'J';
1533 if (library.isInternalLibrary) return 'H'; 1523 if (library.isInternalLibrary) return 'H';
1534 if (library.isPlatformLibrary) { 1524 if (library.isPlatformLibrary) {
1535 if ('${library.canonicalUri}' == 'dart:html') return 'W'; 1525 if ('${library.canonicalUri}' == 'dart:html') return 'W';
1536 return 'P'; 1526 return 'P';
1537 } 1527 }
1538 return userGlobalObjects[library.name.hashCode % userGlobalObjects.length]; 1528 return userGlobalObjects[library.name.hashCode % userGlobalObjects.length];
1539 } 1529 }
1540 1530
1541 jsAst.Name deriveLazyInitializerName(jsAst.Name name) { 1531 jsAst.Name deriveLazyInitializerName(jsAst.Name name) {
1542 // These are not real dart getters, so do not use GetterName; 1532 // These are not real dart getters, so do not use GetterName;
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
1742 * EventKeyProvider_keyup // const EventKeyProvider('keyup') 1732 * EventKeyProvider_keyup // const EventKeyProvider('keyup')
1743 * 1733 *
1744 */ 1734 */
1745 class ConstantNamingVisitor implements ConstantValueVisitor { 1735 class ConstantNamingVisitor implements ConstantValueVisitor {
1746 static final RegExp IDENTIFIER = new RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$'); 1736 static final RegExp IDENTIFIER = new RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$');
1747 static const MAX_FRAGMENTS = 5; 1737 static const MAX_FRAGMENTS = 5;
1748 static const MAX_EXTRA_LENGTH = 30; 1738 static const MAX_EXTRA_LENGTH = 30;
1749 static const DEFAULT_TAG_LENGTH = 3; 1739 static const DEFAULT_TAG_LENGTH = 3;
1750 1740
1751 final RuntimeTypesEncoder rtiEncoder; 1741 final RuntimeTypesEncoder rtiEncoder;
1752 final DiagnosticReporter reporter;
1753 final CodegenWorldBuilder codegenWorldBuilder; 1742 final CodegenWorldBuilder codegenWorldBuilder;
1754 final ConstantCanonicalHasher hasher; 1743 final ConstantCanonicalHasher hasher;
1755 1744
1756 String root = null; // First word, usually a type name. 1745 String root = null; // First word, usually a type name.
1757 bool failed = false; // Failed to generate something pretty. 1746 bool failed = false; // Failed to generate something pretty.
1758 List<String> fragments = <String>[]; 1747 List<String> fragments = <String>[];
1759 int length = 0; 1748 int length = 0;
1760 1749
1761 ConstantNamingVisitor( 1750 ConstantNamingVisitor(this.rtiEncoder, this.codegenWorldBuilder, this.hasher);
1762 this.rtiEncoder, this.reporter, this.codegenWorldBuilder, this.hasher);
1763 1751
1764 String getName(ConstantValue constant) { 1752 String getName(ConstantValue constant) {
1765 _visit(constant); 1753 _visit(constant);
1766 if (root == null) return 'CONSTANT'; 1754 if (root == null) return 'CONSTANT';
1767 if (failed) return '${root}_${getHashTag(constant, DEFAULT_TAG_LENGTH)}'; 1755 if (failed) return '${root}_${getHashTag(constant, DEFAULT_TAG_LENGTH)}';
1768 if (fragments.length == 1) return 'C_${root}'; 1756 if (fragments.length == 1) return 'C_${root}';
1769 return fragments.join('_'); 1757 return fragments.join('_');
1770 } 1758 }
1771 1759
1772 String getHashTag(ConstantValue constant, int width) => 1760 String getHashTag(ConstantValue constant, int width) =>
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1923 case SyntheticConstantKind.DUMMY_INTERCEPTOR: 1911 case SyntheticConstantKind.DUMMY_INTERCEPTOR:
1924 add('dummy_receiver'); 1912 add('dummy_receiver');
1925 break; 1913 break;
1926 case SyntheticConstantKind.TYPEVARIABLE_REFERENCE: 1914 case SyntheticConstantKind.TYPEVARIABLE_REFERENCE:
1927 // Omit. These are opaque deferred indexes with nothing helpful to add. 1915 // Omit. These are opaque deferred indexes with nothing helpful to add.
1928 break; 1916 break;
1929 case SyntheticConstantKind.NAME: 1917 case SyntheticConstantKind.NAME:
1930 add('name'); 1918 add('name');
1931 break; 1919 break;
1932 default: 1920 default:
1933 reporter.internalError( 1921 throw new SpannableAssertionFailure(
1934 CURRENT_ELEMENT_SPANNABLE, "Unexpected SyntheticConstantValue"); 1922 CURRENT_ELEMENT_SPANNABLE, "Unexpected SyntheticConstantValue");
1935 } 1923 }
1936 } 1924 }
1937 1925
1938 @override 1926 @override
1939 void visitDeferred(DeferredConstantValue constant, [_]) { 1927 void visitDeferred(DeferredConstantValue constant, [_]) {
1940 addRoot('Deferred'); 1928 addRoot('Deferred');
1941 } 1929 }
1942 } 1930 }
1943 1931
1944 /** 1932 /**
1945 * Generates canonical hash values for [ConstantValue]s. 1933 * Generates canonical hash values for [ConstantValue]s.
1946 * 1934 *
1947 * Unfortunately, [Constant.hashCode] is not stable under minor perturbations, 1935 * Unfortunately, [Constant.hashCode] is not stable under minor perturbations,
1948 * so it can't be used for generating names. This hasher keeps consistency 1936 * so it can't be used for generating names. This hasher keeps consistency
1949 * between runs by basing hash values of the names of elements, rather than 1937 * between runs by basing hash values of the names of elements, rather than
1950 * their hashCodes. 1938 * their hashCodes.
1951 */ 1939 */
1952 class ConstantCanonicalHasher implements ConstantValueVisitor<int, Null> { 1940 class ConstantCanonicalHasher implements ConstantValueVisitor<int, Null> {
1953 static const _MASK = 0x1fffffff; 1941 static const _MASK = 0x1fffffff;
1954 static const _UINT32_LIMIT = 4 * 1024 * 1024 * 1024; 1942 static const _UINT32_LIMIT = 4 * 1024 * 1024 * 1024;
1955 1943
1956 final DiagnosticReporter reporter;
1957 final RuntimeTypesEncoder rtiEncoder; 1944 final RuntimeTypesEncoder rtiEncoder;
1958 final CodegenWorldBuilder codegenWorldBuilder; 1945 final CodegenWorldBuilder codegenWorldBuilder;
1959 final Map<ConstantValue, int> hashes = new Map<ConstantValue, int>(); 1946 final Map<ConstantValue, int> hashes = new Map<ConstantValue, int>();
1960 1947
1961 ConstantCanonicalHasher( 1948 ConstantCanonicalHasher(this.rtiEncoder, this.codegenWorldBuilder);
1962 this.rtiEncoder, this.reporter, this.codegenWorldBuilder);
1963 1949
1964 int getHash(ConstantValue constant) => _visit(constant); 1950 int getHash(ConstantValue constant) => _visit(constant);
1965 1951
1966 int _visit(ConstantValue constant) { 1952 int _visit(ConstantValue constant) {
1967 int hash = hashes[constant]; 1953 int hash = hashes[constant];
1968 if (hash == null) { 1954 if (hash == null) {
1969 hash = _finish(constant.accept(this, null)); 1955 hash = _finish(constant.accept(this, null));
1970 hashes[constant] = hash; 1956 hashes[constant] = hash;
1971 } 1957 }
1972 return hash; 1958 return hash;
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
2040 2026
2041 @override 2027 @override
2042 int visitSynthetic(SyntheticConstantValue constant, [_]) { 2028 int visitSynthetic(SyntheticConstantValue constant, [_]) {
2043 switch (constant.valueKind) { 2029 switch (constant.valueKind) {
2044 case SyntheticConstantKind.TYPEVARIABLE_REFERENCE: 2030 case SyntheticConstantKind.TYPEVARIABLE_REFERENCE:
2045 // These contain a deferred opaque index into metadata. There is nothing 2031 // These contain a deferred opaque index into metadata. There is nothing
2046 // we can access that is stable between compiles. Luckily, since they 2032 // we can access that is stable between compiles. Luckily, since they
2047 // resolve to integer indexes, they're always part of a larger constant. 2033 // resolve to integer indexes, they're always part of a larger constant.
2048 return 0; 2034 return 0;
2049 default: 2035 default:
2050 reporter.internalError( 2036 throw new SpannableAssertionFailure(
2051 NO_LOCATION_SPANNABLE, 2037 NO_LOCATION_SPANNABLE,
2052 'SyntheticConstantValue should never be named and ' 2038 'SyntheticConstantValue should never be named and '
2053 'never be subconstant'); 2039 'never be subconstant');
2054 return 0;
2055 } 2040 }
2056 } 2041 }
2057 2042
2058 @override 2043 @override
2059 int visitDeferred(DeferredConstantValue constant, [_]) { 2044 int visitDeferred(DeferredConstantValue constant, [_]) {
2060 // TODO(sra): Investigate that the use of hashCode here is probably a source 2045 // TODO(sra): Investigate that the use of hashCode here is probably a source
2061 // of instability. 2046 // of instability.
2062 int hash = constant.prefix.hashCode; 2047 int hash = constant.prefix.hashCode;
2063 return _combine(hash, _visit(constant.referenced)); 2048 return _combine(hash, _visit(constant.referenced));
2064 } 2049 }
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
2207 void addSuggestion(String original, String suggestion) { 2192 void addSuggestion(String original, String suggestion) {
2208 assert(!_suggestedNames.containsKey(original)); 2193 assert(!_suggestedNames.containsKey(original));
2209 _suggestedNames[original] = suggestion; 2194 _suggestedNames[original] = suggestion;
2210 } 2195 }
2211 2196
2212 bool hasSuggestion(String original) => _suggestedNames.containsKey(original); 2197 bool hasSuggestion(String original) => _suggestedNames.containsKey(original);
2213 bool isSuggestion(String candidate) { 2198 bool isSuggestion(String candidate) {
2214 return _suggestedNames.containsValue(candidate); 2199 return _suggestedNames.containsValue(candidate);
2215 } 2200 }
2216 } 2201 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/minify_namer.dart ('k') | pkg/compiler/lib/src/js_backend/native_data.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698