Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP7:Update
protobuf.26315
protobuf-51026d922970e06475f005b39287963594134b...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File protobuf-51026d922970e06475f005b39287963594134b96.patch of Package protobuf.26315
From 51026d922970e06475f005b39287963594134b96 Mon Sep 17 00:00:00 2001 From: Hao Nguyen <haon@google.com> Date: Wed, 26 Jun 2019 11:01:34 -0700 Subject: [PATCH] Down integrate to GitHub --- java/core/src/main/java/com/google/protobuf/BooleanArrayList.java | 19 java/core/src/main/java/com/google/protobuf/CodedInputStream.java | 4 java/core/src/main/java/com/google/protobuf/DiscardUnknownFieldsParser.java | 2 java/core/src/main/java/com/google/protobuf/DoubleArrayList.java | 19 java/core/src/main/java/com/google/protobuf/FloatArrayList.java | 19 java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java | 662 ++++++++-- java/core/src/main/java/com/google/protobuf/IntArrayList.java | 19 java/core/src/main/java/com/google/protobuf/LongArrayList.java | 19 java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java | 104 + java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java | 37 java/core/src/test/java/com/google/protobuf/TestUtil.java | 2 src/google/protobuf/compiler/java/java_file.cc | 2 12 files changed, 744 insertions(+), 164 deletions(-) --- a/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java @@ -46,7 +46,6 @@ final class BooleanArrayList extends Abs implements BooleanList, RandomAccess, PrimitiveNonBoxingCollection { private static final BooleanArrayList EMPTY_LIST = new BooleanArrayList(new boolean[0], 0); - static { EMPTY_LIST.makeImmutable(); } @@ -161,6 +160,12 @@ final class BooleanArrayList extends Abs } @Override + public boolean add(Boolean element) { + addBoolean(element); + return true; + } + + @Override public void add(int index, Boolean element) { addBoolean(index, element); } @@ -168,7 +173,17 @@ final class BooleanArrayList extends Abs /** Like {@link #add(Boolean)} but more efficient in that it doesn't box the element. */ @Override public void addBoolean(boolean element) { - addBoolean(size, element); + ensureIsMutable(); + if (size == array.length) { + // Resize to 1.5x the size + int length = ((size * 3) / 2) + 1; + boolean[] newArray = new boolean[length]; + + System.arraycopy(array, 0, newArray, 0, size); + array = newArray; + } + + array[size++] = element; } /** Like {@link #add(int, Boolean)} but more efficient in that it doesn't box the element. */ --- a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java +++ b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java @@ -483,7 +483,9 @@ public abstract class CodedInputStream { /** * Returns true if the stream has reached the end of the input. This is the case if either the end * of the underlying input source has been reached or if the stream has reached a limit created - * using {@link #pushLimit(int)}. + * using {@link #pushLimit(int)}. This function may get blocked when using StreamDecoder as it + * invokes {@link #StreamDecoder.tryRefillBuffer(int)} in this function which will try to read + * bytes from input. */ public abstract boolean isAtEnd() throws IOException; --- a/java/core/src/main/java/com/google/protobuf/DiscardUnknownFieldsParser.java +++ b/java/core/src/main/java/com/google/protobuf/DiscardUnknownFieldsParser.java @@ -34,7 +34,7 @@ package com.google.protobuf; public final class DiscardUnknownFieldsParser { /** - * Warps a given {@link Parser} into a new {@link Parser} that discards unknown fields during + * Wraps a given {@link Parser} into a new {@link Parser} that discards unknown fields during * parsing. * * <p>Usage example: --- a/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java @@ -46,7 +46,6 @@ final class DoubleArrayList extends Abst implements DoubleList, RandomAccess, PrimitiveNonBoxingCollection { private static final DoubleArrayList EMPTY_LIST = new DoubleArrayList(new double[0], 0); - static { EMPTY_LIST.makeImmutable(); } @@ -161,6 +160,12 @@ final class DoubleArrayList extends Abst } @Override + public boolean add(Double element) { + addDouble(element); + return true; + } + + @Override public void add(int index, Double element) { addDouble(index, element); } @@ -168,7 +173,17 @@ final class DoubleArrayList extends Abst /** Like {@link #add(Double)} but more efficient in that it doesn't box the element. */ @Override public void addDouble(double element) { - addDouble(size, element); + ensureIsMutable(); + if (size == array.length) { + // Resize to 1.5x the size + int length = ((size * 3) / 2) + 1; + double[] newArray = new double[length]; + + System.arraycopy(array, 0, newArray, 0, size); + array = newArray; + } + + array[size++] = element; } /** Like {@link #add(int, Double)} but more efficient in that it doesn't box the element. */ --- a/java/core/src/main/java/com/google/protobuf/FloatArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/FloatArrayList.java @@ -46,7 +46,6 @@ final class FloatArrayList extends Abstr implements FloatList, RandomAccess, PrimitiveNonBoxingCollection { private static final FloatArrayList EMPTY_LIST = new FloatArrayList(new float[0], 0); - static { EMPTY_LIST.makeImmutable(); } @@ -160,6 +159,12 @@ final class FloatArrayList extends Abstr } @Override + public boolean add(Float element) { + addFloat(element); + return true; + } + + @Override public void add(int index, Float element) { addFloat(index, element); } @@ -167,7 +172,17 @@ final class FloatArrayList extends Abstr /** Like {@link #add(Float)} but more efficient in that it doesn't box the element. */ @Override public void addFloat(float element) { - addFloat(size, element); + ensureIsMutable(); + if (size == array.length) { + // Resize to 1.5x the size + int length = ((size * 3) / 2) + 1; + float[] newArray = new float[length]; + + System.arraycopy(array, 0, newArray, 0, size); + array = newArray; + } + + array[size++] = element; } /** Like {@link #add(int, Float)} but more efficient in that it doesn't box the element. */ --- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java +++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java @@ -58,6 +58,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.ObjectStreamException; import java.io.Serializable; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; @@ -79,6 +81,12 @@ import java.util.TreeMap; public abstract class GeneratedMessageV3 extends AbstractMessage implements Serializable { private static final long serialVersionUID = 1L; + // Whether to use reflection for FieldAccessor + private static boolean forTestUseReflection = false; + + static void setForTestUseReflection(boolean useReflection) { + forTestUseReflection = useReflection; + } /** * For testing. Allows a test to disable the optimization that avoids using @@ -105,13 +113,20 @@ public abstract class GeneratedMessageV3 } /** - * For testing. Allows a test to disable the optimization that avoids using - * field builders for nested messages until they are requested. By disabling - * this optimization, existing tests can be reused to test the field builders. - * See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}. + * @see #setAlwaysUseFieldBuildersForTesting(boolean) */ static void enableAlwaysUseFieldBuildersForTesting() { - alwaysUseFieldBuilders = true; + setAlwaysUseFieldBuildersForTesting(true); + } + + /** + * For testing. Allows a test to disable/re-enable the optimization that avoids + * using field builders for nested messages until they are requested. By disabling + * this optimization, existing tests can be reused to test the field builders. + * See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}. + */ + static void setAlwaysUseFieldBuildersForTesting(boolean useBuilders) { + alwaysUseFieldBuilders = useBuilders; } /** @@ -1795,6 +1810,22 @@ public abstract class GeneratedMessageV3 } } + /** Calls invoke and throws a RuntimeException if it fails. */ + private static RuntimeException handleException(Throwable e) { + if (e instanceof ClassCastException) { + // Reflection throws a bad param type as an IllegalArgumentException, whereas MethodHandle + // throws it as a ClassCastException; convert for backwards compatibility + throw new IllegalArgumentException(e); + } else if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } else if (e instanceof Error) { + throw (Error) e; + } else { + throw new RuntimeException( + "Unexpected exception thrown by generated accessor method.", e); + } + } + /** * Gets the map field with the given field number. This method should be * overridden in the generated message class if the message contains map @@ -2041,61 +2072,250 @@ public abstract class GeneratedMessageV3 // --------------------------------------------------------------- private static class SingularFieldAccessor implements FieldAccessor { + private interface MethodInvoker { + Object get(final GeneratedMessageV3 message); + + Object get(GeneratedMessageV3.Builder<?> builder); + + int getOneofFieldNumber(final GeneratedMessageV3 message); + + int getOneofFieldNumber(final GeneratedMessageV3.Builder<?> builder); + + void set(final GeneratedMessageV3.Builder<?> builder, final Object value); + + boolean has(final GeneratedMessageV3 message); + + boolean has(GeneratedMessageV3.Builder<?> builder); + + void clear(final GeneratedMessageV3.Builder<?> builder); + } + + private static final class ReflectionInvoker implements MethodInvoker { + protected final Method getMethod; + protected final Method getMethodBuilder; + protected final Method setMethod; + protected final Method hasMethod; + protected final Method hasMethodBuilder; + protected final Method clearMethod; + protected final Method caseMethod; + protected final Method caseMethodBuilder; + + ReflectionInvoker( + final FieldDescriptor descriptor, + final String camelCaseName, + final Class<? extends GeneratedMessageV3> messageClass, + final Class<? extends Builder> builderClass, + final String containingOneofCamelCaseName, + boolean isOneofField, + boolean hasHasMethod) { + getMethod = getMethodOrDie(messageClass, "get" + camelCaseName); + getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName); + Class<?> type = getMethod.getReturnType(); + setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type); + hasMethod = hasHasMethod ? getMethodOrDie(messageClass, "has" + camelCaseName) : null; + hasMethodBuilder = + hasHasMethod ? getMethodOrDie(builderClass, "has" + camelCaseName) : null; + clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); + caseMethod = + isOneofField + ? getMethodOrDie(messageClass, "get" + containingOneofCamelCaseName + "Case") + : null; + caseMethodBuilder = + isOneofField + ? getMethodOrDie(builderClass, "get" + containingOneofCamelCaseName + "Case") + : null; + } + + @Override + public Object get(final GeneratedMessageV3 message) { + return invokeOrDie(getMethod, message); + } + + @Override + public Object get(GeneratedMessageV3.Builder<?> builder) { + return invokeOrDie(getMethodBuilder, builder); + } + + @Override + public int getOneofFieldNumber(final GeneratedMessageV3 message) { + return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber(); + } + + @Override + public int getOneofFieldNumber(final GeneratedMessageV3.Builder<?> builder) { + return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber(); + } + + @Override + public void set(final GeneratedMessageV3.Builder<?> builder, final Object value) { + invokeOrDie(setMethod, builder, value); + } + + @Override + public boolean has(final GeneratedMessageV3 message) { + return (Boolean) invokeOrDie(hasMethod, message); + } + + @Override + public boolean has(GeneratedMessageV3.Builder<?> builder) { + return (Boolean) invokeOrDie(hasMethodBuilder, builder); + } + + @Override + public void clear(final GeneratedMessageV3.Builder<?> builder) { + invokeOrDie(clearMethod, builder); + } + } + + private static final class MethodHandleInvoker implements MethodInvoker { + protected final MethodHandle getMethod; + protected final MethodHandle getMethodBuilder; + protected final MethodHandle setMethod; + protected final MethodHandle hasMethod; + protected final MethodHandle hasMethodBuilder; + protected final MethodHandle clearMethod; + protected final MethodHandle caseMethod; + protected final MethodHandle caseMethodBuilder; + + MethodHandleInvoker(ReflectionInvoker accessor) throws IllegalAccessException { + MethodHandles.Lookup lookup = MethodHandles.publicLookup(); + + this.getMethod = lookup.unreflect(accessor.getMethod); + this.getMethodBuilder = lookup.unreflect(accessor.getMethodBuilder); + this.setMethod = lookup.unreflect(accessor.setMethod); + this.hasMethod = + (accessor.hasMethod != null) ? lookup.unreflect(accessor.hasMethod) : null; + this.hasMethodBuilder = (accessor.hasMethodBuilder != null) + ? lookup.unreflect(accessor.hasMethodBuilder) : null; + this.clearMethod = lookup.unreflect(accessor.clearMethod); + this.caseMethod = + (accessor.caseMethod != null) ? lookup.unreflect(accessor.caseMethod) : null; + this.caseMethodBuilder = (accessor.caseMethodBuilder != null) + ? lookup.unreflect(accessor.caseMethodBuilder) : null; + } + + @Override + public Object get(final GeneratedMessageV3 message) { + try { + return getMethod.invoke(message); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public Object get(GeneratedMessageV3.Builder<?> builder) { + try { + return getMethodBuilder.invoke(builder); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public int getOneofFieldNumber(final GeneratedMessageV3 message) { + try { + return ((Internal.EnumLite) caseMethod.invoke(message)).getNumber(); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public int getOneofFieldNumber(final GeneratedMessageV3.Builder<?> builder) { + try { + return ((Internal.EnumLite) caseMethodBuilder.invoke(builder)).getNumber(); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void set(final GeneratedMessageV3.Builder<?> builder, final Object value) { + try { + setMethod.invoke(builder, value); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public boolean has(final GeneratedMessageV3 message) { + try { + return (Boolean) hasMethod.invoke(message); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public boolean has(GeneratedMessageV3.Builder<?> builder) { + try { + return (Boolean) hasMethodBuilder.invoke(builder); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void clear(final GeneratedMessageV3.Builder<?> builder) { + try { + clearMethod.invoke(builder); + } catch (Throwable e) { + throw handleException(e); + } + } + } + SingularFieldAccessor( final FieldDescriptor descriptor, final String camelCaseName, final Class<? extends GeneratedMessageV3> messageClass, final Class<? extends Builder> builderClass, final String containingOneofCamelCaseName) { - field = descriptor; isOneofField = descriptor.getContainingOneof() != null; hasHasMethod = supportFieldPresence(descriptor.getFile()) || (!isOneofField && descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE); - getMethod = getMethodOrDie(messageClass, "get" + camelCaseName); - getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName); - type = getMethod.getReturnType(); - setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type); - hasMethod = - hasHasMethod ? getMethodOrDie(messageClass, "has" + camelCaseName) : null; - hasMethodBuilder = - hasHasMethod ? getMethodOrDie(builderClass, "has" + camelCaseName) : null; - clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); - caseMethod = isOneofField ? getMethodOrDie( - messageClass, "get" + containingOneofCamelCaseName + "Case") : null; - caseMethodBuilder = isOneofField ? getMethodOrDie( - builderClass, "get" + containingOneofCamelCaseName + "Case") : null; + ReflectionInvoker reflectionInvoker = + new ReflectionInvoker( + descriptor, + camelCaseName, + messageClass, + builderClass, + containingOneofCamelCaseName, + isOneofField, + hasHasMethod); + field = descriptor; + type = reflectionInvoker.getMethod.getReturnType(); + invoker = tryGetMethodHandleInvoke(reflectionInvoker); + } + + static MethodInvoker tryGetMethodHandleInvoke(ReflectionInvoker accessor) { + if (forTestUseReflection) { + return accessor; + } + try { + return new MethodHandleInvoker(accessor); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } } // Note: We use Java reflection to call public methods rather than // access private fields directly as this avoids runtime security // checks. protected final Class<?> type; - protected final Method getMethod; - protected final Method getMethodBuilder; - protected final Method setMethod; - protected final Method hasMethod; - protected final Method hasMethodBuilder; - protected final Method clearMethod; - protected final Method caseMethod; - protected final Method caseMethodBuilder; protected final FieldDescriptor field; protected final boolean isOneofField; protected final boolean hasHasMethod; - - private int getOneofFieldNumber(final GeneratedMessageV3 message) { - return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber(); - } - - private int getOneofFieldNumber(final GeneratedMessageV3.Builder builder) { - return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber(); - } + protected final MethodInvoker invoker; @Override public Object get(final GeneratedMessageV3 message) { - return invokeOrDie(getMethod, message); + return invoker.get(message); } @Override public Object get(GeneratedMessageV3.Builder builder) { - return invokeOrDie(getMethodBuilder, builder); + return invoker.get(builder); } @Override public Object getRaw(final GeneratedMessageV3 message) { @@ -2107,134 +2327,324 @@ public abstract class GeneratedMessageV3 } @Override public void set(final Builder builder, final Object value) { - invokeOrDie(setMethod, builder, value); + invoker.set(builder, value); } @Override public Object getRepeated(final GeneratedMessageV3 message, final int index) { - throw new UnsupportedOperationException( - "getRepeatedField() called on a singular field."); + throw new UnsupportedOperationException("getRepeatedField() called on a singular field."); } @Override public Object getRepeatedRaw(final GeneratedMessageV3 message, final int index) { throw new UnsupportedOperationException( - "getRepeatedFieldRaw() called on a singular field."); + "getRepeatedFieldRaw() called on a singular field."); } @Override public Object getRepeated(GeneratedMessageV3.Builder builder, int index) { - throw new UnsupportedOperationException( - "getRepeatedField() called on a singular field."); + throw new UnsupportedOperationException("getRepeatedField() called on a singular field."); } @Override public Object getRepeatedRaw(GeneratedMessageV3.Builder builder, int index) { throw new UnsupportedOperationException( - "getRepeatedFieldRaw() called on a singular field."); + "getRepeatedFieldRaw() called on a singular field."); } @Override public void setRepeated(final Builder builder, final int index, final Object value) { - throw new UnsupportedOperationException( - "setRepeatedField() called on a singular field."); + throw new UnsupportedOperationException("setRepeatedField() called on a singular field."); } @Override public void addRepeated(final Builder builder, final Object value) { - throw new UnsupportedOperationException( - "addRepeatedField() called on a singular field."); + throw new UnsupportedOperationException("addRepeatedField() called on a singular field."); } @Override public boolean has(final GeneratedMessageV3 message) { if (!hasHasMethod) { if (isOneofField) { - return getOneofFieldNumber(message) == field.getNumber(); + return invoker.getOneofFieldNumber(message) == field.getNumber(); } return !get(message).equals(field.getDefaultValue()); } - return (Boolean) invokeOrDie(hasMethod, message); + return invoker.has(message); } @Override public boolean has(GeneratedMessageV3.Builder builder) { if (!hasHasMethod) { if (isOneofField) { - return getOneofFieldNumber(builder) == field.getNumber(); + return invoker.getOneofFieldNumber(builder) == field.getNumber(); } return !get(builder).equals(field.getDefaultValue()); } - return (Boolean) invokeOrDie(hasMethodBuilder, builder); + return invoker.has(builder); } @Override public int getRepeatedCount(final GeneratedMessageV3 message) { throw new UnsupportedOperationException( - "getRepeatedFieldSize() called on a singular field."); + "getRepeatedFieldSize() called on a singular field."); } @Override public int getRepeatedCount(GeneratedMessageV3.Builder builder) { throw new UnsupportedOperationException( - "getRepeatedFieldSize() called on a singular field."); + "getRepeatedFieldSize() called on a singular field."); } @Override public void clear(final Builder builder) { - invokeOrDie(clearMethod, builder); + invoker.clear(builder); } @Override public Message.Builder newBuilder() { throw new UnsupportedOperationException( - "newBuilderForField() called on a non-Message type."); + "newBuilderForField() called on a non-Message type."); } @Override public Message.Builder getBuilder(GeneratedMessageV3.Builder builder) { - throw new UnsupportedOperationException( - "getFieldBuilder() called on a non-Message type."); + throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type."); } @Override public Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder, int index) { throw new UnsupportedOperationException( - "getRepeatedFieldBuilder() called on a non-Message type."); + "getRepeatedFieldBuilder() called on a non-Message type."); } } private static class RepeatedFieldAccessor implements FieldAccessor { + interface MethodInvoker { + public Object get(final GeneratedMessageV3 message); + + public Object get(GeneratedMessageV3.Builder<?> builder); + + Object getRepeated(final GeneratedMessageV3 message, final int index); + + Object getRepeated(GeneratedMessageV3.Builder<?> builder, int index); + + void setRepeated( + final GeneratedMessageV3.Builder<?> builder, final int index, final Object value); + + void addRepeated(final GeneratedMessageV3.Builder<?> builder, final Object value); + + int getRepeatedCount(final GeneratedMessageV3 message); + + int getRepeatedCount(GeneratedMessageV3.Builder<?> builder); + + void clear(final GeneratedMessageV3.Builder<?> builder); + } + + private static final class ReflectionInvoker implements MethodInvoker { + protected final Method getMethod; + protected final Method getMethodBuilder; + protected final Method getRepeatedMethod; + protected final Method getRepeatedMethodBuilder; + protected final Method setRepeatedMethod; + protected final Method addRepeatedMethod; + protected final Method getCountMethod; + protected final Method getCountMethodBuilder; + protected final Method clearMethod; + + ReflectionInvoker( + final FieldDescriptor descriptor, + final String camelCaseName, + final Class<? extends GeneratedMessageV3> messageClass, + final Class<? extends Builder> builderClass) { + getMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "List"); + getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "List"); + getRepeatedMethod = getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE); + getRepeatedMethodBuilder = + getMethodOrDie(builderClass, "get" + camelCaseName, Integer.TYPE); + Class<?> type = getRepeatedMethod.getReturnType(); + setRepeatedMethod = + getMethodOrDie(builderClass, "set" + camelCaseName, Integer.TYPE, type); + addRepeatedMethod = getMethodOrDie(builderClass, "add" + camelCaseName, type); + getCountMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Count"); + getCountMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Count"); + clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); + } + + @Override + public Object get(final GeneratedMessageV3 message) { + return invokeOrDie(getMethod, message); + } + + @Override + public Object get(GeneratedMessageV3.Builder<?> builder) { + return invokeOrDie(getMethodBuilder, builder); + } + + @Override + public Object getRepeated( + final GeneratedMessageV3 message, final int index) { + return invokeOrDie(getRepeatedMethod, message, index); + } + + @Override + public Object getRepeated(GeneratedMessageV3.Builder<?> builder, int index) { + return invokeOrDie(getRepeatedMethodBuilder, builder, index); + } + + @Override + public void setRepeated( + final GeneratedMessageV3.Builder<?> builder, final int index, final Object value) { + invokeOrDie(setRepeatedMethod, builder, index, value); + } + + @Override + public void addRepeated( + final GeneratedMessageV3.Builder<?> builder, final Object value) { + invokeOrDie(addRepeatedMethod, builder, value); + } + + @Override + public int getRepeatedCount(final GeneratedMessageV3 message) { + return (Integer) invokeOrDie(getCountMethod, message); + } + + @Override + public int getRepeatedCount(GeneratedMessageV3.Builder<?> builder) { + return (Integer) invokeOrDie(getCountMethodBuilder, builder); + } + + @Override + public void clear(final GeneratedMessageV3.Builder<?> builder) { + invokeOrDie(clearMethod, builder); + } + } + + private static final class MethodHandleInvoker implements MethodInvoker { + protected final MethodHandle getMethod; + protected final MethodHandle getMethodBuilder; + protected final MethodHandle getRepeatedMethod; + protected final MethodHandle getRepeatedMethodBuilder; + protected final MethodHandle setRepeatedMethod; + protected final MethodHandle addRepeatedMethod; + protected final MethodHandle getCountMethod; + protected final MethodHandle getCountMethodBuilder; + protected final MethodHandle clearMethod; + + MethodHandleInvoker(ReflectionInvoker accessor) throws IllegalAccessException { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + + this.getMethod = lookup.unreflect(accessor.getMethod); + this.getMethodBuilder = lookup.unreflect(accessor.getMethodBuilder); + this.getRepeatedMethod = lookup.unreflect(accessor.getRepeatedMethod); + this.getRepeatedMethodBuilder = lookup.unreflect(accessor.getRepeatedMethodBuilder); + this.setRepeatedMethod = lookup.unreflect(accessor.setRepeatedMethod); + this.addRepeatedMethod = lookup.unreflect(accessor.addRepeatedMethod); + this.getCountMethod = lookup.unreflect(accessor.getCountMethod); + this.getCountMethodBuilder = lookup.unreflect(accessor.getCountMethodBuilder); + this.clearMethod = lookup.unreflect(accessor.clearMethod); + } + + @Override + public Object get(final GeneratedMessageV3 message) { + try { + return getMethod.invoke(message); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public Object get(GeneratedMessageV3.Builder<?> builder) { + try { + return getMethodBuilder.invoke(builder); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public Object getRepeated(final GeneratedMessageV3 message, final int index) { + try { + return getRepeatedMethod.invoke(message, index); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public Object getRepeated(GeneratedMessageV3.Builder<?> builder, int index) { + try { + return getRepeatedMethodBuilder.invoke(builder, index); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setRepeated( + final GeneratedMessageV3.Builder<?> builder, final int index, final Object value) { + try { + setRepeatedMethod.invoke(builder, index, value); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void addRepeated(final GeneratedMessageV3.Builder<?> builder, final Object value) { + try { + addRepeatedMethod.invoke(builder, value); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public int getRepeatedCount(final GeneratedMessageV3 message) { + try { + return (Integer) getCountMethod.invoke(message); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public int getRepeatedCount(GeneratedMessageV3.Builder<?> builder) { + try { + return (Integer) getCountMethodBuilder.invoke(builder); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void clear(final GeneratedMessageV3.Builder<?> builder) { + try { + clearMethod.invoke(builder); + } catch (Throwable e) { + throw handleException(e); + } + } + } + protected final Class type; - protected final Method getMethod; - protected final Method getMethodBuilder; - protected final Method getRepeatedMethod; - protected final Method getRepeatedMethodBuilder; - protected final Method setRepeatedMethod; - protected final Method addRepeatedMethod; - protected final Method getCountMethod; - protected final Method getCountMethodBuilder; - protected final Method clearMethod; + protected final MethodInvoker invoker; RepeatedFieldAccessor( final FieldDescriptor descriptor, final String camelCaseName, final Class<? extends GeneratedMessageV3> messageClass, final Class<? extends Builder> builderClass) { - getMethod = getMethodOrDie(messageClass, - "get" + camelCaseName + "List"); - getMethodBuilder = getMethodOrDie(builderClass, - "get" + camelCaseName + "List"); - getRepeatedMethod = - getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE); - getRepeatedMethodBuilder = - getMethodOrDie(builderClass, "get" + camelCaseName, Integer.TYPE); - type = getRepeatedMethod.getReturnType(); - setRepeatedMethod = - getMethodOrDie(builderClass, "set" + camelCaseName, - Integer.TYPE, type); - addRepeatedMethod = - getMethodOrDie(builderClass, "add" + camelCaseName, type); - getCountMethod = - getMethodOrDie(messageClass, "get" + camelCaseName + "Count"); - getCountMethodBuilder = - getMethodOrDie(builderClass, "get" + camelCaseName + "Count"); + ReflectionInvoker reflectionInvoker = + new ReflectionInvoker(descriptor, camelCaseName, messageClass, builderClass); + type = reflectionInvoker.getRepeatedMethod.getReturnType(); + invoker = tryGetMethodHandleInvoke(reflectionInvoker); + } - clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); + static MethodInvoker tryGetMethodHandleInvoke(ReflectionInvoker accessor) { + if (forTestUseReflection) { + return accessor; + } + try { + return new MethodHandleInvoker(accessor); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } } @Override public Object get(final GeneratedMessageV3 message) { - return invokeOrDie(getMethod, message); + return invoker.get(message); } @Override public Object get(GeneratedMessageV3.Builder builder) { - return invokeOrDie(getMethodBuilder, builder); + return invoker.get(builder); } @Override public Object getRaw(final GeneratedMessageV3 message) { @@ -2257,11 +2667,11 @@ public abstract class GeneratedMessageV3 } @Override public Object getRepeated(final GeneratedMessageV3 message, final int index) { - return invokeOrDie(getRepeatedMethod, message, index); + return invoker.getRepeated(message, index); } @Override public Object getRepeated(GeneratedMessageV3.Builder builder, int index) { - return invokeOrDie(getRepeatedMethodBuilder, builder, index); + return invoker.getRepeated(builder, index); } @Override public Object getRepeatedRaw(GeneratedMessageV3 message, int index) { @@ -2273,48 +2683,45 @@ public abstract class GeneratedMessageV3 } @Override public void setRepeated(final Builder builder, final int index, final Object value) { - invokeOrDie(setRepeatedMethod, builder, index, value); + invoker.setRepeated(builder, index, value); } @Override public void addRepeated(final Builder builder, final Object value) { - invokeOrDie(addRepeatedMethod, builder, value); + invoker.addRepeated(builder, value); } @Override public boolean has(final GeneratedMessageV3 message) { - throw new UnsupportedOperationException( - "hasField() called on a repeated field."); + throw new UnsupportedOperationException("hasField() called on a repeated field."); } @Override public boolean has(GeneratedMessageV3.Builder builder) { - throw new UnsupportedOperationException( - "hasField() called on a repeated field."); + throw new UnsupportedOperationException("hasField() called on a repeated field."); } @Override public int getRepeatedCount(final GeneratedMessageV3 message) { - return (Integer) invokeOrDie(getCountMethod, message); + return invoker.getRepeatedCount(message); } @Override public int getRepeatedCount(GeneratedMessageV3.Builder builder) { - return (Integer) invokeOrDie(getCountMethodBuilder, builder); + return invoker.getRepeatedCount(builder); } @Override public void clear(final Builder builder) { - invokeOrDie(clearMethod, builder); + invoker.clear(builder); } @Override public Message.Builder newBuilder() { throw new UnsupportedOperationException( - "newBuilderForField() called on a non-Message type."); + "newBuilderForField() called on a non-Message type."); } @Override public Message.Builder getBuilder(GeneratedMessageV3.Builder builder) { - throw new UnsupportedOperationException( - "getFieldBuilder() called on a non-Message type."); + throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type."); } @Override public Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder, int index) { throw new UnsupportedOperationException( - "getRepeatedFieldBuilder() called on a non-Message type."); + "getRepeatedFieldBuilder() called on a non-Message type."); } } @@ -2489,10 +2896,8 @@ public abstract class GeneratedMessageV3 enumDescriptor = descriptor.getEnumType(); - valueOfMethod = getMethodOrDie(type, "valueOf", - EnumValueDescriptor.class); - getValueDescriptorMethod = - getMethodOrDie(type, "getValueDescriptor"); + valueOfMethod = getMethodOrDie(type, "valueOf", EnumValueDescriptor.class); + getValueDescriptorMethod = getMethodOrDie(type, "getValueDescriptor"); supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue(); if (supportUnknownEnumValue) { @@ -2554,10 +2959,8 @@ public abstract class GeneratedMessageV3 enumDescriptor = descriptor.getEnumType(); - valueOfMethod = getMethodOrDie(type, "valueOf", - EnumValueDescriptor.class); - getValueDescriptorMethod = - getMethodOrDie(type, "getValueDescriptor"); + valueOfMethod = getMethodOrDie(type, "valueOf", EnumValueDescriptor.class); + getValueDescriptorMethod = getMethodOrDie(type, "getValueDescriptor"); supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue(); if (supportUnknownEnumValue) { @@ -2605,35 +3008,31 @@ public abstract class GeneratedMessageV3 } @Override - public Object getRepeated(final GeneratedMessageV3 message, - final int index) { + public Object getRepeated(final GeneratedMessageV3 message, final int index) { if (supportUnknownEnumValue) { int value = (Integer) invokeOrDie(getRepeatedValueMethod, message, index); return enumDescriptor.findValueByNumberCreatingIfUnknown(value); } - return invokeOrDie(getValueDescriptorMethod, - super.getRepeated(message, index)); + return invokeOrDie(getValueDescriptorMethod, super.getRepeated(message, index)); } + @Override - public Object getRepeated(final GeneratedMessageV3.Builder builder, - final int index) { + public Object getRepeated(final GeneratedMessageV3.Builder builder, final int index) { if (supportUnknownEnumValue) { int value = (Integer) invokeOrDie(getRepeatedValueMethodBuilder, builder, index); return enumDescriptor.findValueByNumberCreatingIfUnknown(value); } - return invokeOrDie(getValueDescriptorMethod, - super.getRepeated(builder, index)); + return invokeOrDie(getValueDescriptorMethod, super.getRepeated(builder, index)); } + @Override - public void setRepeated(final Builder builder, - final int index, final Object value) { + public void setRepeated(final Builder builder, final int index, final Object value) { if (supportUnknownEnumValue) { invokeOrDie(setRepeatedValueMethod, builder, index, ((EnumValueDescriptor) value).getNumber()); return; } - super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null, - value)); + super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null, value)); } @Override public void addRepeated(final Builder builder, final Object value) { @@ -2729,7 +3128,8 @@ public abstract class GeneratedMessageV3 // DynamicMessage -- we should accept it. In this case we can make // a copy of the message. return ((Message.Builder) invokeOrDie(newBuilderMethod, null)) - .mergeFrom((Message) value).buildPartial(); + .mergeFrom((Message) value) + .buildPartial(); } } @@ -2772,13 +3172,13 @@ public abstract class GeneratedMessageV3 // DynamicMessage -- we should accept it. In this case we can make // a copy of the message. return ((Message.Builder) invokeOrDie(newBuilderMethod, null)) - .mergeFrom((Message) value).build(); + .mergeFrom((Message) value) + .build(); } } @Override - public void setRepeated(final Builder builder, - final int index, final Object value) { + public void setRepeated(final Builder builder, final int index, final Object value) { super.setRepeated(builder, index, coerceType(value)); } @Override @@ -2809,12 +3209,10 @@ public abstract class GeneratedMessageV3 } /** - * Checks that the {@link Extension} is non-Lite and returns it as a - * {@link GeneratedExtension}. + * Checks that the {@link Extension} is non-Lite and returns it as a {@link GeneratedExtension}. */ private static <MessageType extends ExtendableMessage<MessageType>, T> - Extension<MessageType, T> checkNotLite( - ExtensionLite<MessageType, T> extension) { + Extension<MessageType, T> checkNotLite(ExtensionLite<MessageType, T> extension) { if (extension.isLite()) { throw new IllegalArgumentException("Expected non-lite extension."); } --- a/java/core/src/main/java/com/google/protobuf/IntArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/IntArrayList.java @@ -46,7 +46,6 @@ final class IntArrayList extends Abstrac implements IntList, RandomAccess, PrimitiveNonBoxingCollection { private static final IntArrayList EMPTY_LIST = new IntArrayList(new int[0], 0); - static { EMPTY_LIST.makeImmutable(); } @@ -160,6 +159,12 @@ final class IntArrayList extends Abstrac } @Override + public boolean add(Integer element) { + addInt(element); + return true; + } + + @Override public void add(int index, Integer element) { addInt(index, element); } @@ -167,7 +172,17 @@ final class IntArrayList extends Abstrac /** Like {@link #add(Integer)} but more efficient in that it doesn't box the element. */ @Override public void addInt(int element) { - addInt(size, element); + ensureIsMutable(); + if (size == array.length) { + // Resize to 1.5x the size + int length = ((size * 3) / 2) + 1; + int[] newArray = new int[length]; + + System.arraycopy(array, 0, newArray, 0, size); + array = newArray; + } + + array[size++] = element; } /** Like {@link #add(int, Integer)} but more efficient in that it doesn't box the element. */ --- a/java/core/src/main/java/com/google/protobuf/LongArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/LongArrayList.java @@ -46,7 +46,6 @@ final class LongArrayList extends Abstra implements LongList, RandomAccess, PrimitiveNonBoxingCollection { private static final LongArrayList EMPTY_LIST = new LongArrayList(new long[0], 0); - static { EMPTY_LIST.makeImmutable(); } @@ -160,6 +159,12 @@ final class LongArrayList extends Abstra } @Override + public boolean add(Long element) { + addLong(element); + return true; + } + + @Override public void add(int index, Long element) { addLong(index, element); } @@ -167,7 +172,17 @@ final class LongArrayList extends Abstra /** Like {@link #add(Long)} but more efficient in that it doesn't box the element. */ @Override public void addLong(long element) { - addLong(size, element); + ensureIsMutable(); + if (size == array.length) { + // Resize to 1.5x the size + int length = ((size * 3) / 2) + 1; + long[] newArray = new long[length]; + + System.arraycopy(array, 0, newArray, 0, size); + array = newArray; + } + + array[size++] = element; } /** Like {@link #add(int, Long)} but more efficient in that it doesn't box the element. */ --- a/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java @@ -31,14 +31,13 @@ package com.google.protobuf; import com.google.protobuf.Internal.ProtobufList; -import java.util.ArrayList; -import java.util.List; +import java.util.Arrays; /** Implements {@link ProtobufList} for non-primitive and {@link String} types. */ final class ProtobufArrayList<E> extends AbstractProtobufList<E> { private static final ProtobufArrayList<Object> EMPTY_LIST = - new ProtobufArrayList<Object>(new ArrayList<Object>(0)); + new ProtobufArrayList<Object>(new Object[0], 0); static { EMPTY_LIST.makeImmutable(); @@ -49,56 +48,127 @@ final class ProtobufArrayList<E> extends return (ProtobufArrayList<E>) EMPTY_LIST; } - private final List<E> list; + private E[] array; + private int size; + @SuppressWarnings("unchecked") ProtobufArrayList() { - this(new ArrayList<E>(DEFAULT_CAPACITY)); + this((E[]) new Object[DEFAULT_CAPACITY], 0); } - private ProtobufArrayList(List<E> list) { - this.list = list; + private ProtobufArrayList(E[] array, int size) { + this.array = array; + this.size = size; } @Override public ProtobufArrayList<E> mutableCopyWithCapacity(int capacity) { - if (capacity < size()) { + if (capacity < size) { throw new IllegalArgumentException(); } - List<E> newList = new ArrayList<E>(capacity); - newList.addAll(list); - return new ProtobufArrayList<E>(newList); + + E[] newArray = Arrays.copyOf(array, capacity); + + return new ProtobufArrayList<E>(newArray, size); + } + + @Override + public boolean add(E element) { + ensureIsMutable(); + + if (size == array.length) { + // Resize to 1.5x the size + int length = ((size * 3) / 2) + 1; + E[] newArray = Arrays.copyOf(array, length); + + array = newArray; + } + + array[size++] = element; + modCount++; + + return true; } @Override public void add(int index, E element) { ensureIsMutable(); - list.add(index, element); + + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); + } + + if (size < array.length) { + // Shift everything over to make room + System.arraycopy(array, index, array, index + 1, size - index); + } else { + // Resize to 1.5x the size + int length = ((size * 3) / 2) + 1; + E[] newArray = createArray(length); + + // Copy the first part directly + System.arraycopy(array, 0, newArray, 0, index); + + // Copy the rest shifted over by one to make room + System.arraycopy(array, index, newArray, index + 1, size - index); + array = newArray; + } + + array[index] = element; + size++; modCount++; } @Override public E get(int index) { - return list.get(index); + ensureIndexInRange(index); + return array[index]; } @Override public E remove(int index) { ensureIsMutable(); - E toReturn = list.remove(index); + ensureIndexInRange(index); + + E value = array[index]; + if (index < size - 1) { + System.arraycopy(array, index + 1, array, index, size - index - 1); + } + + size--; modCount++; - return toReturn; + return value; } @Override public E set(int index, E element) { ensureIsMutable(); - E toReturn = list.set(index, element); + ensureIndexInRange(index); + + E toReturn = array[index]; + array[index] = element; + modCount++; return toReturn; } @Override public int size() { - return list.size(); + return size; + } + + @SuppressWarnings("unchecked") + private static <E> E[] createArray(int capacity) { + return (E[]) new Object[capacity]; + } + + private void ensureIndexInRange(int index) { + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); + } + } + + private String makeOutOfBoundsExceptionMessage(int index) { + return "Index:" + index + ", Size:" + size; } } --- a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java +++ b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java @@ -69,6 +69,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; import junit.framework.TestCase; +import junit.framework.TestSuite; /** * Unit test for generated messages and generated code. See also {@link MessageTest}, which tests @@ -80,6 +81,40 @@ public class GeneratedMessageTest extend TestUtil.ReflectionTester reflectionTester = new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null); + public static TestSuite suite() { + TestSuite suite = new TestSuite(); + suite.addTestSuite(ReflectionTest.class); + suite.addTestSuite(FastInvokeTest.class); + return suite; + } + + public static class ReflectionTest extends GeneratedMessageTest { + public ReflectionTest() { + super(true); + } + } + + public static class FastInvokeTest extends GeneratedMessageTest { + public FastInvokeTest() { + super(false); + } + } + + private final boolean useReflection; + + GeneratedMessageTest(boolean useReflection) { + this.useReflection = useReflection; + } + + @Override public void setUp() { + GeneratedMessageV3.setForTestUseReflection(useReflection); + } + + @Override public void tearDown() { + GeneratedMessageV3.setForTestUseReflection(false); + GeneratedMessageV3.setAlwaysUseFieldBuildersForTesting(false); + } + public void testDefaultInstance() throws Exception { assertSame( TestAllTypes.getDefaultInstance(), @@ -937,7 +972,7 @@ public class GeneratedMessageTest extend } public void testInvalidations() throws Exception { - GeneratedMessage.enableAlwaysUseFieldBuildersForTesting(); + GeneratedMessageV3.setAlwaysUseFieldBuildersForTesting(true); TestAllTypes.NestedMessage nestedMessage1 = TestAllTypes.NestedMessage.newBuilder().build(); TestAllTypes.NestedMessage nestedMessage2 = TestAllTypes.NestedMessage.newBuilder().build(); --- a/java/core/src/test/java/com/google/protobuf/TestUtil.java +++ b/java/core/src/test/java/com/google/protobuf/TestUtil.java @@ -2776,7 +2776,7 @@ public final class TestUtil { } /** Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes. */ - private Descriptors.FieldDescriptor f(String name) { + Descriptors.FieldDescriptor f(String name) { Descriptors.FieldDescriptor result; if (extensionRegistry == null) { result = baseDescriptor.findFieldByName(name); --- a/src/google/protobuf/compiler/java/java_file.cc +++ b/src/google/protobuf/compiler/java/java_file.cc @@ -521,7 +521,7 @@ void FileGenerator::GenerateDescriptorIn // we want the mutable code to be independent from the immutable code // at compile time. It is required to implement dual-compile for // mutable and immutable API in blaze. - " java.lang.Class immutableClass = java.lang.Class.forName(\n" + " java.lang.Class<?> immutableClass = java.lang.Class.forName(\n" " \"$immutable_classname$\");\n" "} catch (java.lang.ClassNotFoundException e) {\n", "immutable_classname", name_resolver_->GetImmutableClassName(file_));
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor