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

Side by Side Diff: pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart

Issue 2847343002: Add support for profile-based startup optimizations. (Closed)
Patch Set: Address comments. Created 3 years, 7 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) 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';
8 import 'dart:convert' show JSON;
9
7 import '../../closure.dart' show ClosureTask, ClosureFieldElement; 10 import '../../closure.dart' show ClosureTask, ClosureFieldElement;
8 import '../../common.dart'; 11 import '../../common.dart';
9 import '../../common/names.dart' show Names, Selectors; 12 import '../../common/names.dart' show Names, Selectors;
10 import '../../constants/values.dart' 13 import '../../constants/values.dart'
11 show ConstantValue, InterceptorConstantValue; 14 show ConstantValue, InterceptorConstantValue;
12 import '../../common_elements.dart' show CommonElements, ElementEnvironment; 15 import '../../common_elements.dart' show CommonElements, ElementEnvironment;
13 import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit; 16 import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit;
14 import '../../elements/elements.dart' 17 import '../../elements/elements.dart'
15 show 18 show
16 ClassElement, 19 ClassElement,
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 import '../sorter.dart'; 71 import '../sorter.dart';
69 72
70 part 'collector.dart'; 73 part 'collector.dart';
71 part 'field_visitor.dart'; 74 part 'field_visitor.dart';
72 part 'registry.dart'; 75 part 'registry.dart';
73 76
74 /// Builds a self-contained representation of the program that can then be 77 /// Builds a self-contained representation of the program that can then be
75 /// emitted more easily by the individual emitters. 78 /// emitted more easily by the individual emitters.
76 class ProgramBuilder { 79 class ProgramBuilder {
77 final CompilerOptions _options; 80 final CompilerOptions _options;
81 final DiagnosticReporter _reporter;
78 final ElementEnvironment _elementEnvironment; 82 final ElementEnvironment _elementEnvironment;
79 final CommonElements _commonElements; 83 final CommonElements _commonElements;
80 final DartTypes _types; 84 final DartTypes _types;
81 final DeferredLoadTask _deferredLoadTask; 85 final DeferredLoadTask _deferredLoadTask;
82 final ClosureTask _closureToClassMapper; 86 final ClosureTask _closureToClassMapper;
83 final CodegenWorldBuilder _worldBuilder; 87 final CodegenWorldBuilder _worldBuilder;
84 final NativeCodegenEnqueuer _nativeCodegenEnqueuer; 88 final NativeCodegenEnqueuer _nativeCodegenEnqueuer;
85 final BackendUsage _backendUsage; 89 final BackendUsage _backendUsage;
86 final JavaScriptConstantCompiler _constantHandler; 90 final JavaScriptConstantCompiler _constantHandler;
87 final NativeData _nativeData; 91 final NativeData _nativeData;
(...skipping 22 matching lines...) Expand all
110 final Registry _registry; 114 final Registry _registry;
111 115
112 final FunctionEntity _mainFunction; 116 final FunctionEntity _mainFunction;
113 final bool _isMockCompilation; 117 final bool _isMockCompilation;
114 118
115 /// True if the program should store function types in the metadata. 119 /// True if the program should store function types in the metadata.
116 bool _storeFunctionTypesInMetadata = false; 120 bool _storeFunctionTypesInMetadata = false;
117 121
118 ProgramBuilder( 122 ProgramBuilder(
119 this._options, 123 this._options,
124 this._reporter,
120 this._elementEnvironment, 125 this._elementEnvironment,
121 this._commonElements, 126 this._commonElements,
122 this._types, 127 this._types,
123 this._deferredLoadTask, 128 this._deferredLoadTask,
124 this._closureToClassMapper, 129 this._closureToClassMapper,
125 this._worldBuilder, 130 this._worldBuilder,
126 this._nativeCodegenEnqueuer, 131 this._nativeCodegenEnqueuer,
127 this._backendUsage, 132 this._backendUsage,
128 this._constantHandler, 133 this._constantHandler,
129 this._nativeData, 134 this._nativeData,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 182
178 /// Mapping from names to strings. 183 /// Mapping from names to strings.
179 /// 184 ///
180 /// This mapping is used to support `const Symbol` expressions. 185 /// This mapping is used to support `const Symbol` expressions.
181 /// 186 ///
182 /// This map is filled when building classes. 187 /// This map is filled when building classes.
183 final Map<js.Name, String> _symbolsMap = <js.Name, String>{}; 188 final Map<js.Name, String> _symbolsMap = <js.Name, String>{};
184 189
185 Set<Class> _unneededNativeClasses; 190 Set<Class> _unneededNativeClasses;
186 191
192 /// Classes that have been allocated during a profile run.
193 ///
194 /// These classes should not be soft-deferred.
195 ///
196 /// Also contains classes that are not tracked by the profile run (like
197 /// interceptors, ...).
198 Set<ClassElement> _notSoftDeferred;
199
187 Program buildProgram({bool storeFunctionTypesInMetadata: false}) { 200 Program buildProgram({bool storeFunctionTypesInMetadata: false}) {
188 collector.collect(); 201 collector.collect();
202 _initializeSoftDeferredMap();
189 203
190 this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata; 204 this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata;
191 // Note: In rare cases (mostly tests) output units can be empty. This 205 // Note: In rare cases (mostly tests) output units can be empty. This
192 // happens when the deferred code is dead-code eliminated but we still need 206 // happens when the deferred code is dead-code eliminated but we still need
193 // to check that the library has been loaded. 207 // to check that the library has been loaded.
194 _deferredLoadTask.allOutputUnits.forEach(_registry.registerOutputUnit); 208 _deferredLoadTask.allOutputUnits.forEach(_registry.registerOutputUnit);
195 collector.outputClassLists.forEach(_registry.registerClasses); 209 collector.outputClassLists.forEach(_registry.registerClasses);
196 collector.outputStaticLists.forEach(_registry.registerMembers); 210 collector.outputStaticLists.forEach(_registry.registerMembers);
197 collector.outputConstantLists.forEach(_registerConstants); 211 collector.outputConstantLists.forEach(_registerConstants);
198 collector.outputStaticNonFinalFieldLists.forEach(_registry.registerMembers); 212 collector.outputStaticNonFinalFieldLists.forEach(_registry.registerMembers);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 List<js.TokenFinalizer> finalizers = [_task.metadataCollector]; 273 List<js.TokenFinalizer> finalizers = [_task.metadataCollector];
260 if (_namer is js.TokenFinalizer) { 274 if (_namer is js.TokenFinalizer) {
261 var namingFinalizer = _namer; 275 var namingFinalizer = _namer;
262 finalizers.add(namingFinalizer as js.TokenFinalizer); 276 finalizers.add(namingFinalizer as js.TokenFinalizer);
263 } 277 }
264 278
265 return new Program(fragments, holders, _buildLoadMap(), _symbolsMap, 279 return new Program(fragments, holders, _buildLoadMap(), _symbolsMap,
266 _buildTypeToInterceptorMap(), _task.metadataCollector, finalizers, 280 _buildTypeToInterceptorMap(), _task.metadataCollector, finalizers,
267 needsNativeSupport: needsNativeSupport, 281 needsNativeSupport: needsNativeSupport,
268 outputContainsConstantList: collector.outputContainsConstantList, 282 outputContainsConstantList: collector.outputContainsConstantList,
269 hasIsolateSupport: _backendUsage.isIsolateInUse); 283 hasIsolateSupport: _backendUsage.isIsolateInUse,
284 hasSoftDeferredClasses: _notSoftDeferred != null);
270 } 285 }
271 286
272 void _markEagerClasses() { 287 void _markEagerClasses() {
273 _markEagerInterceptorClasses(); 288 _markEagerInterceptorClasses();
274 } 289 }
275 290
291 void _initializeSoftDeferredMap() {
292 var allocatedClassesPath = _options.experimentalAllocationsPath;
293 if (allocatedClassesPath != null) {
294 // TODO(29574): the following blacklist is ad-hoc and potentially
295 // incomplete. We need to mark all classes as black listed, that are
296 // used without code going through the class' constructor.
297 var blackList = [
298 'dart:_interceptors',
299 'dart:html',
300 'dart:typed_data_implementation',
301 'dart:_native_typed_data'
302 ].toSet();
303
304 // TODO(29574): the compiler should not just use dart:io to get the
305 // contents of a file.
306 File file = new File(allocatedClassesPath);
307
308 // TODO(29574): are the following checks necessary?
309 // To make compilation in build-systems easier, we ignore non-existing
310 // or empty profiles.
311 if (!file.existsSync()) {
312 _reporter.log("Profile file does not exist: $allocatedClassesPath");
313 return;
314 }
315 if (file.lengthSync() == 0) {
316 _reporter.log("Profile information (allocated classes) is empty.");
317 return;
318 }
319
320 String data = new File(allocatedClassesPath).readAsStringSync();
321 Set<String> allocatedClassesKeys = JSON.decode(data).keys.toSet();
322 Set<ClassElement> allocatedClasses = new Set<ClassElement>();
323
324 // Collects all super and mixin classes of a class.
325 void collect(ClassElement element) {
326 allocatedClasses.add(element);
327 if (element.isMixinApplication) {
328 collect(computeMixinClass(element));
329 }
330 if (element.superclass != null) {
331 collect(element.superclass);
332 }
333 }
334
335 // For every known class, see if it was allocated in the profile. If yes,
336 // collect its dependencies (supers and mixins) and mark them as
337 // not-soft-deferrable.
338 collector.outputClassLists.forEach((_, List<ClassElement> elements) {
339 for (ClassElement element in elements) {
340 // TODO(29574): share the encoding of the element with the code
341 // that emits the profile-run.
342 var key = "${element.library.canonicalUri}:${element.name}";
343 if (allocatedClassesKeys.contains(key) ||
344 _nativeData.isJsInteropClass(element) ||
345 blackList.contains(element.library.canonicalUri.toString())) {
346 collect(element);
347 }
348 }
349 });
350 _notSoftDeferred = allocatedClasses;
351 }
352 }
353
276 /// Builds a map from loadId to outputs-to-load. 354 /// Builds a map from loadId to outputs-to-load.
277 Map<String, List<Fragment>> _buildLoadMap() { 355 Map<String, List<Fragment>> _buildLoadMap() {
278 Map<String, List<Fragment>> loadMap = <String, List<Fragment>>{}; 356 Map<String, List<Fragment>> loadMap = <String, List<Fragment>>{};
279 _deferredLoadTask.hunksToLoad 357 _deferredLoadTask.hunksToLoad
280 .forEach((String loadId, List<OutputUnit> outputUnits) { 358 .forEach((String loadId, List<OutputUnit> outputUnits) {
281 loadMap[loadId] = outputUnits 359 loadMap[loadId] = outputUnits
282 .map((OutputUnit unit) => _outputs[unit]) 360 .map((OutputUnit unit) => _outputs[unit])
283 .toList(growable: false); 361 .toList(growable: false);
284 }); 362 });
285 return loadMap; 363 return loadMap;
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
577 .toList(growable: false); 655 .toList(growable: false);
578 656
579 bool visitStatics = true; 657 bool visitStatics = true;
580 List<Field> staticFieldsForReflection = 658 List<Field> staticFieldsForReflection =
581 _buildFields(library, visitStatics: visitStatics); 659 _buildFields(library, visitStatics: visitStatics);
582 660
583 return new Library( 661 return new Library(
584 library, uri, statics, classes, staticFieldsForReflection); 662 library, uri, statics, classes, staticFieldsForReflection);
585 } 663 }
586 664
665 bool _isSoftDeferred(ClassElement element) {
666 return _notSoftDeferred != null && !_notSoftDeferred.contains(element);
667 }
668
587 Class _buildClass(ClassElement element) { 669 Class _buildClass(ClassElement element) {
588 bool onlyForRti = collector.classesOnlyNeededForRti.contains(element); 670 bool onlyForRti = collector.classesOnlyNeededForRti.contains(element);
589 bool hasRtiField = _rtiNeed.classNeedsRtiField(element); 671 bool hasRtiField = _rtiNeed.classNeedsRtiField(element);
590 if (_nativeData.isJsInteropClass(element)) { 672 if (_nativeData.isJsInteropClass(element)) {
591 // TODO(jacobr): check whether the class has any active static fields 673 // TODO(jacobr): check whether the class has any active static fields
592 // if it does not we can suppress it completely. 674 // if it does not we can suppress it completely.
593 onlyForRti = true; 675 onlyForRti = true;
594 } 676 }
595 bool isClosureBaseClass = element == _commonElements.closureClass; 677 bool isClosureBaseClass = element == _commonElements.closureClass;
596 678
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 staticFieldsForReflection, 827 staticFieldsForReflection,
746 callStubs, 828 callStubs,
747 noSuchMethodStubs, 829 noSuchMethodStubs,
748 checkedSetters, 830 checkedSetters,
749 isChecks, 831 isChecks,
750 typeTests.functionTypeIndex, 832 typeTests.functionTypeIndex,
751 isDirectlyInstantiated: isInstantiated, 833 isDirectlyInstantiated: isInstantiated,
752 hasRtiField: hasRtiField, 834 hasRtiField: hasRtiField,
753 onlyForRti: onlyForRti, 835 onlyForRti: onlyForRti,
754 isNative: _nativeData.isNativeClass(element), 836 isNative: _nativeData.isNativeClass(element),
755 isClosureBaseClass: isClosureBaseClass); 837 isClosureBaseClass: isClosureBaseClass,
838 isSoftDeferred: _isSoftDeferred(element));
756 } 839 }
757 _classes[element] = result; 840 _classes[element] = result;
758 return result; 841 return result;
759 } 842 }
760 843
761 bool _methodNeedsStubs(FunctionElement method) { 844 bool _methodNeedsStubs(FunctionElement method) {
762 return !method.functionSignature.optionalParameters.isEmpty; 845 return !method.functionSignature.optionalParameters.isEmpty;
763 } 846 }
764 847
765 bool _methodCanBeReflected(MethodElement method) { 848 bool _methodCanBeReflected(MethodElement method) {
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
1102 Constant constant = new Constant(name, holder, constantValue); 1185 Constant constant = new Constant(name, holder, constantValue);
1103 _constants[constantValue] = constant; 1186 _constants[constantValue] = constant;
1104 } 1187 }
1105 } 1188 }
1106 1189
1107 Holder _registerStaticStateHolder() { 1190 Holder _registerStaticStateHolder() {
1108 return _registry.registerHolder(_namer.staticStateHolder, 1191 return _registry.registerHolder(_namer.staticStateHolder,
1109 isStaticStateHolder: true); 1192 isStaticStateHolder: true);
1110 } 1193 }
1111 } 1194 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/model.dart ('k') | pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698