Intern IntVersions.

--
MOS_MIGRATED_REVID=113197641
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 78a4e1d..87e1a47 100644
--- a/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java
+++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java
@@ -124,7 +124,7 @@
   @Override
   public void deleteDirty(long versionAgeLimit) {
     Preconditions.checkArgument(versionAgeLimit >= 0);
-    final Version threshold = new IntVersion(lastGraphVersion.getVal() - versionAgeLimit);
+    final Version threshold = IntVersion.of(lastGraphVersion.getVal() - versionAgeLimit);
     valuesToDelete.addAll(
         Sets.filter(dirtyKeyTracker.getDirtyKeys(), new Predicate<SkyKey>() {
           @Override
diff --git a/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java b/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java
index 0cee74c..c23b822 100644
--- a/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java
+++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java
@@ -329,7 +329,7 @@
 
   @Override
   public synchronized boolean signalDep() {
-    return signalDep(/*childVersion=*/new IntVersion(Long.MAX_VALUE));
+    return signalDep(/*childVersion=*/ IntVersion.of(Long.MAX_VALUE));
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/skyframe/IntVersion.java b/src/main/java/com/google/devtools/build/skyframe/IntVersion.java
index 38b2d71..cfb3484 100644
--- a/src/main/java/com/google/devtools/build/skyframe/IntVersion.java
+++ b/src/main/java/com/google/devtools/build/skyframe/IntVersion.java
@@ -13,16 +13,20 @@
 // limitations under the License.
 package com.google.devtools.build.skyframe;
 
+import com.google.common.collect.Interner;
+import com.google.common.collect.Interners;
+
 import java.io.Serializable;
 
 /**
  * Versioning scheme based on integers.
  */
 public final class IntVersion implements Version, Serializable {
+  private static final Interner<IntVersion> interner = Interners.newWeakInterner();
 
   private final long val;
 
-  public IntVersion(long val) {
+  private IntVersion(long val) {
     this.val = val;
   }
 
@@ -31,11 +35,15 @@
   }
 
   public IntVersion next() {
-    return new IntVersion(val + 1);
+    return of(val + 1);
   }
 
   public IntVersion previous() {
-    return new IntVersion(val - 1);
+    return of(val - 1);
+  }
+
+  public static IntVersion of(long val) {
+    return interner.intern(new IntVersion(val));
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/skyframe/SequentialBuildDriver.java b/src/main/java/com/google/devtools/build/skyframe/SequentialBuildDriver.java
index 99e2ef0..886c40a 100644
--- a/src/main/java/com/google/devtools/build/skyframe/SequentialBuildDriver.java
+++ b/src/main/java/com/google/devtools/build/skyframe/SequentialBuildDriver.java
@@ -28,7 +28,7 @@
 
   public SequentialBuildDriver(MemoizingEvaluator evaluator) {
     this.memoizingEvaluator = Preconditions.checkNotNull(evaluator);
-    this.curVersion = new IntVersion(0);
+    this.curVersion = IntVersion.of(0);
   }
 
   @Override
diff --git a/src/test/java/com/google/devtools/build/skyframe/EagerInvalidatorTest.java b/src/test/java/com/google/devtools/build/skyframe/EagerInvalidatorTest.java
index fbe5cc8..49706c8 100644
--- a/src/test/java/com/google/devtools/build/skyframe/EagerInvalidatorTest.java
+++ b/src/test/java/com/google/devtools/build/skyframe/EagerInvalidatorTest.java
@@ -69,7 +69,7 @@
   protected AtomicReference<InvalidatingNodeVisitor<?>> visitor = new AtomicReference<>();
   protected DirtyKeyTrackerImpl dirtyKeyTracker;
 
-  private IntVersion graphVersion = new IntVersion(0);
+  private IntVersion graphVersion = IntVersion.of(0);
 
   @After
   public void assertNoTrackedErrors() {
diff --git a/src/test/java/com/google/devtools/build/skyframe/GraphConcurrencyTest.java b/src/test/java/com/google/devtools/build/skyframe/GraphConcurrencyTest.java
index 52b6934..e0d877e 100644
--- a/src/test/java/com/google/devtools/build/skyframe/GraphConcurrencyTest.java
+++ b/src/test/java/com/google/devtools/build/skyframe/GraphConcurrencyTest.java
@@ -58,7 +58,7 @@
 
   protected abstract ProcessableGraph getGraph(Version version) throws Exception;
 
-  private static final IntVersion startingVersion = new IntVersion(42);
+  private static final IntVersion startingVersion = IntVersion.of(42);
 
   @Before
   public void init() throws Exception {
diff --git a/src/test/java/com/google/devtools/build/skyframe/InMemoryNodeEntryTest.java b/src/test/java/com/google/devtools/build/skyframe/InMemoryNodeEntryTest.java
index 2c45174..f29537d 100644
--- a/src/test/java/com/google/devtools/build/skyframe/InMemoryNodeEntryTest.java
+++ b/src/test/java/com/google/devtools/build/skyframe/InMemoryNodeEntryTest.java
@@ -89,7 +89,7 @@
     assertThat(setValue(entry, new SkyValue() {},
         /*errorInfo=*/null, /*graphVersion=*/0L)).isEmpty();
     assertTrue(entry.isDone());
-    assertEquals(new IntVersion(0L), entry.getVersion());
+    assertEquals(IntVersion.of(0L), entry.getVersion());
     assertThat(entry.getDirectDeps()).containsExactly(dep1, dep2, dep3);
   }
 
@@ -226,7 +226,7 @@
     assertThat(entry.markRebuildingAndGetAllRemainingDirtyDirectDeps()).containsExactly(dep);
     assertThat(setValue(entry, new SkyValue() {}, /*errorInfo=*/null,
         /*graphVersion=*/1L)).containsExactly(parent);
-    assertEquals(new IntVersion(1L), entry.getVersion());
+    assertEquals(IntVersion.of(1L), entry.getVersion());
   }
 
   @Test
@@ -372,11 +372,11 @@
     assertEquals(NodeEntry.DirtyState.CHECK_DEPENDENCIES, entry.getDirtyState());
     assertThat(entry.getNextDirtyDirectDeps()).containsExactly(dep);
     addTemporaryDirectDep(entry, dep);
-    entry.signalDep(new IntVersion(0L));
+    entry.signalDep(IntVersion.of(0L));
     assertEquals(NodeEntry.DirtyState.VERIFIED_CLEAN, entry.getDirtyState());
     assertThat(entry.markClean()).containsExactly(parent);
     assertTrue(entry.isDone());
-    assertEquals(new IntVersion(0L), entry.getVersion());
+    assertEquals(IntVersion.of(0L), entry.getVersion());
   }
 
   private static class IntegerValue implements SkyValue {
@@ -411,13 +411,13 @@
     entry.addReverseDepAndCheckIfDone(null); // Start evaluation.
     assertThat(entry.getNextDirtyDirectDeps()).containsExactly(dep);
     addTemporaryDirectDep(entry, dep);
-    entry.signalDep(new IntVersion(1L));
+    entry.signalDep(IntVersion.of(1L));
     assertEquals(NodeEntry.DirtyState.NEEDS_REBUILDING, entry.getDirtyState());
     assertThat(entry.getTemporaryDirectDeps()).containsExactly(dep);
     assertThat(entry.markRebuildingAndGetAllRemainingDirtyDirectDeps()).isEmpty();
     setValue(entry, new IntegerValue(5), /*errorInfo=*/null, /*graphVersion=*/1L);
     assertTrue(entry.isDone());
-    assertEquals(new IntVersion(0L), entry.getVersion());
+    assertEquals(IntVersion.of(0L), entry.getVersion());
   }
 
   @Test
@@ -440,7 +440,7 @@
     assertEquals(NodeEntry.DirtyState.CHECK_DEPENDENCIES, entry.getDirtyState());
     assertThat(entry.getNextDirtyDirectDeps()).containsExactly(dep);
     addTemporaryDirectDep(entry, dep);
-    entry.signalDep(new IntVersion(1L));
+    entry.signalDep(IntVersion.of(1L));
     assertEquals(NodeEntry.DirtyState.NEEDS_REBUILDING, entry.getDirtyState());
     assertThat(entry.getTemporaryDirectDeps()).containsExactly(dep);
     ReifiedSkyFunctionException exception = new ReifiedSkyFunctionException(
@@ -450,7 +450,7 @@
     setValue(entry, new IntegerValue(5), ErrorInfo.fromException(exception, false),
         /*graphVersion=*/1L);
     assertTrue(entry.isDone());
-    assertEquals("Version increments when setValue changes", new IntVersion(1), entry.getVersion());
+    assertEquals("Version increments when setValue changes", IntVersion.of(1), entry.getVersion());
   }
 
   @Test
@@ -477,7 +477,7 @@
     assertEquals(NodeEntry.DirtyState.CHECK_DEPENDENCIES, entry.getDirtyState());
     assertThat(entry.getNextDirtyDirectDeps()).containsExactly(dep);
     addTemporaryDirectDep(entry, dep);
-    entry.signalDep(new IntVersion(1L));
+    entry.signalDep(IntVersion.of(1L));
     assertEquals(NodeEntry.DirtyState.NEEDS_REBUILDING, entry.getDirtyState());
     assertThat(entry.getTemporaryDirectDeps()).containsExactly(dep);
     assertThat(entry.markRebuildingAndGetAllRemainingDirtyDirectDeps())
@@ -488,7 +488,7 @@
     setValue(entry, new IntegerValue(5), /*errorInfo=*/ null, /*graphVersion=*/ 1L);
     assertTrue(entry.isDone());
     assertEquals(
-        "Version does not change when dep group reordered", new IntVersion(0), entry.getVersion());
+        "Version does not change when dep group reordered", IntVersion.of(0), entry.getVersion());
   }
 
   @Test
@@ -508,14 +508,14 @@
     assertEquals(NodeEntry.DirtyState.CHECK_DEPENDENCIES, entry.getDirtyState());
     assertThat(entry.getNextDirtyDirectDeps()).containsExactly(dep);
     addTemporaryDirectDep(entry, dep);
-    entry.signalDep(new IntVersion(1L));
+    entry.signalDep(IntVersion.of(1L));
     assertEquals(NodeEntry.DirtyState.NEEDS_REBUILDING, entry.getDirtyState());
     assertThat(entry.getTemporaryDirectDeps()).containsExactly(dep);
     assertThat(entry.markRebuildingAndGetAllRemainingDirtyDirectDeps()).isEmpty();
     setValue(entry, /*value=*/null, errorInfo, /*graphVersion=*/1L);
     assertTrue(entry.isDone());
     // ErrorInfo is treated as a NotComparableSkyValue, so it is not pruned.
-    assertEquals(new IntVersion(1L), entry.getVersion());
+    assertEquals(IntVersion.of(1L), entry.getVersion());
   }
 
   @Test
@@ -536,8 +536,8 @@
     assertEquals(NodeEntry.DirtyState.CHECK_DEPENDENCIES, entry.getDirtyState());
     assertThat(entry.getNextDirtyDirectDeps()).containsExactly(dep, dep2);
     addTemporaryDirectDeps(entry, dep, dep2);
-    entry.signalDep(new IntVersion(0L));
-    entry.signalDep(new IntVersion(0L));
+    entry.signalDep(IntVersion.of(0L));
+    entry.signalDep(IntVersion.of(0L));
     assertEquals(NodeEntry.DirtyState.CHECK_DEPENDENCIES, entry.getDirtyState());
     assertThat(entry.getNextDirtyDirectDeps()).containsExactly(dep3);
   }
@@ -567,7 +567,7 @@
     assertEquals(NodeEntry.DirtyState.CHECK_DEPENDENCIES, entry.getDirtyState());
     assertThat(entry.getNextDirtyDirectDeps()).containsExactly(dep);
     addTemporaryDirectDep(entry, dep);
-    entry.signalDep(new IntVersion(0L));
+    entry.signalDep(IntVersion.of(0L));
     assertEquals(NodeEntry.DirtyState.CHECK_DEPENDENCIES, entry.getDirtyState());
     assertThat(entry.getNextDirtyDirectDeps()).containsExactly(dep4);
   }
@@ -585,15 +585,15 @@
     assertEquals(NodeEntry.DirtyState.CHECK_DEPENDENCIES, entry.getDirtyState());
     assertThat(entry.getNextDirtyDirectDeps()).containsExactly(dep);
     addTemporaryDirectDep(entry, dep);
-    assertTrue(entry.signalDep(new IntVersion(1L)));
+    assertTrue(entry.signalDep(IntVersion.of(1L)));
     assertEquals(NodeEntry.DirtyState.NEEDS_REBUILDING, entry.getDirtyState());
     assertThat(entry.getTemporaryDirectDeps()).containsExactly(dep);
     assertThat(entry.markRebuildingAndGetAllRemainingDirtyDirectDeps()).isEmpty();
     addTemporaryDirectDep(entry, key("dep2"));
-    assertTrue(entry.signalDep(new IntVersion(1L)));
+    assertTrue(entry.signalDep(IntVersion.of(1L)));
     setValue(entry, new IntegerValue(5), /*errorInfo=*/null, /*graphVersion=*/1L);
     assertTrue(entry.isDone());
-    assertEquals("Version increments when deps change", new IntVersion(1L), entry.getVersion());
+    assertEquals("Version increments when deps change", IntVersion.of(1L), entry.getVersion());
   }
 
   @Test
@@ -614,7 +614,7 @@
     for (int ii = 0; ii < 10; ii++) {
       assertThat(entry.getNextDirtyDirectDeps()).containsExactly(deps.get(ii));
       addTemporaryDirectDep(entry, deps.get(ii));
-      assertTrue(entry.signalDep(new IntVersion(0L)));
+      assertTrue(entry.signalDep(IntVersion.of(0L)));
       if (ii < 9) {
         assertEquals(NodeEntry.DirtyState.CHECK_DEPENDENCIES, entry.getDirtyState());
       } else {
@@ -640,7 +640,7 @@
   @Test
   public void testClone() {
     InMemoryNodeEntry entry = new InMemoryNodeEntry();
-    IntVersion version = new IntVersion(0);
+    IntVersion version = IntVersion.of(0);
     IntegerValue originalValue = new IntegerValue(42);
     SkyKey originalChild = key("child");
     addTemporaryDirectDep(entry, originalChild);
@@ -693,7 +693,7 @@
         entry.signalDep();
       }
     }
-    entry.setValue(new IntegerValue(42), new IntVersion(42L));
+    entry.setValue(new IntegerValue(42), IntVersion.of(42L));
     int i = 0;
     GroupedList<SkyKey> entryGroupedDirectDeps = entry.getGroupedDirectDeps();
     assertThat(Iterables.size(entryGroupedDirectDeps)).isEqualTo(groupedDirectDeps.size());
@@ -704,8 +704,8 @@
 
   private static Set<SkyKey> setValue(NodeEntry entry, SkyValue value,
       @Nullable ErrorInfo errorInfo, long graphVersion) {
-    return entry.setValue(ValueWithMetadata.normal(value, errorInfo, NO_EVENTS),
-        new IntVersion(graphVersion));
+    return entry.setValue(
+        ValueWithMetadata.normal(value, errorInfo, NO_EVENTS), IntVersion.of(graphVersion));
   }
 
   private static void addTemporaryDirectDep(NodeEntry entry, SkyKey key) {
diff --git a/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java b/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java
index c0389e0..172efd5 100644
--- a/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java
+++ b/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java
@@ -76,7 +76,7 @@
 @RunWith(JUnit4.class)
 public class ParallelEvaluatorTest {
   protected ProcessableGraph graph;
-  protected IntVersion graphVersion = new IntVersion(0);
+  protected IntVersion graphVersion = IntVersion.of(0);
   protected GraphTester tester = new GraphTester();
 
   private EventCollector eventCollector;