Drop loading-phase values if --discard_analysis_cache is true and we're not keeping incremental state. PiperOrigin-RevId: 151639711
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutor.java index 61defac..e48991b 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutor.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutor.java
@@ -63,6 +63,7 @@ import com.google.devtools.build.skyframe.InMemoryMemoizingEvaluator; import com.google.devtools.build.skyframe.Injectable; import com.google.devtools.build.skyframe.MemoizingEvaluator.EvaluatorSupplier; +import com.google.devtools.build.skyframe.NodeEntry; import com.google.devtools.build.skyframe.RecordingDifferencer; import com.google.devtools.build.skyframe.SequentialBuildDriver; import com.google.devtools.build.skyframe.SkyFunction; @@ -75,6 +76,7 @@ import java.util.Collection; import java.util.EnumSet; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -595,15 +597,26 @@ recordingDiffer.invalidate(dirtyActionValues); } + private static ImmutableSet<SkyFunctionName> LOADING_TYPES = + ImmutableSet.of( + SkyFunctions.PACKAGE, + SkyFunctions.SKYLARK_IMPORTS_LOOKUP, + SkyFunctions.AST_FILE_LOOKUP, + SkyFunctions.GLOB); + /** * Save memory by removing references to configured targets and aspects in Skyframe. * - * <p>These values must be recreated on subsequent builds. We do not clear the top-level target - * values, since their configured targets are needed for the target completion middleman values. + * <p>These nodes must be recreated on subsequent builds. We do not clear the top-level target + * nodes, since their configured targets are needed for the target completion middleman values. * - * <p>The values are not deleted during this method call, because they are needed for the - * execution phase. Instead, their data is cleared. The next build will delete the values (and - * recreate them if necessary). + * <p>The nodes are not deleted during this method call, because they are needed for the execution + * phase. Instead, their analysis-time data is cleared while preserving the generating action info + * needed for execution. The next build will delete the nodes (and recreate them if necessary). + * + * <p>If {@link #hasIncrementalState} is false, then also delete loading-phase nodes (as + * determined by {@link #LOADING_TYPES}) from the graph, since there will be no future builds to + * use them for. */ private void discardAnalysisCache( Collection<ConfiguredTarget> topLevelTargets, Collection<AspectValue> topLevelAspects) { @@ -611,16 +624,38 @@ topLevelAspects = ImmutableSet.copyOf(topLevelAspects); try (AutoProfiler p = AutoProfiler.logged("discarding analysis cache", LOG)) { lastAnalysisDiscarded = true; - for (Map.Entry<SkyKey, SkyValue> entry : memoizingEvaluator.getValues().entrySet()) { - SkyFunctionName functionName = entry.getKey().functionName(); + Iterator<? extends Map.Entry<SkyKey, ? extends NodeEntry>> it = + memoizingEvaluator.getGraphMap().entrySet().iterator(); + while (it.hasNext()) { + Map.Entry<SkyKey, ? extends NodeEntry> keyAndEntry = it.next(); + NodeEntry entry = keyAndEntry.getValue(); + if (entry == null || !entry.isDone()) { + continue; + } + SkyKey key = keyAndEntry.getKey(); + SkyFunctionName functionName = key.functionName(); + if (!hasIncrementalState() && LOADING_TYPES.contains(functionName)) { + it.remove(); + continue; + } if (functionName.equals(SkyFunctions.CONFIGURED_TARGET)) { - ConfiguredTargetValue ctValue = (ConfiguredTargetValue) entry.getValue(); + ConfiguredTargetValue ctValue; + try { + ctValue = (ConfiguredTargetValue) entry.getValue(); + } catch (InterruptedException e) { + throw new IllegalStateException("No interruption in sequenced evaluation", e); + } // ctValue may be null if target was not successfully analyzed. if (ctValue != null) { ctValue.clear(!topLevelTargets.contains(ctValue.getConfiguredTarget())); } } else if (functionName.equals(SkyFunctions.ASPECT)) { - AspectValue aspectValue = (AspectValue) entry.getValue(); + AspectValue aspectValue; + try { + aspectValue = (AspectValue) entry.getValue(); + } catch (InterruptedException e) { + throw new IllegalStateException("No interruption in sequenced evaluation", e); + } // value may be null if target was not successfully analyzed. if (aspectValue != null) { aspectValue.clear(!topLevelAspects.contains(aspectValue));
diff --git a/src/main/java/com/google/devtools/build/skyframe/InMemoryGraph.java b/src/main/java/com/google/devtools/build/skyframe/InMemoryGraph.java index edb80f0..82ddb17 100644 --- a/src/main/java/com/google/devtools/build/skyframe/InMemoryGraph.java +++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryGraph.java
@@ -44,4 +44,6 @@ // Only for use by MemoizingEvaluator#delete Map<SkyKey, ? extends NodeEntry> getAllValues(); + + Map<SkyKey, ? extends NodeEntry> getAllValuesMutable(); }
diff --git a/src/main/java/com/google/devtools/build/skyframe/InMemoryGraphImpl.java b/src/main/java/com/google/devtools/build/skyframe/InMemoryGraphImpl.java index 71c3ad3..d85ab00 100644 --- a/src/main/java/com/google/devtools/build/skyframe/InMemoryGraphImpl.java +++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryGraphImpl.java
@@ -120,6 +120,11 @@ return Collections.unmodifiableMap(nodeMap); } + @Override + public Map<SkyKey, ? extends NodeEntry> getAllValuesMutable() { + return nodeMap; + } + @VisibleForTesting protected ConcurrentMap<SkyKey, ? extends NodeEntry> getNodeMap() { return nodeMap;
diff --git a/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java b/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java index 68998b3..4ebde56 100644 --- a/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java +++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java
@@ -258,6 +258,11 @@ } @Override + public Map<SkyKey, ? extends NodeEntry> getGraphMap() { + return graph.getAllValuesMutable(); + } + + @Override public Map<SkyKey, SkyValue> getDoneValues() { return graph.getDoneValues(); }
diff --git a/src/main/java/com/google/devtools/build/skyframe/MemoizingEvaluator.java b/src/main/java/com/google/devtools/build/skyframe/MemoizingEvaluator.java index d690c4a..6bd01b5 100644 --- a/src/main/java/com/google/devtools/build/skyframe/MemoizingEvaluator.java +++ b/src/main/java/com/google/devtools/build/skyframe/MemoizingEvaluator.java
@@ -91,6 +91,13 @@ Map<SkyKey, SkyValue> getValues(); /** + * Returns the node entries in the graph. Should only be called between evaluations. The returned + * map is mutable, but do not mutate it unless you know what you are doing! Naively deleting an + * entry will break graph invariants and cause a crash. + */ + Map<SkyKey, ? extends NodeEntry> getGraphMap(); + + /** * Returns the done (without error) values in the graph. * * <p>The returned map may be a live view of the graph.