OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library dart2js.js_emitter.program_builder; | 5 library dart2js.js_emitter.program_builder; |
6 | 6 |
7 import 'dart:io'; | 7 import 'dart:io'; |
8 import 'dart:convert' show JSON; | 8 import 'dart:convert' show JSON; |
9 | 9 |
10 import '../../closure.dart' show ClosureConversionTask, ClosureFieldElement; | 10 import '../../closure.dart' show ClosureConversionTask, ClosureFieldElement; |
11 import '../../common.dart'; | 11 import '../../common.dart'; |
12 import '../../common/names.dart' show Names, Selectors; | 12 import '../../common/names.dart' show Names, Selectors; |
13 import '../../constants/values.dart' | 13 import '../../constants/values.dart' |
14 show ConstantValue, InterceptorConstantValue; | 14 show ConstantValue, InterceptorConstantValue; |
15 import '../../common_elements.dart' show CommonElements, ElementEnvironment; | 15 import '../../common_elements.dart' show CommonElements, ElementEnvironment; |
16 import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit; | 16 import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit; |
17 import '../../elements/elements.dart' | 17 import '../../elements/elements.dart' |
18 show | 18 show ClassElement, FieldElement, LibraryElement, MethodElement; |
19 ClassElement, | |
20 FieldElement, | |
21 FunctionSignature, | |
22 LibraryElement, | |
23 MemberElement, | |
24 MethodElement, | |
25 ParameterElement; | |
26 import '../../elements/entities.dart'; | 19 import '../../elements/entities.dart'; |
27 import '../../elements/resolution_types.dart' show ResolutionDartType; | |
28 import '../../elements/types.dart'; | 20 import '../../elements/types.dart'; |
29 import '../../js/js.dart' as js; | 21 import '../../js/js.dart' as js; |
30 import '../../js_backend/backend.dart' show SuperMemberData; | 22 import '../../js_backend/backend.dart' show SuperMemberData; |
31 import '../../js_backend/backend_usage.dart'; | 23 import '../../js_backend/backend_usage.dart'; |
32 import '../../js_backend/constant_handler_javascript.dart' | 24 import '../../js_backend/constant_handler_javascript.dart' |
33 show JavaScriptConstantCompiler; | 25 show JavaScriptConstantCompiler; |
34 import '../../js_backend/custom_elements_analysis.dart'; | 26 import '../../js_backend/custom_elements_analysis.dart'; |
35 import '../../js_backend/namer.dart' show Namer, StringBackedName; | 27 import '../../js_backend/namer.dart' show Namer, StringBackedName; |
36 import '../../js_backend/native_data.dart'; | 28 import '../../js_backend/native_data.dart'; |
37 import '../../js_backend/interceptor_data.dart'; | 29 import '../../js_backend/interceptor_data.dart'; |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 final Map<js.Name, String> _symbolsMap = <js.Name, String>{}; | 177 final Map<js.Name, String> _symbolsMap = <js.Name, String>{}; |
186 | 178 |
187 Set<Class> _unneededNativeClasses; | 179 Set<Class> _unneededNativeClasses; |
188 | 180 |
189 /// Classes that have been allocated during a profile run. | 181 /// Classes that have been allocated during a profile run. |
190 /// | 182 /// |
191 /// These classes should not be soft-deferred. | 183 /// These classes should not be soft-deferred. |
192 /// | 184 /// |
193 /// Also contains classes that are not tracked by the profile run (like | 185 /// Also contains classes that are not tracked by the profile run (like |
194 /// interceptors, ...). | 186 /// interceptors, ...). |
195 Set<ClassElement> _notSoftDeferred; | 187 Set<ClassEntity> _notSoftDeferred; |
196 | 188 |
197 Program buildProgram({bool storeFunctionTypesInMetadata: false}) { | 189 Program buildProgram({bool storeFunctionTypesInMetadata: false}) { |
198 collector.collect(); | 190 collector.collect(); |
199 _initializeSoftDeferredMap(); | 191 _initializeSoftDeferredMap(); |
200 | 192 |
201 this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata; | 193 this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata; |
202 // Note: In rare cases (mostly tests) output units can be empty. This | 194 // Note: In rare cases (mostly tests) output units can be empty. This |
203 // happens when the deferred code is dead-code eliminated but we still need | 195 // happens when the deferred code is dead-code eliminated but we still need |
204 // to check that the library has been loaded. | 196 // to check that the library has been loaded. |
205 _deferredLoadTask.allOutputUnits.forEach(_registry.registerOutputUnit); | 197 _deferredLoadTask.allOutputUnits.forEach(_registry.registerOutputUnit); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 _reporter.log("Profile file does not exist: $allocatedClassesPath"); | 311 _reporter.log("Profile file does not exist: $allocatedClassesPath"); |
320 return; | 312 return; |
321 } | 313 } |
322 if (file.lengthSync() == 0) { | 314 if (file.lengthSync() == 0) { |
323 _reporter.log("Profile information (allocated classes) is empty."); | 315 _reporter.log("Profile information (allocated classes) is empty."); |
324 return; | 316 return; |
325 } | 317 } |
326 | 318 |
327 String data = new File(allocatedClassesPath).readAsStringSync(); | 319 String data = new File(allocatedClassesPath).readAsStringSync(); |
328 Set<String> allocatedClassesKeys = JSON.decode(data).keys.toSet(); | 320 Set<String> allocatedClassesKeys = JSON.decode(data).keys.toSet(); |
329 Set<ClassElement> allocatedClasses = new Set<ClassElement>(); | 321 Set<ClassEntity> allocatedClasses = new Set<ClassEntity>(); |
330 | 322 |
331 // Collects all super and mixin classes of a class. | 323 // Collects all super and mixin classes of a class. |
332 void collect(ClassElement element) { | 324 void collect(ClassEntity element) { |
333 allocatedClasses.add(element); | 325 allocatedClasses.add(element); |
334 if (element.isMixinApplication) { | 326 if (_elementEnvironment.isMixinApplication(element)) { |
335 collect(_elementEnvironment.getEffectiveMixinClass(element)); | 327 collect(_elementEnvironment.getEffectiveMixinClass(element)); |
336 } | 328 } |
337 if (element.superclass != null) { | 329 ClassEntity superclass = _elementEnvironment.getSuperClass(element); |
338 collect(element.superclass); | 330 if (superclass != null) { |
| 331 collect(superclass); |
339 } | 332 } |
340 } | 333 } |
341 | 334 |
342 // For every known class, see if it was allocated in the profile. If yes, | 335 // For every known class, see if it was allocated in the profile. If yes, |
343 // collect its dependencies (supers and mixins) and mark them as | 336 // collect its dependencies (supers and mixins) and mark them as |
344 // not-soft-deferrable. | 337 // not-soft-deferrable. |
345 collector.outputClassLists.forEach((_, List<ClassEntity> elements) { | 338 collector.outputClassLists.forEach((_, List<ClassEntity> elements) { |
346 for (ClassElement element in elements) { | 339 for (ClassEntity element in elements) { |
347 // TODO(29574): share the encoding of the element with the code | 340 // TODO(29574): share the encoding of the element with the code |
348 // that emits the profile-run. | 341 // that emits the profile-run. |
349 var key = "${element.library.canonicalUri}:${element.name}"; | 342 var key = "${element.library.canonicalUri}:${element.name}"; |
350 if (allocatedClassesKeys.contains(key) || | 343 if (allocatedClassesKeys.contains(key) || |
351 _nativeData.isJsInteropClass(element) || | 344 _nativeData.isJsInteropClass(element) || |
352 blackList.contains(element.library.canonicalUri.toString())) { | 345 blackList.contains(element.library.canonicalUri.toString())) { |
353 collect(element); | 346 collect(element); |
354 } | 347 } |
355 } | 348 } |
356 }); | 349 }); |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 } | 548 } |
556 } | 549 } |
557 | 550 |
558 // Generating stubs for direct calls and stubs for call-through | 551 // Generating stubs for direct calls and stubs for call-through |
559 // of getters that happen to be functions. | 552 // of getters that happen to be functions. |
560 bool isFunctionLike = false; | 553 bool isFunctionLike = false; |
561 FunctionType functionType = null; | 554 FunctionType functionType = null; |
562 | 555 |
563 if (member.isFunction) { | 556 if (member.isFunction) { |
564 MethodElement fn = member; | 557 MethodElement fn = member; |
565 functionType = fn.type; | 558 functionType = _elementEnvironment.getFunctionType(fn); |
566 } else if (member.isGetter) { | 559 } else if (member.isGetter) { |
567 if (_options.trustTypeAnnotations) { | 560 if (_options.trustTypeAnnotations) { |
568 DartType returnType = | 561 DartType returnType = |
569 _elementEnvironment.getFunctionType(member).returnType; | 562 _elementEnvironment.getFunctionType(member).returnType; |
570 if (returnType.isFunctionType) { | 563 if (returnType.isFunctionType) { |
571 functionType = returnType; | 564 functionType = returnType; |
572 } else if (returnType.treatAsDynamic || | 565 } else if (returnType.treatAsDynamic || |
573 _types.isSubtype( | 566 _types.isSubtype( |
574 returnType, | 567 returnType, |
575 // ignore: UNNECESSARY_CAST | 568 // ignore: UNNECESSARY_CAST |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
779 if (_nativeData.isJsInteropClass(cls)) { | 772 if (_nativeData.isJsInteropClass(cls)) { |
780 typeTests.forEachProperty(_sorter, (js.Name name, js.Node code) { | 773 typeTests.forEachProperty(_sorter, (js.Name name, js.Node code) { |
781 _classes[_commonElements.jsInterceptorClass] | 774 _classes[_commonElements.jsInterceptorClass] |
782 .isChecks | 775 .isChecks |
783 .add(_buildStubMethod(name, code)); | 776 .add(_buildStubMethod(name, code)); |
784 }); | 777 }); |
785 } else { | 778 } else { |
786 for (Field field in instanceFields) { | 779 for (Field field in instanceFields) { |
787 if (field.needsCheckedSetter) { | 780 if (field.needsCheckedSetter) { |
788 assert(!field.needsUncheckedSetter); | 781 assert(!field.needsUncheckedSetter); |
789 FieldElement element = field.element; | 782 FieldEntity element = field.element; |
790 js.Expression code = _generatedCode[element]; | 783 js.Expression code = _generatedCode[element]; |
791 assert(code != null); | 784 assert(code != null); |
792 js.Name name = _namer.deriveSetterName(field.accessorName); | 785 js.Name name = _namer.deriveSetterName(field.accessorName); |
793 checkedSetters.add(_buildStubMethod(name, code, element: element)); | 786 checkedSetters.add(_buildStubMethod(name, code, element: element)); |
794 } | 787 } |
795 } | 788 } |
796 | 789 |
797 typeTests.forEachProperty(_sorter, (js.Name name, js.Node code) { | 790 typeTests.forEachProperty(_sorter, (js.Name name, js.Node code) { |
798 isChecks.add(_buildStubMethod(name, code)); | 791 isChecks.add(_buildStubMethod(name, code)); |
799 }); | 792 }); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
856 | 849 |
857 bool _methodCanBeReflected(FunctionEntity method) { | 850 bool _methodCanBeReflected(FunctionEntity method) { |
858 return _mirrorsData.isMemberAccessibleByReflection(method); | 851 return _mirrorsData.isMemberAccessibleByReflection(method); |
859 } | 852 } |
860 | 853 |
861 bool _methodCanBeApplied(FunctionEntity method) { | 854 bool _methodCanBeApplied(FunctionEntity method) { |
862 return _backendUsage.isFunctionApplyUsed && | 855 return _backendUsage.isFunctionApplyUsed && |
863 _closedWorld.getMightBePassedToApply(method); | 856 _closedWorld.getMightBePassedToApply(method); |
864 } | 857 } |
865 | 858 |
866 /* Map | List */ _computeParameterDefaultValues(FunctionSignature signature) { | 859 /* Map | List */ _computeParameterDefaultValues(FunctionEntity method) { |
867 var /* Map | List */ optionalParameterDefaultValues; | 860 var /* Map | List */ optionalParameterDefaultValues; |
868 if (signature.optionalParametersAreNamed) { | 861 ParameterStructure parameterStructure = method.parameterStructure; |
| 862 if (parameterStructure.namedParameters.isNotEmpty) { |
869 optionalParameterDefaultValues = new Map<String, ConstantValue>(); | 863 optionalParameterDefaultValues = new Map<String, ConstantValue>(); |
870 signature.forEachOptionalParameter((_parameter) { | 864 _worldBuilder.forEachParameter(method, |
871 ParameterElement parameter = _parameter; | 865 (DartType type, String name, ConstantValue defaultValue) { |
872 ConstantValue def = | 866 if (parameterStructure.namedParameters.contains(name)) { |
873 _constantHandler.getConstantValue(parameter.constant); | 867 assert(defaultValue != null); |
874 optionalParameterDefaultValues[parameter.name] = def; | 868 optionalParameterDefaultValues[name] = defaultValue; |
| 869 } |
875 }); | 870 }); |
876 } else { | 871 } else { |
877 optionalParameterDefaultValues = <ConstantValue>[]; | 872 optionalParameterDefaultValues = <ConstantValue>[]; |
878 signature.forEachOptionalParameter((_parameter) { | 873 int index = 0; |
879 ParameterElement parameter = _parameter; | 874 _worldBuilder.forEachParameter(method, |
880 ConstantValue def = | 875 (DartType type, String name, ConstantValue defaultValue) { |
881 _constantHandler.getConstantValue(parameter.constant); | 876 if (index >= parameterStructure.requiredParameters) { |
882 optionalParameterDefaultValues.add(def); | 877 assert(defaultValue != null); |
| 878 optionalParameterDefaultValues.add(defaultValue); |
| 879 } |
| 880 index++; |
883 }); | 881 }); |
884 } | 882 } |
885 return optionalParameterDefaultValues; | 883 return optionalParameterDefaultValues; |
886 } | 884 } |
887 | 885 |
888 DartMethod _buildMethod(FunctionEntity element) { | 886 DartMethod _buildMethod(FunctionEntity element) { |
889 assert(!(element is MethodElement && !element.isDeclaration)); | 887 assert(!(element is MethodElement && !element.isDeclaration)); |
890 js.Name name = _namer.methodPropertyName(element); | 888 js.Name name = _namer.methodPropertyName(element); |
891 js.Expression code = _generatedCode[element]; | 889 js.Expression code = _generatedCode[element]; |
892 | 890 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
938 js.Expression functionType; | 936 js.Expression functionType; |
939 if (canTearOff || canBeReflected) { | 937 if (canTearOff || canBeReflected) { |
940 OutputUnit outputUnit = _deferredLoadTask.outputUnitForMember(element); | 938 OutputUnit outputUnit = _deferredLoadTask.outputUnitForMember(element); |
941 functionType = _generateFunctionType(memberType, outputUnit); | 939 functionType = _generateFunctionType(memberType, outputUnit); |
942 } | 940 } |
943 | 941 |
944 int requiredParameterCount; | 942 int requiredParameterCount; |
945 var /* List | Map */ optionalParameterDefaultValues; | 943 var /* List | Map */ optionalParameterDefaultValues; |
946 if (canBeApplied || canBeReflected) { | 944 if (canBeApplied || canBeReflected) { |
947 // TODO(redemption): Handle function entities. | 945 // TODO(redemption): Handle function entities. |
948 MethodElement method = element; | 946 FunctionEntity method = element; |
949 FunctionSignature signature = method.functionSignature; | 947 ParameterStructure parameterStructure = method.parameterStructure; |
950 requiredParameterCount = signature.requiredParameterCount; | 948 requiredParameterCount = parameterStructure.requiredParameters; |
951 optionalParameterDefaultValues = | 949 optionalParameterDefaultValues = _computeParameterDefaultValues(method); |
952 _computeParameterDefaultValues(signature); | |
953 } | 950 } |
954 | 951 |
955 return new InstanceMethod(element, name, code, | 952 return new InstanceMethod(element, name, code, |
956 _generateParameterStubs(element, canTearOff), callName, | 953 _generateParameterStubs(element, canTearOff), callName, |
957 needsTearOff: canTearOff, | 954 needsTearOff: canTearOff, |
958 tearOffName: tearOffName, | 955 tearOffName: tearOffName, |
959 isClosureCallMethod: isClosureCallMethod, | 956 isClosureCallMethod: isClosureCallMethod, |
960 aliasName: aliasName, | 957 aliasName: aliasName, |
961 canBeApplied: canBeApplied, | 958 canBeApplied: canBeApplied, |
962 canBeReflected: canBeReflected, | 959 canBeReflected: canBeReflected, |
(...skipping 25 matching lines...) Expand all Loading... |
988 _worldBuilder, | 985 _worldBuilder, |
989 _closedWorld); | 986 _closedWorld); |
990 return generator.generateParameterStubs(element, canTearOff: canTearOff); | 987 return generator.generateParameterStubs(element, canTearOff: canTearOff); |
991 } | 988 } |
992 | 989 |
993 /// Builds a stub method. | 990 /// Builds a stub method. |
994 /// | 991 /// |
995 /// Stub methods may have an element that can be used for code-size | 992 /// Stub methods may have an element that can be used for code-size |
996 /// attribution. | 993 /// attribution. |
997 Method _buildStubMethod(js.Name name, js.Expression code, | 994 Method _buildStubMethod(js.Name name, js.Expression code, |
998 {MemberElement element}) { | 995 {MemberEntity element}) { |
999 return new StubMethod(name, code, element: element); | 996 return new StubMethod(name, code, element: element); |
1000 } | 997 } |
1001 | 998 |
1002 // The getInterceptor methods directly access the prototype of classes. | 999 // The getInterceptor methods directly access the prototype of classes. |
1003 // We must evaluate these classes eagerly so that the prototype is | 1000 // We must evaluate these classes eagerly so that the prototype is |
1004 // accessible. | 1001 // accessible. |
1005 void _markEagerInterceptorClasses() { | 1002 void _markEagerInterceptorClasses() { |
1006 Iterable<js.Name> names = | 1003 Iterable<js.Name> names = |
1007 _oneShotInterceptorData.specializedGetInterceptorNames; | 1004 _oneShotInterceptorData.specializedGetInterceptorNames; |
1008 for (js.Name name in names) { | 1005 for (js.Name name in names) { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1078 setterFlags += 2; | 1075 setterFlags += 2; |
1079 if (!isHolderInterceptedClass) { | 1076 if (!isHolderInterceptedClass) { |
1080 setterFlags += 1; | 1077 setterFlags += 1; |
1081 } | 1078 } |
1082 } | 1079 } |
1083 } | 1080 } |
1084 fields.add(new Field(field, name, accessorName, getterFlags, setterFlags, | 1081 fields.add(new Field(field, name, accessorName, getterFlags, setterFlags, |
1085 needsCheckedSetter)); | 1082 needsCheckedSetter)); |
1086 } | 1083 } |
1087 | 1084 |
1088 FieldVisitor visitor = new FieldVisitor(_options, _elementEnvironment, | 1085 FieldVisitor visitor = new FieldVisitor( |
1089 _worldBuilder, _nativeData, _mirrorsData, _namer, _closedWorld); | 1086 _options, |
| 1087 _elementEnvironment, |
| 1088 _commonElements, |
| 1089 _worldBuilder, |
| 1090 _nativeData, |
| 1091 _mirrorsData, |
| 1092 _namer, |
| 1093 _closedWorld); |
1090 visitor.visitFields(visitField, | 1094 visitor.visitFields(visitField, |
1091 visitStatics: visitStatics, library: library, cls: cls); | 1095 visitStatics: visitStatics, library: library, cls: cls); |
1092 | 1096 |
1093 return fields; | 1097 return fields; |
1094 } | 1098 } |
1095 | 1099 |
1096 Iterable<StaticStubMethod> _generateOneShotInterceptors() { | 1100 Iterable<StaticStubMethod> _generateOneShotInterceptors() { |
1097 InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator( | 1101 InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator( |
1098 _options, | 1102 _options, |
1099 _commonElements, | 1103 _commonElements, |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1145 DartType type = _elementEnvironment.getFunctionType(element); | 1149 DartType type = _elementEnvironment.getFunctionType(element); |
1146 if (needsTearOff || canBeReflected) { | 1150 if (needsTearOff || canBeReflected) { |
1147 OutputUnit outputUnit = _deferredLoadTask.outputUnitForMember(element); | 1151 OutputUnit outputUnit = _deferredLoadTask.outputUnitForMember(element); |
1148 functionType = _generateFunctionType(type, outputUnit); | 1152 functionType = _generateFunctionType(type, outputUnit); |
1149 } | 1153 } |
1150 | 1154 |
1151 int requiredParameterCount; | 1155 int requiredParameterCount; |
1152 var /* List | Map */ optionalParameterDefaultValues; | 1156 var /* List | Map */ optionalParameterDefaultValues; |
1153 if (canBeApplied || canBeReflected) { | 1157 if (canBeApplied || canBeReflected) { |
1154 // TODO(redemption): Support entities; | 1158 // TODO(redemption): Support entities; |
1155 MethodElement method = element; | 1159 FunctionEntity method = element; |
1156 FunctionSignature signature = method.functionSignature; | 1160 ParameterStructure parameterStructure = method.parameterStructure; |
1157 requiredParameterCount = signature.requiredParameterCount; | 1161 requiredParameterCount = parameterStructure.requiredParameters; |
1158 optionalParameterDefaultValues = | 1162 optionalParameterDefaultValues = _computeParameterDefaultValues(method); |
1159 _computeParameterDefaultValues(signature); | |
1160 } | 1163 } |
1161 | 1164 |
1162 // TODO(floitsch): we shouldn't update the registry in the middle of | 1165 // TODO(floitsch): we shouldn't update the registry in the middle of |
1163 // building a static method. | 1166 // building a static method. |
1164 return new StaticDartMethod(element, name, _registry.registerHolder(holder), | 1167 return new StaticDartMethod(element, name, _registry.registerHolder(holder), |
1165 code, _generateParameterStubs(element, needsTearOff), callName, | 1168 code, _generateParameterStubs(element, needsTearOff), callName, |
1166 needsTearOff: needsTearOff, | 1169 needsTearOff: needsTearOff, |
1167 tearOffName: tearOffName, | 1170 tearOffName: tearOffName, |
1168 canBeApplied: canBeApplied, | 1171 canBeApplied: canBeApplied, |
1169 canBeReflected: canBeReflected, | 1172 canBeReflected: canBeReflected, |
(...skipping 16 matching lines...) Expand all Loading... |
1186 Constant constant = new Constant(name, holder, constantValue); | 1189 Constant constant = new Constant(name, holder, constantValue); |
1187 _constants[constantValue] = constant; | 1190 _constants[constantValue] = constant; |
1188 } | 1191 } |
1189 } | 1192 } |
1190 | 1193 |
1191 Holder _registerStaticStateHolder() { | 1194 Holder _registerStaticStateHolder() { |
1192 return _registry.registerHolder(_namer.staticStateHolder, | 1195 return _registry.registerHolder(_namer.staticStateHolder, |
1193 isStaticStateHolder: true); | 1196 isStaticStateHolder: true); |
1194 } | 1197 } |
1195 } | 1198 } |
OLD | NEW |