Add #getFastDigest method to SyscallCache and use it in DigestUtils. Thread the real per-build SyscallCache through to everywhere that calls into DigestUtils.

This leaves FileStateValue's call of #getFastDigest as the main undelegated one. A follow-up change will get rid of that usage too.

There should be no observable difference from this change: the only new actual usage of SyscallCache is in DigestUtils, which calls getFastDigest, which just delegates back to the Path for now.

PiperOrigin-RevId: 424972494
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java
index e8cd2c9..f170fee 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java
@@ -47,6 +47,7 @@
 import com.google.devtools.build.lib.util.Fingerprint;
 import com.google.devtools.build.lib.util.Pair;
 import com.google.devtools.build.lib.vfs.RootedPath;
+import com.google.devtools.build.lib.vfs.SyscallCache;
 import com.google.devtools.build.skyframe.SkyFunction;
 import com.google.devtools.build.skyframe.SkyFunctionException;
 import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
@@ -68,6 +69,7 @@
 class ArtifactFunction implements SkyFunction {
   private final Supplier<Boolean> mkdirForTreeArtifacts;
   private final MetadataConsumerForMetrics sourceArtifactsSeen;
+  private final Supplier<SyscallCache> syscallCache;
 
   static final class MissingArtifactValue implements SkyValue {
     private final DetailedExitCode detailedExitCode;
@@ -92,9 +94,12 @@
   }
 
   public ArtifactFunction(
-      Supplier<Boolean> mkdirForTreeArtifacts, MetadataConsumerForMetrics sourceArtifactsSeen) {
+      Supplier<Boolean> mkdirForTreeArtifacts,
+      MetadataConsumerForMetrics sourceArtifactsSeen,
+      Supplier<SyscallCache> syscallCache) {
     this.mkdirForTreeArtifacts = mkdirForTreeArtifacts;
     this.sourceArtifactsSeen = sourceArtifactsSeen;
+    this.syscallCache = syscallCache;
   }
 
   @Override
@@ -274,7 +279,8 @@
     if (!fileValue.isDirectory() || !TrackSourceDirectoriesFlag.trackSourceDirectories()) {
       FileArtifactValue metadata;
       try {
-        metadata = FileArtifactValue.createForSourceArtifact(artifact, fileValue);
+        metadata =
+            FileArtifactValue.createForSourceArtifact(artifact, fileValue, syscallCache.get());
       } catch (IOException e) {
         throw new ArtifactFunctionException(
             SourceArtifactException.create(artifact, e), Transience.TRANSIENT);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java
index 2683512..12f56ec 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java
@@ -66,6 +66,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Supplier;
 import javax.annotation.Nullable;
 
 /** A {@link SkyFunction} to build {@link RecursiveFilesystemTraversalValue}s. */
@@ -144,6 +145,12 @@
     }
   }
 
+  private final Supplier<SyscallCache> syscallCache;
+
+  RecursiveFilesystemTraversalFunction(Supplier<SyscallCache> syscallCache) {
+    this.syscallCache = syscallCache;
+  }
+
   @Nullable
   @Override
   public SkyValue compute(SkyKey skyKey, Environment env)
@@ -153,7 +160,7 @@
         Profiler.instance()
             .profile(ProfilerTask.FILESYSTEM_TRAVERSAL, traversal.getRoot().toString())) {
       // Stat the traversal root.
-      FileInfo rootInfo = lookUpFileInfo(env, traversal);
+      FileInfo rootInfo = lookUpFileInfo(env, traversal, syscallCache.get());
       if (rootInfo == null) {
         return null;
       }
@@ -188,7 +195,8 @@
       }
 
       // Otherwise the root is a directory or a symlink to one.
-      PkgLookupResult pkgLookupResult = checkIfPackage(env, traversal, rootInfo);
+      PkgLookupResult pkgLookupResult =
+          checkIfPackage(env, traversal, rootInfo, syscallCache.get());
       if (pkgLookupResult == null) {
         return null;
       }
@@ -306,7 +314,8 @@
   }
 
   @Nullable
-  private static FileInfo lookUpFileInfo(Environment env, TraversalRequest traversal)
+  private static FileInfo lookUpFileInfo(
+      Environment env, TraversalRequest traversal, SyscallCache syscallCache)
       throws IOException, InterruptedException {
     if (traversal.isRootGenerated) {
       HasDigest fsVal = null;
@@ -366,7 +375,8 @@
         if (fsVal == null) {
           fsVal = fileState;
         }
-        return new FileInfo(type, withDigest(fsVal, path), realPath, unresolvedLinkTarget);
+        return new FileInfo(
+            type, withDigest(fsVal, path, syscallCache), realPath, unresolvedLinkTarget);
       }
     } else {
       // Stat the file.
@@ -403,14 +413,14 @@
         Path path = traversal.root.asRootedPath().asPath();
         return new FileInfo(
             type,
-            withDigest(fileValue.realFileStateValue(), path),
+            withDigest(fileValue.realFileStateValue(), path, syscallCache),
             fileValue.realRootedPath(),
             unresolvedLinkTarget);
       } else {
         // If it doesn't exist, or it's a dangling symlink, we still want to handle that gracefully.
         return new FileInfo(
             fileValue.isSymlink() ? FileType.DANGLING_SYMLINK : FileType.NONEXISTENT,
-            withDigest(fileValue.realFileStateValue(), null),
+            withDigest(fileValue.realFileStateValue(), null, syscallCache),
             null,
             fileValue.isSymlink() ? fileValue.getUnresolvedLinkTarget() : null);
       }
@@ -430,7 +440,8 @@
    * @return transformed HasDigest value based on the digest field and object type.
    */
   @VisibleForTesting
-  static HasDigest withDigest(HasDigest fsVal, Path path) throws IOException {
+  static HasDigest withDigest(HasDigest fsVal, Path path, SyscallCache syscallCache)
+      throws IOException {
     if (fsVal instanceof FileStateValue) {
       FileStateValue fsv = (FileStateValue) fsVal;
       if (fsv instanceof RegularFileStateValue) {
@@ -440,7 +451,7 @@
             ? FileArtifactValue.createForVirtualActionInput(rfsv.getDigest(), rfsv.getSize())
             // Otherwise, create a file FileArtifactValue (RegularFileArtifactValue) based on the
             // path and size.
-            : FileArtifactValue.createForNormalFileUsingPath(path, rfsv.getSize());
+            : FileArtifactValue.createForNormalFileUsingPath(path, rfsv.getSize(), syscallCache);
       }
       return new HasDigest.ByteStringDigest(fsv.getValueFingerprint());
     } else if (fsVal instanceof FileArtifactValue) {
@@ -452,7 +463,7 @@
       // In the case there is a directory, the HasDigest value should not be converted. Otherwise,
       // if the HasDigest value is a file, convert it using the Path and size values.
       return fav.getType().isFile()
-          ? FileArtifactValue.createForNormalFileUsingPath(path, fav.getSize())
+          ? FileArtifactValue.createForNormalFileUsingPath(path, fav.getSize(), syscallCache)
           : new HasDigest.ByteStringDigest(fav.getValueFingerprint());
     }
     return fsVal;
@@ -510,7 +521,7 @@
    *     a package is found, but under a different root than expected)
    */
   private static PkgLookupResult checkIfPackage(
-      Environment env, TraversalRequest traversal, FileInfo rootInfo)
+      Environment env, TraversalRequest traversal, FileInfo rootInfo, SyscallCache syscallCache)
       throws IOException, InterruptedException, BuildFileNotFoundException {
     Preconditions.checkArgument(rootInfo.type.exists() && !rootInfo.type.isFile(),
         "{%s} {%s}", traversal, rootInfo);
@@ -540,7 +551,7 @@
           // However the root of this package is different from what we expected. stat() the real
           // BUILD file of that package.
           traversal = traversal.forChangedRootPath(pkgRoot);
-          rootInfo = lookUpFileInfo(env, traversal);
+          rootInfo = lookUpFileInfo(env, traversal, syscallCache);
           Verify.verify(rootInfo.type.exists(), "{%s} {%s}", traversal, rootInfo);
         }
         return PkgLookupResult.pkg(traversal, rootInfo);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
index ec1a6f8..5b6f252 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
@@ -599,7 +599,8 @@
         Artifact.ARTIFACT,
         new ArtifactFunction(
             () -> !skyframeActionExecutor.actionFileSystemType().inMemoryFileSystem(),
-            sourceArtifactsSeen));
+            sourceArtifactsSeen,
+            syscallCacheRef::get));
     map.put(
         SkyFunctions.BUILD_INFO_COLLECTION,
         new BuildInfoCollectionFunction(actionKeyContext, artifactFactory));
@@ -610,7 +611,8 @@
     map.put(SkyFunctions.ACTION_EXECUTION, actionExecutionFunction);
     this.actionExecutionFunction = actionExecutionFunction;
     map.put(
-        SkyFunctions.RECURSIVE_FILESYSTEM_TRAVERSAL, new RecursiveFilesystemTraversalFunction());
+        SkyFunctions.RECURSIVE_FILESYSTEM_TRAVERSAL,
+        new RecursiveFilesystemTraversalFunction(syscallCacheRef::get));
     map.put(SkyFunctions.FILESET_ENTRY, new FilesetEntryFunction(directories::getExecRoot));
     map.put(
         SkyFunctions.ACTION_TEMPLATE_EXPANSION,