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