Disable non-deterministic interning / memory optimizations when Skycache serialization is needed.

This includes `NestedSet` and `StarlarkCustomCommandLine`'s inner classes, and switching `Recipe`/`VectorArg` to use `AutoCodec.Instantiator` with the interning conditional instead.

PiperOrigin-RevId: 964101294
Change-Id: I46d6be65d81cdc181e6d12dad2a7a347136b0f27
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkCustomCommandLine.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkCustomCommandLine.java
index 2d6f465..5ca5e12 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkCustomCommandLine.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkCustomCommandLine.java
@@ -62,6 +62,7 @@
 import java.util.NoSuchElementException;
 import java.util.Objects;
 import java.util.UUID;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Consumer;
 import javax.annotation.Nullable;
 import net.starlark.java.eval.EvalException;
@@ -131,10 +132,18 @@
   private static final Joiner LINE_JOINER = Joiner.on("\n").skipNulls();
   private static final Joiner FIELD_JOINER = Joiner.on(": ").skipNulls();
 
+  private static final AtomicBoolean interningEnabled = new AtomicBoolean(true);
+
+  /** Enables or disables interning of {@link Recipe} and {@link VectorArg} instances. */
+  public static void setInterningEnabled(boolean enabled) {
+    interningEnabled.set(enabled);
+  }
+
   // Used to distinguish command line arguments that are potentially subject to special default
   // stringification (such as Artifacts when path mapped or Labels when not main repo labels) from
   // strings that happen to be identical to their string representations.
-  private enum StringificationType {
+  @VisibleForSerialization
+  enum StringificationType {
     DEFAULT,
     FILE,
     LABEL
@@ -185,7 +194,8 @@
     @Nullable private final String formatJoined;
     @Nullable private final String terminateWith;
 
-    private VectorArg(
+    @VisibleForSerialization
+    VectorArg(
         boolean isNestedSet,
         boolean expandDirectories,
         boolean uniquify,
@@ -220,10 +230,43 @@
       this.terminateWith = terminateWith;
     }
 
-    @VisibleForSerialization
-    @AutoCodec.Interner
-    static VectorArg intern(VectorArg vectorArg) {
-      return interner.intern(vectorArg);
+    @AutoCodec.Instantiator
+    static VectorArg create(
+        boolean isNestedSet,
+        boolean expandDirectories,
+        boolean uniquify,
+        boolean omitIfEmpty,
+        boolean hasSingleArg,
+        boolean hasNonGlobalMapEach,
+        StringificationType stringificationType,
+        @Nullable Location location,
+        @Nullable String argName,
+        @Nullable StarlarkCallable mapEach,
+        @Nullable StarlarkSemantics starlarkSemantics,
+        @Nullable String formatEach,
+        @Nullable String beforeEach,
+        @Nullable String joinWith,
+        @Nullable String formatJoined,
+        @Nullable String terminateWith) {
+      VectorArg vectorArg =
+          new VectorArg(
+              isNestedSet,
+              expandDirectories,
+              uniquify,
+              omitIfEmpty,
+              hasSingleArg,
+              hasNonGlobalMapEach,
+              stringificationType,
+              location,
+              argName,
+              mapEach,
+              starlarkSemantics,
+              formatEach,
+              beforeEach,
+              joinWith,
+              formatJoined,
+              terminateWith);
+      return interningEnabled.get() ? interner.intern(vectorArg) : vectorArg;
     }
 
     private static void push(
@@ -244,24 +287,23 @@
 
       boolean hasNonGlobalMapEach = arg.mapEach instanceof StarlarkFunction fn && !fn.isGlobal();
       recipe.add(
-          VectorArg.intern(
-              new VectorArg(
-                  arg.nestedSet != null,
-                  arg.expandDirectories,
-                  arg.uniquify,
-                  arg.omitIfEmpty,
-                  arg.nestedSet == null && arg.list.size() == 1,
-                  hasNonGlobalMapEach,
-                  arg.nestedSetStringificationType,
-                  arg.mapEach != null ? arg.location : null,
-                  arg.argName,
-                  hasNonGlobalMapEach ? null : arg.mapEach,
-                  arg.mapEach != null ? starlarkSemantics : null,
-                  arg.formatEach,
-                  arg.beforeEach,
-                  arg.joinWith,
-                  arg.formatJoined,
-                  arg.terminateWith)));
+          VectorArg.create(
+              arg.nestedSet != null,
+              arg.expandDirectories,
+              arg.uniquify,
+              arg.omitIfEmpty,
+              arg.nestedSet == null && arg.list.size() == 1,
+              hasNonGlobalMapEach,
+              arg.nestedSetStringificationType,
+              arg.mapEach != null ? arg.location : null,
+              arg.argName,
+              hasNonGlobalMapEach ? null : arg.mapEach,
+              arg.mapEach != null ? starlarkSemantics : null,
+              arg.formatEach,
+              arg.beforeEach,
+              arg.joinWith,
+              arg.formatJoined,
+              arg.terminateWith));
 
       if (hasNonGlobalMapEach) {
         values.add(arg.mapEach);
@@ -773,19 +815,20 @@
     final Object[] elements;
     private final int hashCode;
 
+    @VisibleForSerialization
     Recipe(Object[] elements) {
       this.elements = elements;
       this.hashCode = Arrays.hashCode(elements);
     }
 
-    @VisibleForSerialization
-    @AutoCodec.Interner
     static Recipe intern(Recipe recipe) {
       return interner.intern(recipe);
     }
 
+    @AutoCodec.Instantiator
     static Recipe create(Object[] elements) {
-      return intern(new Recipe(elements));
+      Recipe recipe = new Recipe(elements);
+      return interningEnabled.get() ? interner.intern(recipe) : recipe;
     }
 
     @Override