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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index d27eca3e384c64cd6d65620cdfc3a70fcd3d2bf7..9ecf99ae97c271b3acf1501a440b48670ebb8f1d 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -4,6 +4,9 @@
library dart2js.js_emitter.program_builder;
+import 'dart:io';
+import 'dart:convert' show JSON;
+
import '../../closure.dart' show ClosureTask, ClosureFieldElement;
import '../../common.dart';
import '../../common/names.dart' show Names, Selectors;
@@ -75,6 +78,7 @@ part 'registry.dart';
/// emitted more easily by the individual emitters.
class ProgramBuilder {
final CompilerOptions _options;
+ final DiagnosticReporter _reporter;
final ElementEnvironment _elementEnvironment;
final CommonElements _commonElements;
final DartTypes _types;
@@ -117,6 +121,7 @@ class ProgramBuilder {
ProgramBuilder(
this._options,
+ this._reporter,
this._elementEnvironment,
this._commonElements,
this._types,
@@ -184,8 +189,17 @@ class ProgramBuilder {
Set<Class> _unneededNativeClasses;
+ /// Classes that have been allocated during a profile run.
+ ///
+ /// These classes should not be soft-deferred.
+ ///
+ /// Also contains classes that are not tracked by the profile run (like
+ /// interceptors, ...).
+ Set<ClassElement> _notSoftDeferred;
+
Program buildProgram({bool storeFunctionTypesInMetadata: false}) {
collector.collect();
+ _initializeSoftDeferredMap();
this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata;
// Note: In rare cases (mostly tests) output units can be empty. This
@@ -266,13 +280,77 @@ class ProgramBuilder {
_buildTypeToInterceptorMap(), _task.metadataCollector, finalizers,
needsNativeSupport: needsNativeSupport,
outputContainsConstantList: collector.outputContainsConstantList,
- hasIsolateSupport: _backendUsage.isIsolateInUse);
+ hasIsolateSupport: _backendUsage.isIsolateInUse,
+ hasSoftDeferredClasses: _notSoftDeferred != null);
}
void _markEagerClasses() {
_markEagerInterceptorClasses();
}
+ void _initializeSoftDeferredMap() {
+ var allocatedClassesPath = _options.experimentalAllocationsPath;
+ if (allocatedClassesPath != null) {
+ // TODO(29574): the following blacklist is ad-hoc and potentially
+ // incomplete. We need to mark all classes as black listed, that are
+ // used without code going through the class' constructor.
+ var blackList = [
+ 'dart:_interceptors',
+ 'dart:html',
+ 'dart:typed_data_implementation',
+ 'dart:_native_typed_data'
+ ].toSet();
+
+ // TODO(29574): the compiler should not just use dart:io to get the
+ // contents of a file.
+ File file = new File(allocatedClassesPath);
+
+ // TODO(29574): are the following checks necessary?
+ // To make compilation in build-systems easier, we ignore non-existing
+ // or empty profiles.
+ if (!file.existsSync()) {
+ _reporter.log("Profile file does not exist: $allocatedClassesPath");
+ return;
+ }
+ if (file.lengthSync() == 0) {
+ _reporter.log("Profile information (allocated classes) is empty.");
+ return;
+ }
+
+ String data = new File(allocatedClassesPath).readAsStringSync();
+ Set<String> allocatedClassesKeys = JSON.decode(data).keys.toSet();
+ Set<ClassElement> allocatedClasses = new Set<ClassElement>();
+
+ // Collects all super and mixin classes of a class.
+ void collect(ClassElement element) {
+ allocatedClasses.add(element);
+ if (element.isMixinApplication) {
+ collect(computeMixinClass(element));
+ }
+ if (element.superclass != null) {
+ collect(element.superclass);
+ }
+ }
+
+ // For every known class, see if it was allocated in the profile. If yes,
+ // collect its dependencies (supers and mixins) and mark them as
+ // not-soft-deferrable.
+ collector.outputClassLists.forEach((_, List<ClassElement> elements) {
+ for (ClassElement element in elements) {
+ // TODO(29574): share the encoding of the element with the code
+ // that emits the profile-run.
+ var key = "${element.library.canonicalUri}:${element.name}";
+ if (allocatedClassesKeys.contains(key) ||
+ _nativeData.isJsInteropClass(element) ||
+ blackList.contains(element.library.canonicalUri.toString())) {
+ collect(element);
+ }
+ }
+ });
+ _notSoftDeferred = allocatedClasses;
+ }
+ }
+
/// Builds a map from loadId to outputs-to-load.
Map<String, List<Fragment>> _buildLoadMap() {
Map<String, List<Fragment>> loadMap = <String, List<Fragment>>{};
@@ -584,6 +662,10 @@ class ProgramBuilder {
library, uri, statics, classes, staticFieldsForReflection);
}
+ bool _isSoftDeferred(ClassElement element) {
+ return _notSoftDeferred != null && !_notSoftDeferred.contains(element);
+ }
+
Class _buildClass(ClassElement element) {
bool onlyForRti = collector.classesOnlyNeededForRti.contains(element);
bool hasRtiField = _rtiNeed.classNeedsRtiField(element);
@@ -752,7 +834,8 @@ class ProgramBuilder {
hasRtiField: hasRtiField,
onlyForRti: onlyForRti,
isNative: _nativeData.isNativeClass(element),
- isClosureBaseClass: isClosureBaseClass);
+ isClosureBaseClass: isClosureBaseClass,
+ isSoftDeferred: _isSoftDeferred(element));
}
_classes[element] = result;
return result;
« 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