diff options
Diffstat (limited to 'java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java')
-rw-r--r-- | java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java | 125 |
1 files changed, 96 insertions, 29 deletions
diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java index 7116ae1c..09084646 100644 --- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java +++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java @@ -31,7 +31,6 @@ package com.google.protobuf; import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream; -import com.google.protobuf.GeneratedMessageLite.EqualsVisitor.NotEqualsException; import com.google.protobuf.Internal.BooleanList; import com.google.protobuf.Internal.DoubleList; import com.google.protobuf.Internal.EnumLiteMap; @@ -52,6 +51,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * Lite version of {@link GeneratedMessage}. @@ -62,6 +62,12 @@ public abstract class GeneratedMessageLite< MessageType extends GeneratedMessageLite<MessageType, BuilderType>, BuilderType extends GeneratedMessageLite.Builder<MessageType, BuilderType>> extends AbstractMessageLite<MessageType, BuilderType> { + // BEGIN REGULAR + static final boolean ENABLE_EXPERIMENTAL_RUNTIME_AT_BUILD_TIME = false; + // END REGULAR + // BEGIN EXPERIMENTAL + // static final boolean ENABLE_EXPERIMENTAL_RUNTIME_AT_BUILD_TIME = true; + // END EXPERIMENTAL /** For use by generated code only. Lazily initialized to reduce allocations. */ protected UnknownFieldSetLite unknownFields = UnknownFieldSetLite.getDefaultInstance(); @@ -110,12 +116,19 @@ public abstract class GeneratedMessageLite< if (memoizedHashCode != 0) { return memoizedHashCode; } + // BEGIN EXPERIMENTAL + // memoizedHashCode = Protobuf.getInstance().schemaFor(this).hashCode(this); + // return memoizedHashCode; + // END EXPERIMENTAL + // BEGIN REGULAR HashCodeVisitor visitor = new HashCodeVisitor(); visit(visitor, (MessageType) this); memoizedHashCode = visitor.hashCode; return memoizedHashCode; + // END REGULAR } + // BEGIN REGULAR @SuppressWarnings("unchecked") // Guaranteed by runtime int hashCode(HashCodeVisitor visitor) { if (memoizedHashCode == 0) { @@ -127,6 +140,7 @@ public abstract class GeneratedMessageLite< } return memoizedHashCode; } + // END REGULAR @SuppressWarnings("unchecked") // Guaranteed by isInstance + runtime @Override @@ -139,18 +153,22 @@ public abstract class GeneratedMessageLite< return false; } + // BEGIN EXPERIMENTAL + // return Protobuf.getInstance().schemaFor(this).equals(this, (MessageType) other); + // END EXPERIMENTAL + // BEGIN REGULAR try { visit(EqualsVisitor.INSTANCE, (MessageType) other); - } catch (NotEqualsException e) { + } catch (EqualsVisitor.NotEqualsException e) { return false; } return true; + // END REGULAR } - /** - * Same as {@link #equals(Object)} but throws {@code NotEqualsException}. - */ + // BEGIN REGULAR + /** Same as {@link #equals(Object)} but throws {@code NotEqualsException}. */ @SuppressWarnings("unchecked") // Guaranteed by isInstance + runtime boolean equals(EqualsVisitor visitor, MessageLite other) { if (this == other) { @@ -164,14 +182,13 @@ public abstract class GeneratedMessageLite< visit(visitor, (MessageType) other); return true; } + // END REGULAR // The general strategy for unknown fields is to use an UnknownFieldSetLite that is treated as // mutable during the parsing constructor and immutable after. This allows us to avoid // any unnecessary intermediary allocations while reducing the generated code size. - /** - * Lazily initializes unknown fields. - */ + /** Lazily initializes unknown fields. */ private final void ensureUnknownFieldsInitialized() { if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) { unknownFields = UnknownFieldSetLite.newInstance(); @@ -218,9 +235,23 @@ public abstract class GeneratedMessageLite< unknownFields.makeImmutable(); } + protected final < + MessageType extends GeneratedMessageLite<MessageType, BuilderType>, + BuilderType extends GeneratedMessageLite.Builder<MessageType, BuilderType>> + BuilderType createBuilder() { + return (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER); + } + + protected final < + MessageType extends GeneratedMessageLite<MessageType, BuilderType>, + BuilderType extends GeneratedMessageLite.Builder<MessageType, BuilderType>> + BuilderType createBuilder(MessageType prototype) { + return ((BuilderType) createBuilder()).mergeFrom(prototype); + } + @Override public final boolean isInitialized() { - return dynamicMethod(MethodToInvoke.IS_INITIALIZED, Boolean.TRUE) != null; + return isInitialized((MessageType) this, Boolean.TRUE); } @Override @@ -238,9 +269,13 @@ public abstract class GeneratedMessageLite< * For use by generated code only. */ public static enum MethodToInvoke { - // Rely on/modify instance state IS_INITIALIZED, + // BEGIN REGULAR VISIT, + // END REGULAR + // Rely on/modify instance state + GET_MEMOIZED_IS_INITIALIZED, + SET_MEMOIZED_IS_INITIALIZED, MERGE_FROM_STREAM, MAKE_IMMUTABLE, @@ -256,25 +291,30 @@ public abstract class GeneratedMessageLite< * Theses different kinds of operations are required to implement message-level operations for * builders in the runtime. This method bundles those operations to reduce the generated methods * count. + * * <ul> - * <li>{@code MERGE_FROM_STREAM} is parameterized with an {@link CodedInputStream} and - * {@link ExtensionRegistryLite}. It consumes the input stream, parsing the contents into the - * returned protocol buffer. If parsing throws an {@link InvalidProtocolBufferException}, the - * implementation wraps it in a RuntimeException. - * <li>{@code NEW_INSTANCE} returns a new instance of the protocol buffer that has not yet been - * made immutable. See {@code MAKE_IMMUTABLE}. - * <li>{@code IS_INITIALIZED} is parameterized with a {@code Boolean} detailing whether to - * memoize. It returns {@code null} for false and the default instance for true. We optionally - * memoize to support the Builder case, where memoization is not desired. - * <li>{@code NEW_BUILDER} returns a {@code BuilderType} instance. - * <li>{@code VISIT} is parameterized with a {@code Visitor} and a {@code MessageType} and - * recursively iterates through the fields side by side between this and the instance. - * <li>{@code MAKE_IMMUTABLE} sets all internal fields to an immutable state. + * <li>{@code MERGE_FROM_STREAM} is parameterized with an {@link CodedInputStream} and {@link + * ExtensionRegistryLite}. It consumes the input stream, parsing the contents into the + * returned protocol buffer. If parsing throws an {@link InvalidProtocolBufferException}, + * the implementation wraps it in a RuntimeException. + * <li>{@code NEW_INSTANCE} returns a new instance of the protocol buffer that has not yet been + * made immutable. See {@code MAKE_IMMUTABLE}. + * <li>{@code IS_INITIALIZED} returns {@code null} for false and the default instance for true. + * It doesn't use or modify any memoized value. + * <li>{@code GET_MEMOIZED_IS_INITIALIZED} returns the memoized {@code isInitialized} byte + * value. + * <li>{@code SET_MEMOIZED_IS_INITIALIZED} sets the memoized {@code isInitilaized} byte value to + * 1 if the first parameter is not null, or to 0 if the first parameter is null. + * <li>{@code NEW_BUILDER} returns a {@code BuilderType} instance. + * <li>{@code VISIT} is parameterized with a {@code Visitor} and a {@code MessageType} and + * recursively iterates through the fields side by side between this and the instance. + * <li>{@code MAKE_IMMUTABLE} sets all internal fields to an immutable state. * </ul> + * * This method, plus the implementation of the Builder, enables the Builder class to be proguarded * away entirely on Android. - * <p> - * For use by generated code only. + * + * <p>For use by generated code only. */ protected abstract Object dynamicMethod(MethodToInvoke method, Object arg0, Object arg1); @@ -292,14 +332,17 @@ public abstract class GeneratedMessageLite< return dynamicMethod(method, null, null); } + // BEGIN REGULAR void visit(Visitor visitor, MessageType other) { dynamicMethod(MethodToInvoke.VISIT, visitor, other); unknownFields = visitor.visitUnknownFields(unknownFields, other.unknownFields); } + // END REGULAR + + /** - * Merge some unknown fields into the {@link UnknownFieldSetLite} for this - * message. + * Merge some unknown fields into the {@link UnknownFieldSetLite} for this message. * * <p>For use by generated code only. */ @@ -392,7 +435,12 @@ public abstract class GeneratedMessageLite< } private void mergeFromInstance(MessageType dest, MessageType src) { + // BEGIN EXPERIMENTAL + // Protobuf.getInstance().schemaFor(dest).mergeFrom(dest, src); + // END EXPERIMENTAL + // BEGIN REGULAR dest.visit(MergeFromVisitor.INSTANCE, src); + // END REGULAR } @Override @@ -470,11 +518,13 @@ public abstract class GeneratedMessageLite< extensions.mergeFrom(((ExtendableMessage) other).extensions); } + // BEGIN REGULAR @Override final void visit(Visitor visitor, MessageType other) { super.visit(visitor, other); extensions = visitor.visitExtensions(extensions, other.extensions); } + // END REGULAR /** * Parse an unknown field or an extension. For use by generated code only. @@ -487,7 +537,8 @@ public abstract class GeneratedMessageLite< MessageType defaultInstance, CodedInputStream input, ExtensionRegistryLite extensionRegistry, - int tag) throws IOException { + int tag) + throws IOException { int fieldNumber = WireFormat.getTagFieldNumber(tag); // TODO(dweis): How much bytecode would be saved by not requiring the generated code to @@ -1403,7 +1454,21 @@ public abstract class GeneratedMessageLite< */ protected static final <T extends GeneratedMessageLite<T, ?>> boolean isInitialized( T message, boolean shouldMemoize) { - return message.dynamicMethod(MethodToInvoke.IS_INITIALIZED, shouldMemoize) != null; + byte memoizedIsInitialized = + (Byte) message.dynamicMethod(MethodToInvoke.GET_MEMOIZED_IS_INITIALIZED); + if (memoizedIsInitialized == 1) { + return true; + } + if (memoizedIsInitialized == 0) { + return false; + } + boolean isInitialized = + message.dynamicMethod(MethodToInvoke.IS_INITIALIZED, Boolean.FALSE) != null; + if (shouldMemoize) { + message.dynamicMethod( + MethodToInvoke.SET_MEMOIZED_IS_INITIALIZED, isInitialized ? message : null); + } + return isInitialized; } protected static final <T extends GeneratedMessageLite<T, ?>> void makeImmutable(T message) { @@ -1695,6 +1760,7 @@ public abstract class GeneratedMessageLite< return message; } + // BEGIN REGULAR /** * An abstract visitor that the generated code calls into that we use to implement various * features. Fields that are not members of oneofs are always visited. Members of a oneof are only @@ -2380,4 +2446,5 @@ public abstract class GeneratedMessageLite< return mine; } } + // END REGULAR } |