Automated rollback of commit 5576979669383c2380c11b59beaa2f8263ff1f56.

*** Reason for rollback ***

Causes a large regression in peak post GC memory.

PiperOrigin-RevId: 436137399
diff --git a/src/main/java/net/starlark/java/eval/Dict.java b/src/main/java/net/starlark/java/eval/Dict.java
index 342d65a..b1a0c16 100644
--- a/src/main/java/net/starlark/java/eval/Dict.java
+++ b/src/main/java/net/starlark/java/eval/Dict.java
@@ -14,7 +14,6 @@
 
 package net.starlark.java.eval;
 
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -112,21 +111,8 @@
         StarlarkIndexable,
         StarlarkIterable<K> {
 
-  /**
-   * The contents of the Dict.
-   *
-   * <p>This will either be a {@link LinkedHashMap} (for a mutable Dict that hasn't yet been frozen)
-   * or a {@link ImmutableMap} (for a Dict that started frozen or has been frozen; see {@link
-   * #Dict(ImmutableMap)} and {@link #onFreeze}, respectively).
-   */
-  private Map<K, V> contents;
-
-  /**
-   * The number of active iterators.
-   *
-   * <p>This is unused after the Dict is frozen.
-   */
-  private int iteratorCount;
+  private final Map<K, V> contents;
+  private int iteratorCount; // number of active iterators (unused once frozen)
 
   /** Final except for {@link #unsafeShallowFreeze}; must not be modified any other way. */
   private Mutability mutability;
@@ -135,7 +121,8 @@
     Preconditions.checkNotNull(mutability);
     Preconditions.checkState(mutability != Mutability.IMMUTABLE);
     this.mutability = mutability;
-    mutability.notifyOnFreeze(this);
+    // TODO(bazel-team): Memory optimization opportunity: Make it so that a call to
+    //  `mutability.freeze()` causes `contents` here to become an ImmutableMap.
     this.contents = contents;
   }
 
@@ -573,35 +560,6 @@
   public void unsafeShallowFreeze() {
     Mutability.Freezable.checkUnsafeShallowFreezePrecondition(this);
     this.mutability = Mutability.IMMUTABLE;
-    this.contents = ImmutableMap.copyOf(contents);
-  }
-
-  /**
-   * Switches {@link #contents} to be a {@link ImmutableMap} in order to save memory.
-   *
-   * <p>See the comment in {@link #Dict(ImmutableMap)} for details.
-   */
-  @Override
-  public void onFreeze() {
-    if (contents instanceof LinkedHashMap) {
-      this.contents = ImmutableMap.copyOf(contents);
-      // TODO(bazel-team): Make #mutability IMMUTABLE, causing the old Mutability instance to be
-      // eligible for GC. Do this in StarlarkList too.
-    } else {
-      // Assert #onFreeze hasn't been called before. But also hackily support the usage in
-      // ScriptTest.
-      //
-      // ScriptTest extends the language with a `freeze` feature, allowing #unsafeShallowFreeze to
-      // be called. When the bzl code has already caused that method to be called, #contents will
-      // already be an ImmutableMap, but #mutability will still not be.
-      //
-      // And we definitely want #unsafeShallowFreeze to cause #contents to become an ImmutableMap.
-      // That method is used at the end of deserialization, which uses a mutable #mutability that
-      // became IMMUTABLE in that method.
-      //
-      // TODO(bazel-team): Combine the two methods.
-      Preconditions.checkState(mutability == Mutability.IMMUTABLE);
-    }
   }
 
   /**
@@ -665,11 +623,6 @@
     return Starlark.repr(this);
   }
 
-  @VisibleForTesting
-  Map<K, V> getContentsForTesting() {
-    return contents;
-  }
-
   /**
    * Casts a non-null Starlark value {@code x} to a {@code Dict<K, V>} after checking that all keys
    * and values are instances of {@code keyType} and {@code valueType}, respectively. On error, it
diff --git a/src/main/java/net/starlark/java/eval/Mutability.java b/src/main/java/net/starlark/java/eval/Mutability.java
index 6243393..c31de3c 100644
--- a/src/main/java/net/starlark/java/eval/Mutability.java
+++ b/src/main/java/net/starlark/java/eval/Mutability.java
@@ -14,7 +14,6 @@
 package net.starlark.java.eval;
 
 import com.google.common.base.Joiner;
-import java.util.ArrayList;
 import java.util.IdentityHashMap;
 
 /**
@@ -106,8 +105,6 @@
   /** Controls access to {@link Freezable#unsafeShallowFreeze}. */
   private final boolean allowsUnsafeShallowFreeze;
 
-  private ArrayList<Freezable> freezablesToNotifyOnFreeze;
-
   private Mutability(Object[] annotation, boolean allowsUnsafeShallowFreeze) {
     this.annotation = annotation;
     this.allowsUnsafeShallowFreeze = allowsUnsafeShallowFreeze;
@@ -174,22 +171,13 @@
    * Freezes this {@code Mutability}, rendering all {@link Freezable} objects that refer to it
    * immutable.
    *
-   * <p>Note that freezing directly touches only the {@code Freezables} for which there was a call
-   * to {@code thisMutability.notifyOnFreeze(thatFreezable)}, so this is linear-time in the number
-   * of such {@code Freezables}s.
+   * Note that freezing does not directly touch all the {@code Freezables}, so this operation is
+   * constant-time.
    *
    * @return this object, in the fluent style
    */
   public Mutability freeze() {
     this.iteratorCount = null;
-
-    if (freezablesToNotifyOnFreeze != null) {
-      for (Freezable freezable : freezablesToNotifyOnFreeze) {
-        freezable.onFreeze();
-      }
-      freezablesToNotifyOnFreeze = null;
-    }
-
     return this;
   }
 
@@ -200,23 +188,13 @@
 
   /**
    * Returns whether {@link Freezable}s having this {@code Mutability} allow the {@link
-   * Freezable#unsafeShallowFreeze} operation.
+   * #unsafeShallowFreeze} operation.
    */
   public boolean allowsUnsafeShallowFreeze() {
     return allowsUnsafeShallowFreeze;
   }
 
   /**
-   * Causes {@code freezable.onFreeze()} to be called in the future when {@link #freeze} is called.
-   */
-  public void notifyOnFreeze(Freezable freezable) {
-    if (freezablesToNotifyOnFreeze == null) {
-      freezablesToNotifyOnFreeze = new ArrayList<>();
-    }
-    freezablesToNotifyOnFreeze.add(freezable);
-  }
-
-  /**
    * An object that refers to a {@link Mutability} to decide whether to allow mutation. All {@link
    * Freezable} Starlark objects created within a given {@link StarlarkThread} will share the same
    * {@code Mutability} as that {@code StarlarkThread}.
@@ -230,14 +208,6 @@
     Mutability mutability();
 
     /**
-     * If {@code mutability().notifyOnFreeze(this)} has been called, this method gets called when
-     * {@code mutability().freeze()} gets called.
-     *
-     * <p>Do not call this method from outside {@link Mutability#freeze}.
-     */
-    default void onFreeze() {}
-
-    /**
      * Registers a change to this Freezable's iterator count and reports whether it is temporarily
      * immutable.
      *
diff --git a/src/test/java/net/starlark/java/eval/MutabilityTest.java b/src/test/java/net/starlark/java/eval/MutabilityTest.java
index 9fab8ba..17a6a3b 100644
--- a/src/test/java/net/starlark/java/eval/MutabilityTest.java
+++ b/src/test/java/net/starlark/java/eval/MutabilityTest.java
@@ -127,44 +127,4 @@
     Mutability mutability = Mutability.createAllowingShallowFreeze("test");
     Freezable.checkUnsafeShallowFreezePrecondition(new DummyFreezable(mutability));
   }
-
-  @Test
-  public void notifyOnFreeze() {
-    class FreezableWithNotify implements Freezable {
-      private final Mutability mutability;
-      private boolean onFreezeCalled = false;
-
-      FreezableWithNotify(Mutability mutability) {
-        this.mutability = mutability;
-      }
-
-      @Override
-      public Mutability mutability() {
-        return mutability;
-      }
-
-      @Override
-      public void onFreeze() {
-        onFreezeCalled = true;
-      }
-    }
-
-    // When we have an unfrozen Mutability,
-    Mutability mutability = Mutability.create("test");
-
-    // And we create two Freezables using the Mutability,
-    FreezableWithNotify freezable1 = new FreezableWithNotify(mutability);
-    FreezableWithNotify freezable2 = new FreezableWithNotify(mutability);
-
-    // And we tell the Mutability to notify one of the two Freezables when it has been frozen,
-    mutability.notifyOnFreeze(freezable1);
-
-    // And we freeze the Mutability,
-    mutability.freeze();
-
-    // Then the Freezable that was supposed to be notified was notified,
-    assertThat(freezable1.onFreezeCalled).isTrue();
-    // And the other one wasn't.
-    assertThat(freezable2.onFreezeCalled).isFalse();
-  }
 }
diff --git a/src/test/java/net/starlark/java/eval/StarlarkMutableTest.java b/src/test/java/net/starlark/java/eval/StarlarkMutableTest.java
index cc41cdf..66d02a8 100644
--- a/src/test/java/net/starlark/java/eval/StarlarkMutableTest.java
+++ b/src/test/java/net/starlark/java/eval/StarlarkMutableTest.java
@@ -20,14 +20,13 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
-/** Tests for how Starlark value implementations interact with {@link Mutability#freeze}. */
+/** Tests for {@link StarlarkMutable}. */
 @RunWith(JUnit4.class)
 public final class StarlarkMutableTest {
 
@@ -143,33 +142,4 @@
         .isEqualTo(
             "{\"one\": \"1\", \"two\": \"22\", \"three\": \"33\", \"four\": \"4\"}"); // unchanged
   }
-
-  @Test
-  public void testImmutableDictUsesImmutableMap() {
-    Mutability mu = Mutability.IMMUTABLE;
-    Dict<String, String> dict = Dict.<String, String>builder().put("cat", "dog").build(mu);
-    assertThat(dict.getContentsForTesting()).isInstanceOf(ImmutableMap.class);
-    assertThat(dict.getContentsForTesting()).containsExactly("cat", "dog");
-  }
-
-  @Test
-  public void testMutableDictSwitchesToImmutableMapWhenFrozen() {
-    Mutability mu = Mutability.create("test");
-    Dict<String, String> dict = Dict.<String, String>builder().put("cat", "dog").build(mu);
-    assertThat(dict.getContentsForTesting()).isInstanceOf(LinkedHashMap.class);
-    assertThat(dict.getContentsForTesting()).containsExactly("cat", "dog");
-    mu.freeze();
-    assertThat(dict.getContentsForTesting()).isInstanceOf(ImmutableMap.class);
-    assertThat(dict.getContentsForTesting()).containsExactly("cat", "dog");
-  }
-
-  @Test
-  public void testMutableDictSwitchesToImmutableMapWhenFrozen_usesCanonicalEmptyImmutableMap() {
-    Mutability mu = Mutability.create("test");
-    Dict<String, String> dict = Dict.<String, String>builder().build(mu);
-    assertThat(dict.getContentsForTesting()).isInstanceOf(LinkedHashMap.class);
-    assertThat(dict.getContentsForTesting()).isEmpty();
-    mu.freeze();
-    assertThat(dict.getContentsForTesting()).isSameInstanceAs(ImmutableMap.of());
-  }
 }