diff options
6 files changed, 188 insertions, 10 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkLateBoundDefault.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkLateBoundDefault.java index 52d316259e..93fe96e32e 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkLateBoundDefault.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkLateBoundDefault.java @@ -26,6 +26,7 @@ import com.google.devtools.build.lib.packages.Attribute.AbstractLabelLateBoundDe import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; import com.google.devtools.build.lib.packages.AttributeMap; import com.google.devtools.build.lib.packages.Rule; +import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter; import com.google.devtools.build.lib.skylarkinterface.SkylarkValue; @@ -47,6 +48,7 @@ import javax.annotation.concurrent.Immutable; * target configuration. */ @Immutable +@AutoCodec public class SkylarkLateBoundDefault<FragmentT> extends AbstractLabelLateBoundDefault<FragmentT> implements SkylarkValue { @@ -82,13 +84,26 @@ public class SkylarkLateBoundDefault<FragmentT> extends AbstractLabelLateBoundDe private SkylarkLateBoundDefault(SkylarkConfigurationField annotation, Class<FragmentT> fragmentClass, String fragmentName, Method method, String toolsRepository) { - super(false /* don't use host configuration */, + this( + getDefaultLabel(annotation, toolsRepository), fragmentClass, - getDefaultLabel(annotation, toolsRepository)); + method, + fragmentName, + annotation.name()); + } + @AutoCodec.VisibleForSerialization + @AutoCodec.Instantiator + SkylarkLateBoundDefault( + Label defaultVal, + Class<FragmentT> fragmentClass, + Method method, + String fragmentName, + String fragmentFieldName) { + super(/*useHostConfiguration=*/ false, fragmentClass, defaultVal); this.method = method; this.fragmentName = fragmentName; - this.fragmentFieldName = annotation.name(); + this.fragmentFieldName = fragmentFieldName; } /** @@ -111,6 +126,12 @@ public class SkylarkLateBoundDefault<FragmentT> extends AbstractLabelLateBoundDe printer.format("<late-bound default>"); } + /** For use by @AutoCodec since the {@link #defaultValue} field is hard for it to process. */ + @AutoCodec.VisibleForSerialization + Label getDefaultVal() { + return getDefault(); + } + /** * An exception thrown if a user specifies an invalid configuration field identifier. * diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageValue.java index ba1962335b..565e4f1290 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageValue.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageValue.java @@ -30,7 +30,7 @@ import java.util.ArrayList; import java.util.List; /** A Skyframe value representing a package. */ -@AutoCodec +@AutoCodec(memoization = AutoCodec.Memoization.START_MEMOIZING) @Immutable @ThreadSafe public class PackageValue implements NotComparableSkyValue { diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/ClassCodec.java b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/ClassCodec.java index e3675ee9e8..d21f928354 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/ClassCodec.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/ClassCodec.java @@ -14,6 +14,8 @@ package com.google.devtools.build.lib.skyframe.serialization; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableBiMap; import com.google.protobuf.CodedInputStream; import com.google.protobuf.CodedOutputStream; import java.io.IOException; @@ -29,17 +31,40 @@ class ClassCodec implements ObjectCodec<Class<?>> { @Override public void serialize(SerializationContext context, Class<?> obj, CodedOutputStream codedOut) throws SerializationException, IOException { - context.serialize(obj.getName(), codedOut); + codedOut.writeBoolNoTag(obj.isPrimitive()); + if (obj.isPrimitive()) { + codedOut.writeInt32NoTag(Preconditions.checkNotNull(PRIMITIVE_CLASS_INDEX_MAP.get(obj), obj)); + } else { + context.serialize(obj.getName(), codedOut); + } } @Override public Class<?> deserialize(DeserializationContext context, CodedInputStream codedIn) throws SerializationException, IOException { - String className = context.deserialize(codedIn); - try { - return Class.forName(className); - } catch (ClassNotFoundException e) { - throw new SerializationException("Couldn't find class for " + className, e); + boolean isPrimitive = codedIn.readBool(); + if (isPrimitive) { + return PRIMITIVE_CLASS_INDEX_MAP.inverse().get(codedIn.readInt32()); + } else { + String className = context.deserialize(codedIn); + try { + return Class.forName(className); + } catch (ClassNotFoundException e) { + throw new SerializationException("Couldn't find class for " + className, e); + } } } + + private static final ImmutableBiMap<Class<?>, Integer> PRIMITIVE_CLASS_INDEX_MAP = + ImmutableBiMap.<Class<?>, Integer>builder() + .put(byte.class, 1) + .put(short.class, 2) + .put(int.class, 3) + .put(long.class, 4) + .put(char.class, 5) + .put(float.class, 6) + .put(double.class, 7) + .put(boolean.class, 8) + .put(void.class, 9) + .build(); } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/MethodCodec.java b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/MethodCodec.java new file mode 100644 index 0000000000..5fc68d5db4 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/MethodCodec.java @@ -0,0 +1,65 @@ +// 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.protobuf.CodedInputStream; +import com.google.protobuf.CodedOutputStream; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.Arrays; + +/** {@link ObjectCodec} for {@link Method}. */ +class MethodCodec implements ObjectCodec<Method> { + @Override + public Class<Method> getEncodedClass() { + return Method.class; + } + + @Override + public void serialize(SerializationContext context, Method obj, CodedOutputStream codedOut) + throws SerializationException, IOException { + context.serialize(obj.getDeclaringClass(), codedOut); + context.serialize(obj.getName(), codedOut); + Class<?>[] parameterTypes = obj.getParameterTypes(); + codedOut.writeInt32NoTag(parameterTypes.length); + for (Class<?> parameter : parameterTypes) { + context.serialize(parameter, codedOut); + } + } + + @Override + public Method deserialize(DeserializationContext context, CodedInputStream codedIn) + throws SerializationException, IOException { + Class<?> clazz = context.deserialize(codedIn); + String name = context.deserialize(codedIn); + + Class<?>[] parameters = new Class<?>[codedIn.readInt32()]; + for (int i = 0; i < parameters.length; i++) { + parameters[i] = context.deserialize(codedIn); + } + try { + return clazz.getDeclaredMethod(name, parameters); + } catch (NoSuchMethodException e) { + throw new SerializationException( + "Couldn't get method " + + name + + " in " + + clazz + + " with parameters " + + Arrays.toString(parameters), + e); + } + } +} diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/serialization/ClassCodecTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/ClassCodecTest.java new file mode 100644 index 0000000000..16a0d2df7e --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/ClassCodecTest.java @@ -0,0 +1,30 @@ +// 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.devtools.build.lib.skyframe.serialization.testutils.SerializationTester; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link ClassCodec}. */ +@RunWith(JUnit4.class) +public class ClassCodecTest { + @Test + public void smoke() throws Exception { + new SerializationTester(String.class, Object.class, Class.class, int.class, boolean.class) + .runTests(); + } +} diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/serialization/MethodCodecTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/MethodCodecTest.java new file mode 100644 index 0000000000..0874331042 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/MethodCodecTest.java @@ -0,0 +1,37 @@ +// 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.ImmutableList; +import com.google.devtools.build.lib.skyframe.serialization.testutils.SerializationTester; +import java.lang.reflect.Method; +import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link MethodCodec}. */ +@RunWith(JUnit4.class) +public class MethodCodecTest { + @Test + public void smoke() throws Exception { + new SerializationTester( + ImmutableList.<Method>builder() + .add(String.class.getMethods()) + .add(List.class.getMethods()) + .build()) + .runTests(); + } +} |