[CFE] Allow enabling internal experiments via environment

Change-Id: Icec66e1087ccd99abd7513a612479b2bdae989f0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/137963
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 298bd28..5fd3fb8 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -88,6 +88,12 @@
 
 import 'util/error_reporter_file_copier.dart' show saveAsGzip;
 
+import 'util/experiment_environment_getter.dart'
+    show
+        getExperimentEnvironment,
+        enableExperimentKeyInvalidation,
+        enableExperimentKeyInvalidationSerialization;
+
 import 'util/textual_outline.dart' show textualOutline;
 
 import 'fasta_codes.dart'
@@ -143,6 +149,7 @@
   List<Component> modulesToLoad;
   IncrementalSerializer incrementalSerializer;
   bool useExperimentalInvalidation = false;
+  bool useExperimentalInvalidationSerialization = false;
 
   static final Uri debugExprUri =
       new Uri(scheme: "org-dartlang-debug", path: "synthetic_debug_expression");
@@ -156,7 +163,9 @@
       : ticker = context.options.ticker,
         initializeFromDillUri = null,
         this.outlineOnly = outlineOnly ?? false,
-        this.incrementalSerializer = incrementalSerializer;
+        this.incrementalSerializer = incrementalSerializer {
+    enableExperimentsBasedOnEnvironment();
+  }
 
   IncrementalCompiler(this.context,
       [this.initializeFromDillUri,
@@ -165,7 +174,23 @@
       : ticker = context.options.ticker,
         componentToInitializeFrom = null,
         this.outlineOnly = outlineOnly ?? false,
-        this.incrementalSerializer = incrementalSerializer;
+        this.incrementalSerializer = incrementalSerializer {
+    enableExperimentsBasedOnEnvironment();
+  }
+
+  void enableExperimentsBasedOnEnvironment() {
+    // Note that these are all experimental. Use at your own risk.
+    Set<String> enabledExperiments = getExperimentEnvironment();
+    if (enabledExperiments.contains(enableExperimentKeyInvalidation)) {
+      useExperimentalInvalidation = true;
+    }
+    if (useExperimentalInvalidation) {
+      if (enabledExperiments
+          .contains(enableExperimentKeyInvalidationSerialization)) {
+        useExperimentalInvalidationSerialization = true;
+      }
+    }
+  }
 
   @override
   Future<Component> computeDelta(
@@ -435,13 +460,15 @@
       List<Library> compiledLibraries,
       Map<Uri, Source> uriToSource) {
     if (experimentalInvalidation != null) {
-      // Make sure "compiledLibraries" contains what it would have, had we not
-      // only re-done the bodies, but invalidated everything.
-      experimentalInvalidation.originalNotReusedLibraries
-          .removeAll(experimentalInvalidation.rebuildBodies);
-      for (LibraryBuilder builder
-          in experimentalInvalidation.originalNotReusedLibraries) {
-        compiledLibraries.add(builder.library);
+      if (!useExperimentalInvalidationSerialization) {
+        // Make sure "compiledLibraries" contains what it would have, had we not
+        // only re-done the bodies, but invalidated everything.
+        experimentalInvalidation.originalNotReusedLibraries
+            .removeAll(experimentalInvalidation.rebuildBodies);
+        for (LibraryBuilder builder
+            in experimentalInvalidation.originalNotReusedLibraries) {
+          compiledLibraries.add(builder.library);
+        }
       }
 
       // uriToSources are created in the outline stage which we skipped for
diff --git a/pkg/front_end/lib/src/fasta/util/experiment_environment_getter.dart b/pkg/front_end/lib/src/fasta/util/experiment_environment_getter.dart
new file mode 100644
index 0000000..9b2c87a
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/util/experiment_environment_getter.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io' show Platform;
+
+const String enableExperimentKeyInvalidation =
+    "DART_CFE_ENABLE_EXPERIMENTAL_INVALIDATION";
+
+const String enableExperimentKeyInvalidationSerialization =
+    "DART_CFE_ENABLE_EXPERIMENTAL_INVALIDATION_SERIALIZATION";
+
+const Set<String> _known = {
+  enableExperimentKeyInvalidation,
+  enableExperimentKeyInvalidationSerialization,
+};
+
+Set<String> getExperimentEnvironment() {
+  Set<String> enabled = {};
+  Map<String, String> environment = Platform.environment;
+  for (String experiment in _known) {
+    if (environment[experiment] == "true") {
+      enabled.add(experiment);
+    }
+  }
+  return enabled;
+}
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index bd57121..0e11445 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -862,6 +862,7 @@
 rhs
 ri
 rightmost
+risk
 rn
 rnystrom
 role