SourceArtifacts are interned on deserialization using an ArtifactFactory.  This should reduce memory consumption in NestedSet deserialization, which currently does not recycle Artifact instances.

PiperOrigin-RevId: 194083901
diff --git a/src/test/java/com/google/devtools/build/lib/BUILD b/src/test/java/com/google/devtools/build/lib/BUILD
index 03860d2..91c8a1d 100644
--- a/src/test/java/com/google/devtools/build/lib/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/BUILD
@@ -674,6 +674,7 @@
         "//src/main/java/com/google/devtools/build/lib/actions",
         "//src/main/java/com/google/devtools/build/lib/skyframe/serialization",
         "//src/main/java/com/google/devtools/build/lib/skyframe/serialization/testutils",
+        "//src/main/java/com/google/devtools/build/lib/skyframe/serialization/testutils:depsutils",
         "//src/main/java/com/google/devtools/build/lib/vfs",
         "//src/main/protobuf:extra_actions_base_java_proto",
         "//third_party:jsr305",
@@ -795,6 +796,7 @@
         "//src/main/java/com/google/devtools/build/lib/rules/cpp",
         "//src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec",
         "//src/main/java/com/google/devtools/build/lib/skyframe/serialization/testutils",
+        "//src/main/java/com/google/devtools/build/lib/skyframe/serialization/testutils:depsutils",
         "//src/main/java/com/google/devtools/build/lib/vfs",
         "//src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs",
         "//src/main/java/com/google/devtools/build/skyframe",
diff --git a/src/test/java/com/google/devtools/build/lib/actions/ArtifactTest.java b/src/test/java/com/google/devtools/build/lib/actions/ArtifactTest.java
index ccec350..abbd347 100644
--- a/src/test/java/com/google/devtools/build/lib/actions/ArtifactTest.java
+++ b/src/test/java/com/google/devtools/build/lib/actions/ArtifactTest.java
@@ -17,14 +17,19 @@
 import static org.junit.Assert.fail;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.devtools.build.lib.actions.ActionAnalysisMetadata.MiddlemanType;
+import com.google.devtools.build.lib.actions.Artifact.SourceArtifact;
+import com.google.devtools.build.lib.actions.ArtifactResolver.ArtifactResolverSupplier;
 import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
 import com.google.devtools.build.lib.actions.util.LabelArtifactOwner;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.rules.cpp.CppFileTypes;
 import com.google.devtools.build.lib.rules.java.JavaSemantics;
+import com.google.devtools.build.lib.skyframe.serialization.AutoRegistry;
+import com.google.devtools.build.lib.skyframe.serialization.ObjectCodecs;
 import com.google.devtools.build.lib.skyframe.serialization.testutils.SerializationTester;
 import com.google.devtools.build.lib.testutil.MoreAsserts;
 import com.google.devtools.build.lib.testutil.Scratch;
@@ -320,6 +325,43 @@
   }
 
   @Test
+  public void testCodecRecyclesSourceArtifactInstances() throws Exception {
+    Root root = Root.fromPath(scratch.dir("/"));
+    ArtifactRoot artifactRoot = ArtifactRoot.asSourceRoot(root);
+    ArtifactFactory artifactFactory = new ArtifactFactory(execDir, "blaze-out");
+    artifactFactory.setSourceArtifactRoots(ImmutableMap.of(root, artifactRoot));
+    ArtifactResolverSupplier artifactResolverSupplierForTest = () -> artifactFactory;
+
+    OutputBaseSupplier outputBaseSupplier = () -> scratch.getFileSystem().getPath("/");
+    ObjectCodecs objectCodecs =
+        new ObjectCodecs(
+            AutoRegistry.get()
+                .getBuilder()
+                .addReferenceConstant(scratch.getFileSystem())
+                .setAllowDefaultCodec(true)
+                .build(),
+            ImmutableMap.of(
+                FileSystem.class, scratch.getFileSystem(),
+                OutputBaseSupplier.class, outputBaseSupplier,
+                ArtifactResolverSupplier.class, artifactResolverSupplierForTest));
+
+    PathFragment pathFragment = PathFragment.create("src/foo.cc");
+    ArtifactOwner owner = new LabelArtifactOwner(Label.parseAbsoluteUnchecked("//foo:bar"));
+    SourceArtifact sourceArtifact = new SourceArtifact(artifactRoot, pathFragment, owner);
+    SourceArtifact deserialized1 =
+        (SourceArtifact) objectCodecs.deserialize(objectCodecs.serialize(sourceArtifact));
+    SourceArtifact deserialized2 =
+        (SourceArtifact) objectCodecs.deserialize(objectCodecs.serialize(sourceArtifact));
+    assertThat(deserialized1).isSameAs(deserialized2);
+
+    Artifact sourceArtifactFromFactory =
+        artifactFactory.getSourceArtifact(pathFragment, root, owner);
+    Artifact deserialized =
+        (Artifact) objectCodecs.deserialize(objectCodecs.serialize(sourceArtifactFromFactory));
+    assertThat(sourceArtifactFromFactory).isSameAs(deserialized);
+  }
+
+  @Test
   public void testLongDirname() throws Exception {
     String dirName = createDirNameArtifact().getDirname();
 
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/actions/SymlinkActionTest.java b/src/test/java/com/google/devtools/build/lib/analysis/actions/SymlinkActionTest.java
index cdd4760..81979db 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/actions/SymlinkActionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/actions/SymlinkActionTest.java
@@ -25,6 +25,7 @@
 import com.google.devtools.build.lib.actions.OutputBaseSupplier;
 import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
 import com.google.devtools.build.lib.exec.util.TestExecutorBuilder;
+import com.google.devtools.build.lib.skyframe.serialization.testutils.SerializationDepsUtils;
 import com.google.devtools.build.lib.skyframe.serialization.testutils.SerializationTester;
 import com.google.devtools.build.lib.testutil.TestConstants;
 import com.google.devtools.build.lib.vfs.FileSystem;
@@ -100,6 +101,7 @@
     new SerializationTester(action)
         .addDependency(FileSystem.class, scratch.getFileSystem())
         .addDependency(OutputBaseSupplier.class, () -> outputBase)
+        .addDependencies(SerializationDepsUtils.SERIALIZATION_DEPS_FOR_TEST)
         .setVerificationFunction(
             (in, out) -> {
               SymlinkAction inAction = (SymlinkAction) in;