diff options
Diffstat (limited to 'src/main')
6 files changed, 111 insertions, 69 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/collect/nestedset/Order.java b/src/main/java/com/google/devtools/build/lib/collect/nestedset/Order.java index 581acad779..0fb2ae4d8c 100644 --- a/src/main/java/com/google/devtools/build/lib/collect/nestedset/Order.java +++ b/src/main/java/com/google/devtools/build/lib/collect/nestedset/Order.java @@ -15,6 +15,7 @@ package com.google.devtools.build.lib.collect.nestedset; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; +import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; import java.util.HashMap; /** @@ -115,6 +116,29 @@ public enum Order { this.emptySet = new NestedSet<>(this); } + @AutoCodec @AutoCodec.VisibleForSerialization + static final Order STABLE_ORDER_CONSTANT = STABLE_ORDER; + + @AutoCodec @AutoCodec.VisibleForSerialization + static final Order COMPILE_ORDER_CONSTANT = COMPILE_ORDER; + + @AutoCodec @AutoCodec.VisibleForSerialization static final Order LINK_ORDER_CONSTANT = LINK_ORDER; + + @AutoCodec @AutoCodec.VisibleForSerialization + static final Order NAIVE_LINK_ORDER_CONSTANT = NAIVE_LINK_ORDER; + + @AutoCodec @AutoCodec.VisibleForSerialization + static final NestedSet<?> EMPTY_STABLE = STABLE_ORDER.emptySet(); + + @AutoCodec @AutoCodec.VisibleForSerialization + static final NestedSet<?> EMPTY_COMPILE = COMPILE_ORDER.emptySet(); + + @AutoCodec @AutoCodec.VisibleForSerialization + static final NestedSet<?> EMPTY_LINK = LINK_ORDER.emptySet(); + + @AutoCodec @AutoCodec.VisibleForSerialization + static final NestedSet<?> EMPTY_NAIVE_LINK = NAIVE_LINK_ORDER.emptySet(); + /** * Returns an empty set of the given ordering. */ diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/AutoRegistry.java b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/AutoRegistry.java index bae7acca31..7785493aa5 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/AutoRegistry.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/AutoRegistry.java @@ -18,7 +18,10 @@ import com.google.common.base.Predicates; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Ordering; import java.io.IOException; +import java.util.Comparator; /** * A lazy, automatically populated registry. @@ -48,7 +51,11 @@ public class AutoRegistry { Predicates.alwaysTrue(), Predicates.alwaysFalse(), Predicates.isNull(), - Predicates.notNull()); + Predicates.notNull(), + ImmutableList.of(), + ImmutableSet.of(), + Comparator.naturalOrder(), + Ordering.natural()); public static ObjectCodecRegistry get() { return SUPPLIER.get(); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/ImmutableSortedSetCodec.java b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/ImmutableSortedSetCodec.java new file mode 100644 index 0000000000..1517a6158b --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/ImmutableSortedSetCodec.java @@ -0,0 +1,55 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// 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 com.google.common.collect.ImmutableSortedSet; +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.CodedOutputStream; +import java.io.IOException; + +/** + * {@link ObjectCodec} for {@link ImmutableSortedSet}. Comparator must be serializable, ideally a + * registered constant. + */ +class ImmutableSortedSetCodec<E> implements ObjectCodec<ImmutableSortedSet<E>> { + @SuppressWarnings("unchecked") + @Override + public Class<ImmutableSortedSet<E>> getEncodedClass() { + return (Class<ImmutableSortedSet<E>>) (Class<?>) ImmutableSortedSet.class; + } + + @Override + public void serialize( + SerializationContext context, ImmutableSortedSet<E> object, CodedOutputStream codedOut) + throws SerializationException, IOException { + context.serialize(object.comparator(), codedOut); + codedOut.writeInt32NoTag(object.size()); + for (Object obj : object) { + context.serialize(obj, codedOut); + } + } + + @Override + public ImmutableSortedSet<E> deserialize(DeserializationContext context, CodedInputStream codedIn) + throws SerializationException, IOException { + ImmutableSortedSet.Builder<E> builder = + ImmutableSortedSet.orderedBy(context.deserialize(codedIn)); + int size = codedIn.readInt32(); + for (int i = 0; i < size; i++) { + builder.add(context.<E>deserialize(codedIn)); + } + return builder.build(); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/ObjectCodecRegistry.java b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/ObjectCodecRegistry.java index ca104188f4..be324bcc05 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/ObjectCodecRegistry.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/ObjectCodecRegistry.java @@ -24,6 +24,7 @@ import com.google.common.collect.ImmutableSortedSet; import com.google.protobuf.CodedInputStream; import com.google.protobuf.CodedOutputStream; import java.io.IOException; +import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.IdentityHashMap; @@ -265,6 +266,28 @@ public class ObjectCodecRegistry { return this; } + /** + * Adds a constant value by reference. Any value encountered during serialization which {@code + * == object} will be replaced by {@code object} upon deserialization. Interned objects and + * effective singletons are ideal for reference constants. + * + * <p>These constants should be interned or effectively interned: it should not be possible to + * create objects that should be considered equal in which one has an element of this list and + * the other does not, since that would break bit-for-bit equality of the objects' serialized + * bytes when used in {@link com.google.devtools.build.skyframe.SkyKey}s. + * + * <p>Note that even {@link Boolean} does not satisfy this constraint, since {@code new + * Boolean(true)} is allowed, but upon deserialization, when a {@code boolean} is boxed to a + * {@link Boolean}, it will always be {@link Boolean#TRUE} or {@link Boolean#FALSE}. + * + * <p>The same is not true for an empty {@link ImmutableList}, since an empty non-{@link + * ImmutableList} will not serialize to an {@link ImmutableList}, and so won't be deserialized + * to an empty {@link ImmutableList}. If an object has a list field, and one codepath passes in + * an empty {@link ArrayList} and another passes in an empty {@link ImmutableList}, and two + * objects constructed in this way can be considered equal, then those two objects already do + * not serialize bit-for-bit identical disregarding this list of constants, since the list + * object's codec will be different for the two objects. + */ public Builder addConstant(Object object) { constantsBuilder.add(object); return this; diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/Marshallers.java b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/Marshallers.java index a0b306b3ce..41ab14f875 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/Marshallers.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/Marshallers.java @@ -18,14 +18,11 @@ import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.ImmutableSortedSet; -import com.google.common.collect.Iterables; import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationCodeGenerator.Context; import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationCodeGenerator.Marshaller; import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationCodeGenerator.PrimitiveValueSerializationCodeGenerator; import com.google.devtools.build.lib.skyframe.serialization.strings.StringCodecs; import com.squareup.javapoet.TypeName; -import java.util.Comparator; import java.util.Map; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.TypeElement; @@ -87,21 +84,6 @@ class Marshallers { } } - - private void writeIterableDeserializationLoopWithoutNullsAndBuild( - Context context, Context repeated, String builderName) { - String lengthName = context.makeName("length"); - context.builder.addStatement("int $L = codedIn.readInt32()", lengthName); - String indexName = context.makeName("i"); - context.builder.beginControlFlow( - "for (int $L = 0; $L < $L; ++$L)", indexName, indexName, lengthName, indexName); - writeDeserializationCode(repeated); - context.builder.addStatement("$L.add($L)", builderName, repeated.name); - context.builder.endControlFlow(); - context.builder.addStatement("$L = $L.build()", context.name, builderName); - } - - private SerializationCodeGenerator getMatchingCodeGenerator(TypeMirror type) { if (type.getKind() == TypeKind.ARRAY) { return arrayCodeGenerator; @@ -324,54 +306,6 @@ class Marshallers { } }; - private void addSerializationCodeForIterable(Context context) { - // Writes the target count to the stream so deserialization knows when to stop. - context.builder.addStatement( - "codedOut.writeInt32NoTag($T.size($L))", Iterables.class, context.name); - TypeMirror typeParameter = context.getDeclaredType().getTypeArguments().get(0); - // If this is generic we have to get the erasure since we don't know what <T> or <?> are. - if (isVariableOrWildcardType(typeParameter)) { - typeParameter = env.getTypeUtils().erasure(typeParameter); - } - Context repeated = - context.with( - context.getDeclaredType().getTypeArguments().get(0), context.makeName("repeated")); - context.builder.beginControlFlow( - "for ($T $L : $L)", typeParameter, repeated.name, context.name); - writeSerializationCode(repeated); - context.builder.endControlFlow(); - } - - private final Marshaller immutableSortedSetMarshaller = - new Marshaller() { - @Override - public boolean matches(DeclaredType type) { - return matchesErased(type, ImmutableSortedSet.class); - } - - @Override - public void addSerializationCode(Context context) { - addSerializationCodeForIterable(context); - } - - @Override - public void addDeserializationCode(Context context) { - Context repeated = - context.with( - context.getDeclaredType().getTypeArguments().get(0), - context.makeName("repeated")); - String builderName = context.makeName("builder"); - context.builder.addStatement( - "$T<$T> $L = new $T<>($T.naturalOrder())", - ImmutableSortedSet.Builder.class, - repeated.getTypeName(), - builderName, - ImmutableSortedSet.Builder.class, - Comparator.class); - writeIterableDeserializationLoopWithoutNullsAndBuild(context, repeated, builderName); - } - }; - private final Marshaller multimapMarshaller = new Marshaller() { @Override @@ -462,7 +396,6 @@ class Marshallers { ImmutableList.of( charSequenceMarshaller, supplierMarshaller, - immutableSortedSetMarshaller, multimapMarshaller, contextMarshaller); diff --git a/src/main/java/com/google/devtools/build/lib/vfs/PathFragment.java b/src/main/java/com/google/devtools/build/lib/vfs/PathFragment.java index cf90a32e85..fcb857bf20 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/PathFragment.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/PathFragment.java @@ -53,7 +53,7 @@ public final class PathFragment CommandLineItem { private static final OsPathPolicy OS = OsPathPolicy.getFilePathOs(); - public static final PathFragment EMPTY_FRAGMENT = create(""); + @AutoCodec public static final PathFragment EMPTY_FRAGMENT = create(""); public static final char SEPARATOR_CHAR = OS.getSeparator(); public static final int INVALID_SEGMENT = -1; |