Skip to content

Commit a421288

Browse files
meisterTcopybara-github
authored andcommitted
Automated rollback of commit 5576979.
*** Reason for rollback *** Causes a large regression in peak post GC memory. PiperOrigin-RevId: 436137399
1 parent 49625ea commit a421288

File tree

4 files changed

+8
-155
lines changed

4 files changed

+8
-155
lines changed

src/main/java/net/starlark/java/eval/Dict.java

+4-51
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
package net.starlark.java.eval;
1616

17-
import com.google.common.annotations.VisibleForTesting;
1817
import com.google.common.base.Preconditions;
1918
import com.google.common.collect.ImmutableMap;
2019
import com.google.common.collect.ImmutableSet;
@@ -112,21 +111,8 @@ public class Dict<K, V>
112111
StarlarkIndexable,
113112
StarlarkIterable<K> {
114113

115-
/**
116-
* The contents of the Dict.
117-
*
118-
* <p>This will either be a {@link LinkedHashMap} (for a mutable Dict that hasn't yet been frozen)
119-
* or a {@link ImmutableMap} (for a Dict that started frozen or has been frozen; see {@link
120-
* #Dict(ImmutableMap)} and {@link #onFreeze}, respectively).
121-
*/
122-
private Map<K, V> contents;
123-
124-
/**
125-
* The number of active iterators.
126-
*
127-
* <p>This is unused after the Dict is frozen.
128-
*/
129-
private int iteratorCount;
114+
private final Map<K, V> contents;
115+
private int iteratorCount; // number of active iterators (unused once frozen)
130116

131117
/** Final except for {@link #unsafeShallowFreeze}; must not be modified any other way. */
132118
private Mutability mutability;
@@ -135,7 +121,8 @@ private Dict(Mutability mutability, LinkedHashMap<K, V> contents) {
135121
Preconditions.checkNotNull(mutability);
136122
Preconditions.checkState(mutability != Mutability.IMMUTABLE);
137123
this.mutability = mutability;
138-
mutability.notifyOnFreeze(this);
124+
// TODO(bazel-team): Memory optimization opportunity: Make it so that a call to
125+
// `mutability.freeze()` causes `contents` here to become an ImmutableMap.
139126
this.contents = contents;
140127
}
141128

@@ -573,35 +560,6 @@ public Mutability mutability() {
573560
public void unsafeShallowFreeze() {
574561
Mutability.Freezable.checkUnsafeShallowFreezePrecondition(this);
575562
this.mutability = Mutability.IMMUTABLE;
576-
this.contents = ImmutableMap.copyOf(contents);
577-
}
578-
579-
/**
580-
* Switches {@link #contents} to be a {@link ImmutableMap} in order to save memory.
581-
*
582-
* <p>See the comment in {@link #Dict(ImmutableMap)} for details.
583-
*/
584-
@Override
585-
public void onFreeze() {
586-
if (contents instanceof LinkedHashMap) {
587-
this.contents = ImmutableMap.copyOf(contents);
588-
// TODO(bazel-team): Make #mutability IMMUTABLE, causing the old Mutability instance to be
589-
// eligible for GC. Do this in StarlarkList too.
590-
} else {
591-
// Assert #onFreeze hasn't been called before. But also hackily support the usage in
592-
// ScriptTest.
593-
//
594-
// ScriptTest extends the language with a `freeze` feature, allowing #unsafeShallowFreeze to
595-
// be called. When the bzl code has already caused that method to be called, #contents will
596-
// already be an ImmutableMap, but #mutability will still not be.
597-
//
598-
// And we definitely want #unsafeShallowFreeze to cause #contents to become an ImmutableMap.
599-
// That method is used at the end of deserialization, which uses a mutable #mutability that
600-
// became IMMUTABLE in that method.
601-
//
602-
// TODO(bazel-team): Combine the two methods.
603-
Preconditions.checkState(mutability == Mutability.IMMUTABLE);
604-
}
605563
}
606564

607565
/**
@@ -665,11 +623,6 @@ public String toString() {
665623
return Starlark.repr(this);
666624
}
667625

668-
@VisibleForTesting
669-
Map<K, V> getContentsForTesting() {
670-
return contents;
671-
}
672-
673626
/**
674627
* Casts a non-null Starlark value {@code x} to a {@code Dict<K, V>} after checking that all keys
675628
* and values are instances of {@code keyType} and {@code valueType}, respectively. On error, it

src/main/java/net/starlark/java/eval/Mutability.java

+3-33
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
package net.starlark.java.eval;
1515

1616
import com.google.common.base.Joiner;
17-
import java.util.ArrayList;
1817
import java.util.IdentityHashMap;
1918

2019
/**
@@ -106,8 +105,6 @@ public final class Mutability implements AutoCloseable {
106105
/** Controls access to {@link Freezable#unsafeShallowFreeze}. */
107106
private final boolean allowsUnsafeShallowFreeze;
108107

109-
private ArrayList<Freezable> freezablesToNotifyOnFreeze;
110-
111108
private Mutability(Object[] annotation, boolean allowsUnsafeShallowFreeze) {
112109
this.annotation = annotation;
113110
this.allowsUnsafeShallowFreeze = allowsUnsafeShallowFreeze;
@@ -174,22 +171,13 @@ private boolean updateIteratorCount(Freezable x, int delta) {
174171
* Freezes this {@code Mutability}, rendering all {@link Freezable} objects that refer to it
175172
* immutable.
176173
*
177-
* <p>Note that freezing directly touches only the {@code Freezables} for which there was a call
178-
* to {@code thisMutability.notifyOnFreeze(thatFreezable)}, so this is linear-time in the number
179-
* of such {@code Freezables}s.
174+
* Note that freezing does not directly touch all the {@code Freezables}, so this operation is
175+
* constant-time.
180176
*
181177
* @return this object, in the fluent style
182178
*/
183179
public Mutability freeze() {
184180
this.iteratorCount = null;
185-
186-
if (freezablesToNotifyOnFreeze != null) {
187-
for (Freezable freezable : freezablesToNotifyOnFreeze) {
188-
freezable.onFreeze();
189-
}
190-
freezablesToNotifyOnFreeze = null;
191-
}
192-
193181
return this;
194182
}
195183

@@ -200,22 +188,12 @@ public void close() {
200188

201189
/**
202190
* Returns whether {@link Freezable}s having this {@code Mutability} allow the {@link
203-
* Freezable#unsafeShallowFreeze} operation.
191+
* #unsafeShallowFreeze} operation.
204192
*/
205193
public boolean allowsUnsafeShallowFreeze() {
206194
return allowsUnsafeShallowFreeze;
207195
}
208196

209-
/**
210-
* Causes {@code freezable.onFreeze()} to be called in the future when {@link #freeze} is called.
211-
*/
212-
public void notifyOnFreeze(Freezable freezable) {
213-
if (freezablesToNotifyOnFreeze == null) {
214-
freezablesToNotifyOnFreeze = new ArrayList<>();
215-
}
216-
freezablesToNotifyOnFreeze.add(freezable);
217-
}
218-
219197
/**
220198
* An object that refers to a {@link Mutability} to decide whether to allow mutation. All {@link
221199
* Freezable} Starlark objects created within a given {@link StarlarkThread} will share the same
@@ -229,14 +207,6 @@ public interface Freezable {
229207
*/
230208
Mutability mutability();
231209

232-
/**
233-
* If {@code mutability().notifyOnFreeze(this)} has been called, this method gets called when
234-
* {@code mutability().freeze()} gets called.
235-
*
236-
* <p>Do not call this method from outside {@link Mutability#freeze}.
237-
*/
238-
default void onFreeze() {}
239-
240210
/**
241211
* Registers a change to this Freezable's iterator count and reports whether it is temporarily
242212
* immutable.

src/test/java/net/starlark/java/eval/MutabilityTest.java

-40
Original file line numberDiff line numberDiff line change
@@ -127,44 +127,4 @@ public void checkUnsafeShallowFreezePrecondition_SucceedsWhenAllowed() throws Ex
127127
Mutability mutability = Mutability.createAllowingShallowFreeze("test");
128128
Freezable.checkUnsafeShallowFreezePrecondition(new DummyFreezable(mutability));
129129
}
130-
131-
@Test
132-
public void notifyOnFreeze() {
133-
class FreezableWithNotify implements Freezable {
134-
private final Mutability mutability;
135-
private boolean onFreezeCalled = false;
136-
137-
FreezableWithNotify(Mutability mutability) {
138-
this.mutability = mutability;
139-
}
140-
141-
@Override
142-
public Mutability mutability() {
143-
return mutability;
144-
}
145-
146-
@Override
147-
public void onFreeze() {
148-
onFreezeCalled = true;
149-
}
150-
}
151-
152-
// When we have an unfrozen Mutability,
153-
Mutability mutability = Mutability.create("test");
154-
155-
// And we create two Freezables using the Mutability,
156-
FreezableWithNotify freezable1 = new FreezableWithNotify(mutability);
157-
FreezableWithNotify freezable2 = new FreezableWithNotify(mutability);
158-
159-
// And we tell the Mutability to notify one of the two Freezables when it has been frozen,
160-
mutability.notifyOnFreeze(freezable1);
161-
162-
// And we freeze the Mutability,
163-
mutability.freeze();
164-
165-
// Then the Freezable that was supposed to be notified was notified,
166-
assertThat(freezable1.onFreezeCalled).isTrue();
167-
// And the other one wasn't.
168-
assertThat(freezable2.onFreezeCalled).isFalse();
169-
}
170130
}

src/test/java/net/starlark/java/eval/StarlarkMutableTest.java

+1-31
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,13 @@
2020
import com.google.common.collect.ImmutableList;
2121
import com.google.common.collect.ImmutableMap;
2222
import java.util.Iterator;
23-
import java.util.LinkedHashMap;
2423
import java.util.List;
2524
import java.util.Map;
2625
import org.junit.Test;
2726
import org.junit.runner.RunWith;
2827
import org.junit.runners.JUnit4;
2928

30-
/** Tests for how Starlark value implementations interact with {@link Mutability#freeze}. */
29+
/** Tests for {@link StarlarkMutable}. */
3130
@RunWith(JUnit4.class)
3231
public final class StarlarkMutableTest {
3332

@@ -143,33 +142,4 @@ public void testDictBuilder() throws Exception {
143142
.isEqualTo(
144143
"{\"one\": \"1\", \"two\": \"22\", \"three\": \"33\", \"four\": \"4\"}"); // unchanged
145144
}
146-
147-
@Test
148-
public void testImmutableDictUsesImmutableMap() {
149-
Mutability mu = Mutability.IMMUTABLE;
150-
Dict<String, String> dict = Dict.<String, String>builder().put("cat", "dog").build(mu);
151-
assertThat(dict.getContentsForTesting()).isInstanceOf(ImmutableMap.class);
152-
assertThat(dict.getContentsForTesting()).containsExactly("cat", "dog");
153-
}
154-
155-
@Test
156-
public void testMutableDictSwitchesToImmutableMapWhenFrozen() {
157-
Mutability mu = Mutability.create("test");
158-
Dict<String, String> dict = Dict.<String, String>builder().put("cat", "dog").build(mu);
159-
assertThat(dict.getContentsForTesting()).isInstanceOf(LinkedHashMap.class);
160-
assertThat(dict.getContentsForTesting()).containsExactly("cat", "dog");
161-
mu.freeze();
162-
assertThat(dict.getContentsForTesting()).isInstanceOf(ImmutableMap.class);
163-
assertThat(dict.getContentsForTesting()).containsExactly("cat", "dog");
164-
}
165-
166-
@Test
167-
public void testMutableDictSwitchesToImmutableMapWhenFrozen_usesCanonicalEmptyImmutableMap() {
168-
Mutability mu = Mutability.create("test");
169-
Dict<String, String> dict = Dict.<String, String>builder().build(mu);
170-
assertThat(dict.getContentsForTesting()).isInstanceOf(LinkedHashMap.class);
171-
assertThat(dict.getContentsForTesting()).isEmpty();
172-
mu.freeze();
173-
assertThat(dict.getContentsForTesting()).isSameInstanceAs(ImmutableMap.of());
174-
}
175145
}

0 commit comments

Comments
 (0)