diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/UnmodifiableMapCodec.java b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/UnmodifiableMapCodec.java index 9b8d871985459c..c2297276ade1b0 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/UnmodifiableMapCodec.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/UnmodifiableMapCodec.java @@ -11,9 +11,11 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. - package com.google.devtools.build.lib.skyframe.serialization; +import static com.google.devtools.build.lib.skyframe.serialization.HashMapCodec.populateMap; +import static com.google.devtools.build.lib.skyframe.serialization.MapHelpers.serializeMapEntries; + import com.google.protobuf.CodedInputStream; import com.google.protobuf.CodedOutputStream; import java.io.IOException; @@ -23,38 +25,38 @@ import java.util.Map; /** {@link ObjectCodec} for {@link java.util.Collections.UnmodifiableMap}. */ -final class UnmodifiableMapCodec implements ObjectCodec> { - private final Map empty = Collections.unmodifiableMap(new HashMap<>()); +@SuppressWarnings({"unchecked", "rawtypes", "NonApiType"}) +final class UnmodifiableMapCodec extends AsyncObjectCodec { + @SuppressWarnings("ConstantCaseForConstants") + private static final Map EMPTY = Collections.unmodifiableMap(new HashMap()); - @SuppressWarnings("unchecked") @Override - public Class> getEncodedClass() { - return (Class>) empty.getClass(); + public Class getEncodedClass() { + return EMPTY.getClass(); } @Override - public void serialize(SerializationContext context, Map obj, CodedOutputStream codedOut) + public void serialize(SerializationContext context, Map obj, CodedOutputStream codedOut) throws SerializationException, IOException { codedOut.writeInt32NoTag(obj.size()); - for (Map.Entry entry : obj.entrySet()) { - context.serialize(entry.getKey(), codedOut); - context.serialize(entry.getValue(), codedOut); - } + serializeMapEntries(context, obj, codedOut); } @Override - public Map deserialize(DeserializationContext context, CodedInputStream codedIn) + public Map deserializeAsync(AsyncDeserializationContext context, CodedInputStream codedIn) throws SerializationException, IOException { int size = codedIn.readInt32(); if (size == 0) { - return empty; + return EMPTY; } + // Load factor is 0.75, so we need an initial capacity of 4/3 actual size to avoid rehashing. - LinkedHashMap result = new LinkedHashMap<>(4 * size / 3); - for (int i = 0; i < size; i++) { - result.put(context.deserialize(codedIn), context.deserialize(codedIn)); - } - return Collections.unmodifiableMap(result); - } + LinkedHashMap map = new LinkedHashMap(4 * size / 3); + Map result = Collections.unmodifiableMap(map); + context.registerInitialValue(result); + + populateMap(context, codedIn, map, size); + return result; + } }